From cc184fe98b3769dc0b384be024089459ae934575 Mon Sep 17 00:00:00 2001 From: Marc Sladek Date: Wed, 11 Feb 2026 19:30:26 +0100 Subject: [PATCH] Fix `send:raw` permission for send `-w -I` When performing an incremental raw send with intermediates (-w -I), the standard 'send' permission was incorrectly required instead of allowing 'send:raw'. This was due to a strict boolean comparison on the 'rawok' flag in zfs_secpolicy_send() with non-boolean value. This change normalizes the 'rawok' variable to be strictly 0/1 and updates the test suite to properly verify delegated raw send behavior. Introduced-by: https://github.com/openzfs/zfs/pull/17543 Reviewed-by: Alexander Motin Reviewed-by: Brian Behlendorf Signed-off-by: Marc Sladek Closes #18198 Closes #18193 --- module/zfs/zfs_ioctl.c | 6 +++--- .../zfs_send_delegation_user/zfs_send_usertest.ksh | 11 ++++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index c6f7dd596..3bbc9107a 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -685,7 +685,7 @@ zfs_secpolicy_send(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr) dsl_dataset_t *ds; const char *cp; int error; - boolean_t rawok = (zc->zc_flags & 0x8); + boolean_t rawok = !!(zc->zc_flags & 0x8); /* * Generate the current snapshot name from the given objsetid, then @@ -708,7 +708,7 @@ zfs_secpolicy_send(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr) error = zfs_secpolicy_write_perms_ds(zc->zc_name, ds, ZFS_DELEG_PERM_SEND, cr); - if (error != 0 && rawok == B_TRUE) { + if (error != 0 && rawok) { error = zfs_secpolicy_write_perms_ds(zc->zc_name, ds, ZFS_DELEG_PERM_SEND_RAW, cr); } @@ -727,7 +727,7 @@ zfs_secpolicy_send_new(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr) (void) innvl; error = zfs_secpolicy_write_perms(zc->zc_name, ZFS_DELEG_PERM_SEND, cr); - if (error != 0 && rawok == B_TRUE) { + if (error != 0 && rawok) { error = zfs_secpolicy_write_perms(zc->zc_name, ZFS_DELEG_PERM_SEND_RAW, cr); } diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_send_delegation_user/zfs_send_usertest.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_send_delegation_user/zfs_send_usertest.ksh index f62f2b079..ea54a962f 100755 --- a/tests/zfs-tests/tests/functional/cli_user/zfs_send_delegation_user/zfs_send_usertest.ksh +++ b/tests/zfs-tests/tests/functional/cli_user/zfs_send_delegation_user/zfs_send_usertest.ksh @@ -103,13 +103,18 @@ log_must zfs unallow -u $OTHER1 send $TESTPOOL/$TESTFS1 # test new sendraw abilities (send should fail, sendraw should pass) log_mustnot user_run $OTHER1 sh -c "'zfs send $TESTPOOL/$TESTFS1@snap1 | zfs receive -u $TESTPOOL/$TESTFS2/zfsrecv2_user_datastream.$$'" - verify nothing went through +# verify nothing went through if [ -s $TESTPOOL/$TESTFS2/zfsrecv2_user_datastream.$$ ] then log_fail "A zfs recieve was completed in $TESTPOOL/$TESTFS2/zfsrecv2_user_datastream !" fi log_must user_run $OTHER1 sh -c "'zfs send -w $TESTPOOL/$TESTFS1@snap1 | zfs receive -u $TESTPOOL/$TESTFS2/zfsrecv2raw_user_datastream.$$'" +# test incremental send with intermediates (should pass) +log_must zfs allow $OTHER1 hold $TESTPOOL/$TESTFS1 +log_must zfs snapshot $TESTPOOL/$TESTFS1@snap2 +log_must user_run $OTHER1 sh -c "'zfs send -w -I $TESTPOOL/$TESTFS1@snap1 $TESTPOOL/$TESTFS1@snap2 > /dev/null'" + # disable raw delegation log_must zfs unallow -u $OTHER1 send:raw $TESTPOOL/$TESTFS1 log_must zfs allow $OTHER1 send $TESTPOOL/$TESTFS1 @@ -123,13 +128,13 @@ log_must zfs unallow -u $OTHER1 send $TESTPOOL/$TESTFS1 # verify original send abilities (should fail) log_mustnot user_run $OTHER1 sh -c "'zfs send $TESTPOOL/$TESTFS1@snap1 | zfs receive -u $TESTPOOL/$TESTFS2/zfsrecv4_user_datastream.$$'" - verify nothing went through +# verify nothing went through if [ -s $TESTPOOL/$TESTFS2/zfsrecv4_user_datastream.$$ ] then log_fail "A zfs recieve was completed in $TESTPOOL/$TESTFS2/zfsrecv4_user_datastream !" fi log_mustnot user_run $OTHER1 sh -c "'zfs send -w $TESTPOOL/$TESTFS1@snap1 | zfs receive -u $TESTPOOL/$TESTFS2/zfsrecv4raw_user_datastream.$$'" - verify nothing went through +# verify nothing went through if [ -s $TESTPOOL/$TESTFS2/zfsrecv4raw_user_datastream.$$ ] then log_fail "A zfs recieve was completed in $TESTPOOL/$TESTFS2/zfsrecv4raw_user_datastream !"