From 2aec80b9f8c2a97ab283332e64dc9045fd887406 Mon Sep 17 00:00:00 2001 From: Alexander Schreiber Date: Fri, 5 Sep 2025 18:36:44 +0300 Subject: [PATCH] Added --sys argument for mounting sysfs Signed-off-by: Alexander Schreiber --- bubblewrap.c | 51 ++++++++++++++++++++++++++++++++++++++++++ bwrap.xml | 4 ++++ completions/bash/bwrap | 1 + completions/zsh/_bwrap | 1 + 4 files changed, 57 insertions(+) diff --git a/bubblewrap.c b/bubblewrap.c index f6062576..13e4ca23 100644 --- a/bubblewrap.c +++ b/bubblewrap.c @@ -130,6 +130,7 @@ typedef enum { SETUP_OVERLAY_SRC, SETUP_MOUNT_PROC, SETUP_MOUNT_DEV, + SETUP_MOUNT_SYS, SETUP_MOUNT_TMPFS, SETUP_MOUNT_MQUEUE, SETUP_MAKE_DIR, @@ -175,6 +176,7 @@ enum { PRIV_SEP_OP_BIND_MOUNT, PRIV_SEP_OP_OVERLAY_MOUNT, PRIV_SEP_OP_PROC_MOUNT, + PRIV_SEP_OP_SYS_MOUNT, PRIV_SEP_OP_TMPFS_MOUNT, PRIV_SEP_OP_DEVPTS_MOUNT, PRIV_SEP_OP_MQUEUE_MOUNT, @@ -352,6 +354,7 @@ usage (int ecode, FILE *out) " --file-label LABEL File label for temporary sandbox content\n" " --proc DEST Mount new procfs on DEST\n" " --dev DEST Mount new dev on DEST\n" + " --sys DEST Mount new sysfs on DEST\n" " --tmpfs DEST Mount new tmpfs on DEST\n" " --mqueue DEST Mount new mqueue on DEST\n" " --dir DEST Create dir at DEST\n" @@ -1122,6 +1125,11 @@ privileged_op (int privileged_op_socket, die_with_mount_error ("Can't mount proc on %s", arg1); break; + case PRIV_SEP_OP_SYS_MOUNT: + if (mount ("sysfs", arg1, "sysfs", MS_NOSUID | MS_NOEXEC | MS_NODEV, NULL) != 0) + die_with_mount_error ("Can't mount sys on %s", arg1); + break; + case PRIV_SEP_OP_TMPFS_MOUNT: { cleanup_free char *mode = NULL; @@ -1191,6 +1199,7 @@ setup_newroot (bool unshare_pid, { SetupOp *op; int tmp_overlay_idx = 0; + struct stat sbuf; for (op = ops; op != NULL; op = op->next) { @@ -1443,6 +1452,36 @@ setup_newroot (bool unshare_pid, break; + case SETUP_MOUNT_SYS: + if (ensure_dir (dest, 0755) != 0) + die_with_error ("Can't mkdir %s", op->dest); + + if (unshare_pid || opt_pidns_fd != -1) + { + /* Our own sysfs */ + privileged_op (privileged_op_socket, + PRIV_SEP_OP_SYS_MOUNT, 0, 0, 0, + dest, NULL); + + /* In case the host utilizes SELinux, /sys/fs/selinux should be shared with the sandbox */ + char *selinux_src_dir = "oldroot/sys/fs/selinux"; + cleanup_free char *selinux_dest_dir = strconcat (dest, "/fs/selinux"); + if (stat (selinux_src_dir, &sbuf) == 0 && stat (selinux_dest_dir, &sbuf) == 0) + { + privileged_op (privileged_op_socket, + PRIV_SEP_OP_BIND_MOUNT, 0, 0, 0, + selinux_src_dir, selinux_dest_dir); + } + } + else + { + /* Use system sysfs, as we share pid namespace anyway */ + privileged_op (privileged_op_socket, + PRIV_SEP_OP_BIND_MOUNT, 0, 0, 0, + "oldroot/sys", dest); + } + break; + case SETUP_MOUNT_TMPFS: assert (dest != NULL); assert (op->perms >= 0); @@ -1642,6 +1681,7 @@ resolve_symlinks_in_ops (void) case SETUP_TMP_OVERLAY_MOUNT: case SETUP_MOUNT_PROC: case SETUP_MOUNT_DEV: + case SETUP_MOUNT_SYS: case SETUP_MOUNT_TMPFS: case SETUP_MOUNT_MQUEUE: case SETUP_MAKE_DIR: @@ -2100,6 +2140,17 @@ parse_args_recurse (int *argcp, op = setup_op_new (SETUP_MOUNT_PROC); op->dest = argv[1]; + argv += 1; + argc -= 1; + } + else if (strcmp (arg, "--sys") == 0) + { + if (argc < 2) + die ("--sys takes an argument"); + + op = setup_op_new (SETUP_MOUNT_SYS); + op->dest = argv[1]; + argv += 1; argc -= 1; } diff --git a/bwrap.xml b/bwrap.xml index f379f0fa..35d50ec3 100644 --- a/bwrap.xml +++ b/bwrap.xml @@ -405,6 +405,10 @@ Mount new devtmpfs on DEST + + + Mount sysfs on DEST + diff --git a/completions/bash/bwrap b/completions/bash/bwrap index e7a523c2..3e484a91 100644 --- a/completions/bash/bwrap +++ b/completions/bash/bwrap @@ -63,6 +63,7 @@ _bwrap() { --size --symlink --sync-fd + --sys --tmp-overlay --uid --unsetenv diff --git a/completions/zsh/_bwrap b/completions/zsh/_bwrap index fbddda43..1e580d52 100644 --- a/completions/zsh/_bwrap +++ b/completions/zsh/_bwrap @@ -65,6 +65,7 @@ _bwrap_args=( '--size[Set size in bytes for next action argument]: :->after_size' '--symlink[Create symlink at DEST with target SRC]:symlink target:_files:symlink to create:_files:' '--sync-fd[Keep this fd open while sandbox is running]: :_guard "[0-9]#" "file descriptor to keep open"' + '--sys[Mount new sysfs on DEST]:mount point for sysfs:_files -/' '--uid[Custom uid in the sandbox (requires --unshare-user or --userns)]: :_guard "[0-9]#" "numeric group ID"' '(--clearenv)--unsetenv[Unset an environment variable]:variable to unset:_parameters -g "*export*"' '--unshare-all[Unshare every namespace we support by default]'