1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-14 10:09:48 +00:00

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>
This commit is contained in:
Robert Watson 2000-05-03 05:50:46 +00:00
parent 86a5a8c251
commit a7e8b37043
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=59913

View File

@ -443,7 +443,7 @@ ufs_extattr_get(struct vnode *vp, char *name, struct uio *uio,
struct mount *mp = vp->v_mount; struct mount *mp = vp->v_mount;
struct ufsmount *ump = VFSTOUFS(mp); struct ufsmount *ump = VFSTOUFS(mp);
struct inode *ip = VTOI(vp); struct inode *ip = VTOI(vp);
off_t base_offset, old_offset, offset; off_t base_offset, offset;
size_t size, old_size; size_t size, old_size;
int error = 0; int error = 0;
@ -459,10 +459,12 @@ ufs_extattr_get(struct vnode *vp, char *name, struct uio *uio,
return (error); 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 || if (uio->uio_offset != 0)
uio->uio_offset < 0)
return (ENXIO); return (ENXIO);
/* /*
@ -529,28 +531,24 @@ ufs_extattr_get(struct vnode *vp, char *name, struct uio *uio,
} }
/* allow for offset into the attr data */ /* allow for offset into the attr data */
offset = base_offset + sizeof(struct ufs_extattr_header) + uio->uio_offset = base_offset + sizeof(struct ufs_extattr_header);
uio->uio_offset;
/* /*
* Figure out maximum to transfer -- use buffer size and local data * Figure out maximum to transfer -- use buffer size and local data
* limit. * limit.
*/ */
size = MIN(uio->uio_resid, ueh.ueh_len - uio->uio_offset); size = MIN(uio->uio_resid, ueh.ueh_len);
old_offset = uio->uio_offset;
uio->uio_offset = offset;
old_size = uio->uio_resid; old_size = uio->uio_resid;
uio->uio_resid = size; uio->uio_resid = size;
error = VOP_READ(attribute->uele_backing_vnode, uio, 0, error = VOP_READ(attribute->uele_backing_vnode, uio, 0,
ump->um_extattr.uepm_ucred); ump->um_extattr.uepm_ucred);
if (error) { if (error) {
uio->uio_offset = old_offset; uio->uio_offset = 0;
goto vopunlock_exit; goto vopunlock_exit;
} }
uio->uio_offset = old_offset; uio->uio_offset = 0;
uio->uio_resid = old_size - (size - uio->uio_resid); uio->uio_resid = old_size - (size - uio->uio_resid);
vopunlock_exit: vopunlock_exit: