How can I determine what permissions my user is missing for receiving a ZFS dataset?
I have a FreeNAS (11.1-U1) and a FreeBSD (11.1-RELEASE-p6) machine. On the FreeNAS I'd like to zfs receive
recursive snapshots as a non-root user with delegated privileges. This appears to work well for most of the child-datasets. But iocage's data
datasets, which can be mounted into the jail and administered from there, they fail:
root@freebsd:~> zfs send -RI "dozer@2018-02-21" "dozer@2018-03-08" | ssh -T -i /root/backup_key backupuser@freenas zfs receive -dvuF neo/backups/freebsd
receiving incremental stream of dozer@2018-03-03 into neo/backups/freebsd@2018-03-03
received 312B stream in 1 seconds (312B/sec)
receiving incremental stream of dozer@2018-03-07 into neo/backups/freebsd@2018-03-07
received 312B stream in 1 seconds (312B/sec)
receiving incremental stream of dozer@2018-03-08 into neo/backups/freebsd@2018-03-08
received 312B stream in 1 seconds (312B/sec)
receiving incremental stream of dozer/ROOT@2018-03-03 into neo/backups/freebsd/ROOT@2018-03-03
.
.
.
receiving incremental stream of dozer/iocage/jails/owncloud/root@2018-03-08 into neo/backups/freebsd/iocage/jails/owncloud/root@2018-03-08
received 578MB stream in 110 seconds (5.25MB/sec)
receiving incremental stream of dozer/iocage/jails/owncloud/root/data@2018-03-03 into neo/backups/freebsd/iocage/jails/owncloud/root/data@2018-03-03
cannot receive incremental stream: permission denied
warning: cannot send 'dozer/iocage/jails/owncloud/root/data@2018-03-03': signal received
warning: cannot send 'dozer/iocage/jails/owncloud/root/data@2018-03-07': Broken pipe
warning: cannot send 'dozer/iocage/jails/owncloud/root/data@2018-03-08': Broken pipe
The permissions of that particular child are exactly the same as the one of the parent dataset:
root@freenas:~ # zfs allow neo/backups/freebsd/iocage/jails/owncloud/root/data
---- Permissions on neo/backups/freebsd -----------------------------
Local+Descendent permissions:
user backupuser atime,compression,create,dedup,exec,jailed,mount,mountpoint,quota,receive,rename,reservation,setuid,userprop
Running the zfs receive
on the FreeNAS as root works as expected.
What delegated privileges does my user need to receive the jailed datasets of iocage and, more generally, is there a way to make zfs receive
give out a more detailed error message which tells you what permission is missing?
Solution 1:
When troubleshooting permission problems arising from zfs
commands, analyze the zfs
operation in terms of its component steps.
The sample command of zfs receive -duvF
unpacks into several steps. Two of those flags do not relate to any special permissions:
-d affects the naming of the new dataset (if any)
-v enables verbose output
The other two do.
-F means the filesystem will be rolled back to the initial snapshot of the incremental transfer before the receive starts
-u means the filesystem will not be mounted after the receive finishes
My hunch is that you're missing the rollback permission. The -F flag in your command implies that a zfs rollback
will be performed, and your zfs allow
does not list rollback
.
In the general case, one can make deductive guesses about the permissions necessary for a given zfs
command.
The man page for zfs
points out:
Permission names are the same as ZFS subcommand and property names.
and ...
Permissions are generally the ability to use a ZFS subcommand or change a ZFS property. The following permissions are available:
NAME TYPE NOTES allow subcommand Must also have the permission that is being allowed clone subcommand Must also have the 'create' ability and 'mount' ability in the origin file system create subcommand Must also have the 'mount' ability destroy subcommand Must also have the 'mount' ability diff subcommand Allows lookup of paths within a dataset given an object number, and the ability to create snapshots necessary to 'zfs diff' hold subcommand Allows adding a user hold to a snapshot mount subcommand Allows mount/umount of ZFS datasets promote subcommand Must also have the 'mount' and 'promote' ability in the origin file system receive subcommand Must also have the 'mount' and 'create' ability release subcommand Allows releasing a user hold which might destroy the snapshot rename subcommand Must also have the 'mount' and 'create' ability in the new parent rollback subcommand Must also have the 'mount' ability send subcommand share subcommand Allows sharing file systems over the NFS protocol snapshot subcommand Must also have the 'mount' ability groupquota other Allows accessing any groupquota@... property groupused other Allows reading any groupused@... property userprop other Allows changing any user property userquota other Allows accessing any userquota@... property userused other Allows reading any userused@... property aclinherit property aclmode property atime property canmount property casesensitivity property checksum property compression property copies property dedup property devices property exec property filesystem_limit property logbias property jailed property mlslabel property mountpoint property nbmand property normalization property primarycache property quota property readonly property recordsize property refquota property refreservation property reservation property secondarycache property setuid property sharenfs property sharesmb property snapdir property snapshot_limit property sync property utf8only property version property volblocksize property volsize property vscan property xattr property
The example at hand includes the -u
flag, so the file system will not be mounted at the end of the receive operation. However, if -u
were absent, the filesystem would be mounted at the end of the receive process. Tellingly, the receive
permission requires the mount
permission.
Because a zfs mount
operation will auto-create any necessary mountpoints, it is possible for a user to have zfs
permission to mount the dataset, but not have filesystem permissions to create the mountpoint. In the case of zfs mount
, the mount will fail. In a zfs create
or rename
operation, the file system will be created or renamed, but it will remain unmounted if the user does not have sufficient filesystem permissions to create the mountpoint.
Similarly, a zfs rename
command could fail for lack of permissions at several points within the rename operation. Loosely expressed, the component steps might be:
1) unmount the filesystem (mount
permission)
2) create a new filesystem (create
permission)
3) map the filesystem meta-data into the new name (rename
permission)
A fourth step is to re-mount the newly-named filesystem at its new, possibly changed mountpoint, which again uses the mount
permission, and possibly filesystem permissions to create the new mountpoint.
I have not tested such tricks, but it can be seen that zfs
distinguishes between create
and rename
permissions, and also between mount
and mountpoint
permissions. One imagines it might be possible to allow a user to create new filesystems, but once created, the user cannot rename them. For filesystems with inherited mountpoints, renaming a filesystem often also will rename the filesystem's mountpoint, as when renaming tank/usr/local
to tank/usr/local.OLD
changes the mountpoint from /usr/local
to /usr/local.OLD
.
The separation of mount
or rename
from mountpoint
permissions means that a user could be allowed to rename a filesystem but not allowed to change its mountpoint. Or vice versa, to be able to change where a filesystem is mounted, but not be able to change the filesystem's name.
The richness of its filesystem operations and delegation of those operations, coupled with the granularity of permissions, can make zfs
somewhat challenging, but also very powerful.