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:
parent
86a5a8c251
commit
a7e8b37043
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=59913
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user