aboutsummaryrefslogtreecommitdiffstats
path: root/lib/libzfs/os
diff options
context:
space:
mode:
authorWill Andrews <[email protected]>2021-02-21 10:19:43 -0600
committerBrian Behlendorf <[email protected]>2022-06-10 09:51:46 -0700
commit4ed5e25074ffec266df38556d9b3a928c5e0dee9 (patch)
tree930f2397ca27e885ca33c05728802d7f19021f08 /lib/libzfs/os
parenta1aa8f14c864b6851649f9c3e74e9f12e6518edd (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 'lib/libzfs/os')
-rw-r--r--lib/libzfs/os/linux/libzfs_util_os.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/lib/libzfs/os/linux/libzfs_util_os.c b/lib/libzfs/os/linux/libzfs_util_os.c
index 9d6f574a5..7bd26ea98 100644
--- a/lib/libzfs/os/linux/libzfs_util_os.c
+++ b/lib/libzfs/os/linux/libzfs_util_os.c
@@ -19,6 +19,9 @@
* CDDL HEADER END
*/
+/*
+ * Copyright (c) 2021 Klara, Inc.
+ */
#include <alloca.h>
#include <errno.h>
@@ -207,3 +210,69 @@ zfs_version_kernel(void)
ret[read - 1] = '\0';
return (ret);
}
+
+/*
+ * Add or delete the given filesystem to/from the given user namespace.
+ */
+int
+zfs_userns(zfs_handle_t *zhp, const char *nspath, int attach)
+{
+ libzfs_handle_t *hdl = zhp->zfs_hdl;
+ zfs_cmd_t zc = {"\0"};
+ char errbuf[1024];
+ unsigned long cmd;
+ int ret;
+
+ if (attach) {
+ (void) snprintf(errbuf, sizeof (errbuf),
+ dgettext(TEXT_DOMAIN, "cannot add '%s' to namespace"),
+ zhp->zfs_name);
+ } else {
+ (void) snprintf(errbuf, sizeof (errbuf),
+ dgettext(TEXT_DOMAIN, "cannot remove '%s' from namespace"),
+ zhp->zfs_name);
+ }
+
+ switch (zhp->zfs_type) {
+ case ZFS_TYPE_VOLUME:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "volumes can not be namespaced"));
+ return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
+ case ZFS_TYPE_SNAPSHOT:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "snapshots can not be namespaced"));
+ return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
+ case ZFS_TYPE_BOOKMARK:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "bookmarks can not be namespaced"));
+ return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
+ case ZFS_TYPE_VDEV:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "vdevs can not be namespaced"));
+ return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
+ case ZFS_TYPE_INVALID:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "invalid zfs_type_t: ZFS_TYPE_INVALID"));
+ return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
+ case ZFS_TYPE_POOL:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "pools can not be namespaced"));
+ return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
+ case ZFS_TYPE_FILESYSTEM:
+ zfs_fallthrough;
+ }
+ assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
+
+ (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
+ zc.zc_objset_type = DMU_OST_ZFS;
+ zc.zc_cleanup_fd = open(nspath, O_RDONLY);
+ if (zc.zc_cleanup_fd < 0) {
+ return (zfs_error(hdl, EZFS_NOT_USER_NAMESPACE, errbuf));
+ }
+
+ cmd = attach ? ZFS_IOC_USERNS_ATTACH : ZFS_IOC_USERNS_DETACH;
+ if ((ret = zfs_ioctl(hdl, cmd, &zc)) != 0)
+ zfs_standard_error(hdl, errno, errbuf);
+
+ return (ret);
+}