Intentionally allow ZFS_READONLY in zfs_write
ZFS_READONLY represents the "DOS R/O" attribute. When that flag is set, we should behave as if write access were not granted by anything in the ACL. In particular: We _must_ allow writes after opening the file r/w, then setting the DOS R/O attribute, and writing some more. (Similar to how you can write after fchmod(fd, 0444).) Restore these semantics which were lost on FreeBSD when refactoring zfs_write. To my knowledge Linux does not actually expose this flag, but we'll need it to eventually so I've added the supporting checks. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Ryan Moeller <ryan@iXsystems.com> Closes #11693
This commit is contained in:
parent
df8271301e
commit
cda6fdd500
|
@ -2214,13 +2214,11 @@ zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only check for READONLY on non-directories.
|
* Intentionally allow ZFS_READONLY through here.
|
||||||
|
* See zfs_zaccess_common().
|
||||||
*/
|
*/
|
||||||
if ((v4_mode & WRITE_MASK_DATA) &&
|
if ((v4_mode & WRITE_MASK_DATA) &&
|
||||||
((!S_ISDIR(ZTOI(zp)->i_mode) &&
|
(zp->z_pflags & ZFS_IMMUTABLE)) {
|
||||||
(zp->z_pflags & (ZFS_READONLY | ZFS_IMMUTABLE))) ||
|
|
||||||
(S_ISDIR(ZTOI(zp)->i_mode) &&
|
|
||||||
(zp->z_pflags & ZFS_IMMUTABLE)))) {
|
|
||||||
return (SET_ERROR(EPERM));
|
return (SET_ERROR(EPERM));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2434,6 +2432,24 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: ZFS_READONLY represents the "DOS R/O" attribute.
|
||||||
|
* When that flag is set, we should behave as if write access
|
||||||
|
* were not granted by anything in the ACL. In particular:
|
||||||
|
* We _must_ allow writes after opening the file r/w, then
|
||||||
|
* setting the DOS R/O attribute, and writing some more.
|
||||||
|
* (Similar to how you can write after fchmod(fd, 0444).)
|
||||||
|
*
|
||||||
|
* Therefore ZFS_READONLY is ignored in the dataset check
|
||||||
|
* above, and checked here as if part of the ACL check.
|
||||||
|
* Also note: DOS R/O is ignored for directories.
|
||||||
|
*/
|
||||||
|
if ((v4_mode & WRITE_MASK_DATA) &&
|
||||||
|
S_ISDIR(ZTOI(zp)->i_mode) &&
|
||||||
|
(zp->z_pflags & ZFS_READONLY)) {
|
||||||
|
return (SET_ERROR(EPERM));
|
||||||
|
}
|
||||||
|
|
||||||
return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr));
|
return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -258,9 +258,11 @@ zfs_write(znode_t *zp, uio_t *uio, int ioflag, cred_t *cr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If immutable or not appending then return EPERM
|
* If immutable or not appending then return EPERM.
|
||||||
|
* Intentionally allow ZFS_READONLY through here.
|
||||||
|
* See zfs_zaccess_common()
|
||||||
*/
|
*/
|
||||||
if ((zp->z_pflags & (ZFS_IMMUTABLE | ZFS_READONLY)) ||
|
if ((zp->z_pflags & ZFS_IMMUTABLE) ||
|
||||||
((zp->z_pflags & ZFS_APPENDONLY) && !(ioflag & O_APPEND) &&
|
((zp->z_pflags & ZFS_APPENDONLY) && !(ioflag & O_APPEND) &&
|
||||||
(uio->uio_loffset < zp->z_size))) {
|
(uio->uio_loffset < zp->z_size))) {
|
||||||
ZFS_EXIT(zfsvfs);
|
ZFS_EXIT(zfsvfs);
|
||||||
|
|
Loading…
Reference in New Issue