summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2000-05-03 05:50:46 +0000
committerrwatson <rwatson@FreeBSD.org>2000-05-03 05:50:46 +0000
commit51a3d7f35d186fb5758fc6349a7f1ae3b2db7d1e (patch)
tree09a6c5beb0db8a3086ca5e96f9ef9297c5163385
parent058748cefba2fb53e482f50ea4e28f425659ec35 (diff)
downloadFreeBSD-src-51a3d7f35d186fb5758fc6349a7f1ae3b2db7d1e.zip
FreeBSD-src-51a3d7f35d186fb5758fc6349a7f1ae3b2db7d1e.tar.gz
Don't allow VOP_GETEXTATTR to set uio->uio_offset != 0, as we don't
provide locking over extended attribute operations, requiring that individual operations be atomic. Allowing non-zero starting offsets permits applications/etc to put themselves at risk for inconsistent behavior. As VOP_SETEXTATTR already prohibited non-zero write offsets, this makes sense. Suggested by: Andreas Gruenbacher <a.gruenbacher@bestbits.at>
-rw-r--r--sys/ufs/ufs/ufs_extattr.c22
1 files changed, 10 insertions, 12 deletions
diff --git a/sys/ufs/ufs/ufs_extattr.c b/sys/ufs/ufs/ufs_extattr.c
index e5155dd..ae0c0fb 100644
--- a/sys/ufs/ufs/ufs_extattr.c
+++ b/sys/ufs/ufs/ufs_extattr.c
@@ -443,7 +443,7 @@ ufs_extattr_get(struct vnode *vp, char *name, struct uio *uio,
struct mount *mp = vp->v_mount;
struct ufsmount *ump = VFSTOUFS(mp);
struct inode *ip = VTOI(vp);
- off_t base_offset, old_offset, offset;
+ off_t base_offset, offset;
size_t size, old_size;
int error = 0;
@@ -459,10 +459,12 @@ ufs_extattr_get(struct vnode *vp, char *name, struct uio *uio,
return (error);
/*
- * Early rejection of offsets that are invalid
+ * Allow only offsets of zero to encourage the read/replace
+ * extended attribute semantic. Otherwise we can't guarantee
+ * atomicity, as we don't provide locks for extended
+ * attributes.
*/
- if (uio->uio_offset >= attribute->uele_fileheader.uef_size ||
- uio->uio_offset < 0)
+ if (uio->uio_offset != 0)
return (ENXIO);
/*
@@ -529,28 +531,24 @@ ufs_extattr_get(struct vnode *vp, char *name, struct uio *uio,
}
/* allow for offset into the attr data */
- offset = base_offset + sizeof(struct ufs_extattr_header) +
- uio->uio_offset;
+ uio->uio_offset = base_offset + sizeof(struct ufs_extattr_header);
/*
* Figure out maximum to transfer -- use buffer size and local data
* limit.
*/
- size = MIN(uio->uio_resid, ueh.ueh_len - uio->uio_offset);
-
- old_offset = uio->uio_offset;
- uio->uio_offset = offset;
+ size = MIN(uio->uio_resid, ueh.ueh_len);
old_size = uio->uio_resid;
uio->uio_resid = size;
error = VOP_READ(attribute->uele_backing_vnode, uio, 0,
ump->um_extattr.uepm_ucred);
if (error) {
- uio->uio_offset = old_offset;
+ uio->uio_offset = 0;
goto vopunlock_exit;
}
- uio->uio_offset = old_offset;
+ uio->uio_offset = 0;
uio->uio_resid = old_size - (size - uio->uio_resid);
vopunlock_exit:
OpenPOWER on IntegriCloud