diff options
author | Will Andrews <[email protected]> | 2021-02-21 10:19:43 -0600 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2022-06-10 09:51:46 -0700 |
commit | 4ed5e25074ffec266df38556d9b3a928c5e0dee9 (patch) | |
tree | 930f2397ca27e885ca33c05728802d7f19021f08 /cmd/zfs | |
parent | a1aa8f14c864b6851649f9c3e74e9f12e6518edd (diff) |
Add Linux namespace delegation support
This allows ZFS datasets to be delegated to a user/mount namespace
Within that namespace, only the delegated datasets are visible
Works very similarly to Zones/Jailes on other ZFS OSes
As a user:
```
$ unshare -Um
$ zfs list
no datasets available
$ echo $$
1234
```
As root:
```
# zfs list
NAME ZONED MOUNTPOINT
containers off /containers
containers/host off /containers/host
containers/host/child off /containers/host/child
containers/host/child/gchild off /containers/host/child/gchild
containers/unpriv on /unpriv
containers/unpriv/child on /unpriv/child
containers/unpriv/child/gchild on /unpriv/child/gchild
# zfs zone /proc/1234/ns/user containers/unpriv
```
Back to the user namespace:
```
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
containers 129M 47.8G 24K /containers
containers/unpriv 128M 47.8G 24K /unpriv
containers/unpriv/child 128M 47.8G 128M /unpriv/child
```
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Will Andrews <[email protected]>
Signed-off-by: Allan Jude <[email protected]>
Signed-off-by: Mateusz Piotrowski <[email protected]>
Co-authored-by: Allan Jude <[email protected]>
Co-authored-by: Mateusz Piotrowski <[email protected]>
Sponsored-by: Buddy <https://buddy.works>
Closes #12263
Diffstat (limited to 'cmd/zfs')
-rw-r--r-- | cmd/zfs/zfs_main.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index 6282d8946..30b2ae0c4 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -127,6 +127,11 @@ static int zfs_do_jail(int argc, char **argv); static int zfs_do_unjail(int argc, char **argv); #endif +#ifdef __linux__ +static int zfs_do_zone(int argc, char **argv); +static int zfs_do_unzone(int argc, char **argv); +#endif + /* * Enable a reasonable set of defaults for libumem debugging on DEBUG builds. */ @@ -184,6 +189,8 @@ typedef enum { HELP_JAIL, HELP_UNJAIL, HELP_WAIT, + HELP_ZONE, + HELP_UNZONE, } zfs_help_t; typedef struct zfs_command { @@ -254,6 +261,11 @@ static zfs_command_t command_table[] = { { "jail", zfs_do_jail, HELP_JAIL }, { "unjail", zfs_do_unjail, HELP_UNJAIL }, #endif + +#ifdef __linux__ + { "zone", zfs_do_zone, HELP_ZONE }, + { "unzone", zfs_do_unzone, HELP_UNZONE }, +#endif }; #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) @@ -415,6 +427,10 @@ get_usage(zfs_help_t idx) return (gettext("\tunjail <jailid|jailname> <filesystem>\n")); case HELP_WAIT: return (gettext("\twait [-t <activity>] <filesystem>\n")); + case HELP_ZONE: + return (gettext("\tzone <nsfile> <filesystem>\n")); + case HELP_UNZONE: + return (gettext("\tunzone <nsfile> <filesystem>\n")); default: __builtin_unreachable(); } @@ -8692,6 +8708,50 @@ main(int argc, char **argv) return (ret); } +/* + * zfs zone nsfile filesystem + * + * Add or delete the given dataset to/from the namespace. + */ +#ifdef __linux__ +static int +zfs_do_zone_impl(int argc, char **argv, boolean_t attach) +{ + zfs_handle_t *zhp; + int ret; + + if (argc < 3) { + (void) fprintf(stderr, gettext("missing argument(s)\n")); + usage(B_FALSE); + } + if (argc > 3) { + (void) fprintf(stderr, gettext("too many arguments\n")); + usage(B_FALSE); + } + + zhp = zfs_open(g_zfs, argv[2], ZFS_TYPE_FILESYSTEM); + if (zhp == NULL) + return (1); + + ret = (zfs_userns(zhp, argv[1], attach) != 0); + + zfs_close(zhp); + return (ret); +} + +static int +zfs_do_zone(int argc, char **argv) +{ + return (zfs_do_zone_impl(argc, argv, B_TRUE)); +} + +static int +zfs_do_unzone(int argc, char **argv) +{ + return (zfs_do_zone_impl(argc, argv, B_FALSE)); +} +#endif + #ifdef __FreeBSD__ #include <sys/jail.h> #include <jail.h> |