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
e7a06356c1
commit
4b2e20824b
|
@ -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) &&
|
||||
((!S_ISDIR(ZTOI(zp)->i_mode) &&
|
||||
(zp->z_pflags & (ZFS_READONLY | ZFS_IMMUTABLE))) ||
|
||||
(S_ISDIR(ZTOI(zp)->i_mode) &&
|
||||
(zp->z_pflags & ZFS_IMMUTABLE)))) {
|
||||
(zp->z_pflags & ZFS_IMMUTABLE)) {
|
||||
return (SET_ERROR(EPERM));
|
||||
}
|
||||
|
||||
|
@ -2434,6 +2432,24 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
|
|||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -350,9 +350,11 @@ zfs_write(znode_t *zp, zfs_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) &&
|
||||
(zfs_uio_offset(uio) < zp->z_size))) {
|
||||
ZFS_EXIT(zfsvfs);
|
||||
|
|
Loading…
Reference in New Issue