Skip to content

Commit 534a900

Browse files
committed
Add receive:append permission for limited receive
Force receive (zfs receive -F) can rollback or destroy snapshots and file systems that do not exist on the sending side (see zfs-receive man page). This means an user having the receive permission can effectively delete data on receiving side, even if such user does not have explicit rollback or destroy permissions. This patch adds the receive:append permission, which only permits limited, non-forced receive. Behavior for users with full receive permission is not changed in any way. Fixes #16943 Signed-off-by: Gionatan Danti <[email protected]>
1 parent 523e3ad commit 534a900

File tree

7 files changed

+62
-4
lines changed

7 files changed

+62
-4
lines changed

cmd/zfs/zfs_main.c

+1
Original file line numberDiff line numberDiff line change
@@ -5292,6 +5292,7 @@ zfs_do_receive(int argc, char **argv)
52925292
#define ZFS_DELEG_PERM_SHARE "share"
52935293
#define ZFS_DELEG_PERM_SEND "send"
52945294
#define ZFS_DELEG_PERM_RECEIVE "receive"
5295+
#define ZFS_DELEG_PERM_RECEIVE_APPEND "receive:append"
52955296
#define ZFS_DELEG_PERM_ALLOW "allow"
52965297
#define ZFS_DELEG_PERM_USERPROP "userprop"
52975298
#define ZFS_DELEG_PERM_VSCAN "vscan" /* ??? */

include/sys/dsl_deleg.h

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ extern "C" {
4646
#define ZFS_DELEG_PERM_SHARE "share"
4747
#define ZFS_DELEG_PERM_SEND "send"
4848
#define ZFS_DELEG_PERM_RECEIVE "receive"
49+
#define ZFS_DELEG_PERM_RECEIVE_APPEND "receive:append"
4950
#define ZFS_DELEG_PERM_ALLOW "allow"
5051
#define ZFS_DELEG_PERM_USERPROP "userprop"
5152
#define ZFS_DELEG_PERM_VSCAN "vscan"

man/man8/zfs-allow.8

+2-1
Original file line numberDiff line numberDiff line change
@@ -207,14 +207,15 @@ load-key subcommand Allows loading and unloading of encryption key (see \fBzfs l
207207
change-key subcommand Allows changing an encryption key via \fBzfs change-key\fR.
208208
mount subcommand Allows mounting/umounting ZFS datasets
209209
promote subcommand Must also have the \fBmount\fR and \fBpromote\fR ability in the origin file system
210-
receive subcommand Must also have the \fBmount\fR and \fBcreate\fR ability
210+
receive subcommand Must also have the \fBmount\fR and \fBcreate\fR ability, required for \fBzfs receive -F\fR (see also \fBreceive:append\fR for limited, non forced receive)
211211
release subcommand Allows releasing a user hold which might destroy the snapshot
212212
rename subcommand Must also have the \fBmount\fR and \fBcreate\fR ability in the new parent
213213
rollback subcommand Must also have the \fBmount\fR ability
214214
send subcommand
215215
share subcommand Allows sharing file systems over NFS or SMB protocols
216216
snapshot subcommand Must also have the \fBmount\fR ability
217217

218+
receive:append other Must also have the \fBmount\fR and \fBcreate\fR ability, limited receive ability (can not do receive -F)
218219
groupquota other Allows accessing any \fBgroupquota@\fI\fR property
219220
groupobjquota other Allows accessing any \fBgroupobjquota@\fI\fR property
220221
groupused other Allows reading any \fBgroupused@\fI\fR property

module/zcommon/zfs_deleg.c

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const zfs_deleg_perm_tab_t zfs_deleg_perm_tab[] = {
5252
{ZFS_DELEG_PERM_MOUNT},
5353
{ZFS_DELEG_PERM_PROMOTE},
5454
{ZFS_DELEG_PERM_RECEIVE},
55+
{ZFS_DELEG_PERM_RECEIVE_APPEND},
5556
{ZFS_DELEG_PERM_RENAME},
5657
{ZFS_DELEG_PERM_ROLLBACK},
5758
{ZFS_DELEG_PERM_SNAPSHOT},

module/zfs/zfs_ioctl.c

+11-2
Original file line numberDiff line numberDiff line change
@@ -900,9 +900,18 @@ zfs_secpolicy_recv(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
900900
(void) innvl;
901901
int error;
902902

903+
/*
904+
* zfs receive -F requires full receive permission,
905+
* otherwise receive:append permission is enough
906+
*/
903907
if ((error = zfs_secpolicy_write_perms(zc->zc_name,
904-
ZFS_DELEG_PERM_RECEIVE, cr)) != 0)
905-
return (error);
908+
ZFS_DELEG_PERM_RECEIVE, cr)) != 0) {
909+
if (zc->zc_guid || nvlist_exists(innvl, "force"))
910+
return (error);
911+
if ((error = zfs_secpolicy_write_perms(zc->zc_name,
912+
ZFS_DELEG_PERM_RECEIVE_APPEND, cr)) != 0)
913+
return (error);
914+
}
906915

907916
if ((error = zfs_secpolicy_write_perms(zc->zc_name,
908917
ZFS_DELEG_PERM_MOUNT, cr)) != 0)

tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib

+42
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,9 @@ function check_fs_perm
256256
receive)
257257
verify_fs_receive $user $perm $fs
258258
;;
259+
receive:append)
260+
verify_fs_receive_append $user $perm $fs
261+
;;
259262
*)
260263
common_perm $user $perm $fs
261264
;;
@@ -425,6 +428,45 @@ function verify_fs_receive
425428
return 0
426429
}
427430

431+
function verify_fs_receive_append
432+
{
433+
typeset user=$1
434+
typeset perm=$2
435+
typeset fs=$3
436+
437+
typeset dtst
438+
typeset stamp=${perm}.${user}.$RANDOM
439+
typeset newfs=$fs/newfs.$stamp
440+
typeset bak_user=$TEST_BASE_DIR/bak.$user.$stamp
441+
442+
log_must zfs create $newfs
443+
typeset dtst="$newfs"
444+
445+
typeset dtstsnap=$dtst@snap.$stamp
446+
log_must zfs snapshot $dtstsnap
447+
448+
log_must eval "zfs send $dtstsnap > $bak_user"
449+
log_must_busy zfs destroy -rf $dtst
450+
451+
log_must zfs allow $user create,mount,canmount $fs
452+
user_run $user eval "zfs receive -o canmount=off -F $dtst < $bak_user"
453+
log_must zfs unallow $user create,mount,canmount $fs
454+
if datasetexists $dtstsnap ; then
455+
return 1
456+
fi
457+
458+
log_must zfs allow $user create,mount,canmount $fs
459+
user_run $user eval "zfs receive -o canmount=off $dtst < $bak_user"
460+
log_must zfs unallow $user create,mount,canmount $fs
461+
if ! datasetexists $dtstsnap ; then
462+
return 1
463+
fi
464+
465+
rm -rf $bak_user
466+
467+
return 0
468+
}
469+
428470
function verify_userprop
429471
{
430472
typeset user=$1

tests/zfs-tests/tests/functional/delegate/zfs_allow_010_pos.ksh

+4-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ set -A perms create true false \
8686
clone true true \
8787
promote true true \
8888
xattr true false \
89-
receive true false
89+
receive true false \
90+
receive:append true false
9091

9192
elif is_freebsd; then
9293
# Results in Results in
@@ -126,6 +127,7 @@ set -A perms create true false \
126127
rename true true \
127128
promote true true \
128129
receive true false \
130+
receive:append true false \
129131
destroy true true
130132

131133
else
@@ -160,6 +162,7 @@ set -A perms create true false \
160162
zoned true false \
161163
xattr true false \
162164
receive true false \
165+
receive:append true false \
163166
destroy true true
164167

165168
if is_global_zone; then

0 commit comments

Comments
 (0)