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]'