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 <alexander.motin@TrueNAS.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Marc Sladek <marc@sladek.dev>
Closes #18198
Closes #18193
This commit is contained in:
Marc Sladek 2026-02-11 19:30:26 +01:00 committed by GitHub
parent 3463d40779
commit cc184fe98b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 11 additions and 6 deletions

View File

@ -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);
}

View File

@ -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 !"