From 3885143c95f04b25f5d29c5a1776edfc5f4f9a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=B7=D0=B0=D0=BB=D0=B8=D1=8F=20=D0=A1=D0=BC=D0=B0?= =?UTF-8?q?=D1=80=D0=B0=D0=B3=D0=B4=D0=BE=D0=B2=D0=B0?= Date: Sun, 24 Jul 2022 23:30:45 +0500 Subject: [PATCH 1/2] Added an option to use private propagation for bind mounts. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Азалия Смарагдова --- bind-mount.c | 12 +++++++----- bind-mount.h | 1 + bubblewrap.c | 15 ++++++++++++--- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/bind-mount.c b/bind-mount.c index 877b0955..6836796a 100644 --- a/bind-mount.c +++ b/bind-mount.c @@ -241,7 +241,6 @@ parse_mountinfo (int proc_fd, int max_id; unsigned int n_lines; int root; - mountinfo = load_file_at (proc_fd, "self/mountinfo"); if (mountinfo == NULL) die_with_error ("Can't open /proc/self/mountinfo"); @@ -376,6 +375,7 @@ parse_mountinfo (int proc_fd, bind_mount_result bind_mount (int proc_fd, + int p_priv, const char *src, const char *dest, bind_option_t options) @@ -391,10 +391,12 @@ bind_mount (int proc_fd, cleanup_free char *kernel_case_combination = NULL; cleanup_fd int dest_fd = -1; int i; - + int current_propagation = 0; + if (p_priv == 1) + current_propagation = MS_PRIVATE; if (src) { - if (mount (src, dest, NULL, MS_SILENT | MS_BIND | (recursive ? MS_REC : 0), NULL) != 0) + if (mount (src, dest, NULL, MS_SILENT | MS_BIND | current_propagation | (recursive ? MS_REC : 0), NULL) != 0) return BIND_MOUNT_ERROR_MOUNT; } @@ -436,7 +438,7 @@ bind_mount (int proc_fd, new_flags = current_flags | (devices ? 0 : MS_NODEV) | MS_NOSUID | (readonly ? MS_RDONLY : 0); if (new_flags != current_flags && mount ("none", resolved_dest, - NULL, MS_SILENT | MS_BIND | MS_REMOUNT | new_flags, NULL) != 0) + NULL, MS_SILENT | MS_BIND | MS_REMOUNT | new_flags | current_propagation, NULL) != 0) return BIND_MOUNT_ERROR_REMOUNT_DEST; /* We need to work around the fact that a bind mount does not apply the flags, so we need to manually @@ -451,7 +453,7 @@ bind_mount (int proc_fd, new_flags = current_flags | (devices ? 0 : MS_NODEV) | MS_NOSUID | (readonly ? MS_RDONLY : 0); if (new_flags != current_flags && mount ("none", mount_tab[i].mountpoint, - NULL, MS_SILENT | MS_BIND | MS_REMOUNT | new_flags, NULL) != 0) + NULL, MS_SILENT | MS_BIND | MS_REMOUNT | new_flags | current_propagation, NULL) != 0) { /* If we can't read the mountpoint we can't remount it, but that should be safe to ignore because its not something the user can access. */ diff --git a/bind-mount.h b/bind-mount.h index 1fac3e58..2b072558 100644 --- a/bind-mount.h +++ b/bind-mount.h @@ -40,6 +40,7 @@ typedef enum } bind_mount_result; bind_mount_result bind_mount (int proc_fd, + int p_priv, const char *src, const char *dest, bind_option_t options); diff --git a/bubblewrap.c b/bubblewrap.c index b17ff990..6107ab60 100644 --- a/bubblewrap.c +++ b/bubblewrap.c @@ -85,6 +85,7 @@ int opt_userns_block_fd = -1; int opt_info_fd = -1; int opt_json_status_fd = -1; int opt_seccomp_fd = -1; +int opt_propagation = 0; const char *opt_sandbox_hostname = NULL; char *opt_args_data = NULL; /* owned */ int opt_userns_fd = -1; @@ -331,6 +332,7 @@ usage (int ecode, FILE *out) " --symlink SRC DEST Create symlink at DEST with target SRC\n" " --seccomp FD Load and use seccomp rules from FD (not repeatable)\n" " --add-seccomp-fd FD Load and use seccomp rules from FD (repeatable)\n" + " --private Set mount propagation to private\n" " --block-fd FD Block on FD until some data to read is available\n" " --userns-block-fd FD Block on FD until the user namespace is ready\n" " --info-fd FD Write information about the running container to FD\n" @@ -1070,7 +1072,7 @@ privileged_op (int privileged_op_socket, break; case PRIV_SEP_OP_REMOUNT_RO_NO_RECURSIVE: - bind_result = bind_mount (proc_fd, NULL, arg2, BIND_READONLY); + bind_result = bind_mount (proc_fd, opt_propagation, NULL, arg2, BIND_READONLY); if (bind_result != BIND_MOUNT_SUCCESS) die_with_bind_result (bind_result, errno, @@ -1081,7 +1083,7 @@ privileged_op (int privileged_op_socket, case PRIV_SEP_OP_BIND_MOUNT: /* We always bind directories recursively, otherwise this would let us access files that are otherwise covered on the host */ - bind_result = bind_mount (proc_fd, arg1, arg2, BIND_RECURSIVE | flags); + bind_result = bind_mount (proc_fd, opt_propagation, arg1, arg2, BIND_RECURSIVE | flags); if (bind_result != BIND_MOUNT_SUCCESS) die_with_bind_result (bind_result, errno, @@ -2149,6 +2151,8 @@ parse_args_recurse (int *argcp, argv += 1; argc -= 1; } + else if (strcmp (arg, "--private") == 0) + opt_propagation = 1; else if (strcmp (arg, "--add-seccomp-fd") == 0) { int the_fd; @@ -2956,7 +2960,12 @@ main (int argc, /* Mark everything as slave, so that we still * receive mounts from the real root, but don't * propagate mounts to the real root. */ - if (mount (NULL, "/", NULL, MS_SILENT | MS_SLAVE | MS_REC, NULL) < 0) + int current_propagation; + if (opt_propagation == 0) + current_propagation = MS_SLAVE; + else + current_propagation = MS_PRIVATE; + if (mount (NULL, "/", NULL, MS_SILENT | current_propagation | MS_REC, NULL) < 0) die_with_error ("Failed to make / slave"); /* Create a tmpfs which we will use as / in the namespace */ From 6a2838f89c6695867e7dfd80c7aba71f7e0d10c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=B7=D0=B0=D0=BB=D0=B8=D1=8F=20=D0=A1=D0=BC=D0=B0?= =?UTF-8?q?=D1=80=D0=B0=D0=B3=D0=B4=D0=BE=D0=B2=D0=B0?= Date: Mon, 25 Jul 2022 13:43:48 +0500 Subject: [PATCH 2/2] Added mentions of private propagation in the manpage and completion files. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Азалия Смарагдова --- bwrap.xml | 4 ++++ completions/bash/bwrap | 1 + completions/zsh/_bwrap | 1 + 3 files changed, 6 insertions(+) diff --git a/bwrap.xml b/bwrap.xml index 2baec5d8..f0794ca7 100644 --- a/bwrap.xml +++ b/bwrap.xml @@ -161,6 +161,10 @@ Use a custom hostname in the sandbox (requires ) + + + Use private propagation instead of slave one (prevents host mounts from propagating to the sandbox, but may cause some problems, for example, by keeping removable media mounted in the sandbox). + Options about environment setup: diff --git a/completions/bash/bwrap b/completions/bash/bwrap index c57d9abe..710c8b06 100644 --- a/completions/bash/bwrap +++ b/completions/bash/bwrap @@ -13,6 +13,7 @@ _bwrap() { --clearenv --help --new-session + --private --unshare-all --unshare-cgroup --unshare-cgroup-try diff --git a/completions/zsh/_bwrap b/completions/zsh/_bwrap index 1e365f09..17e41f7d 100644 --- a/completions/zsh/_bwrap +++ b/completions/zsh/_bwrap @@ -41,6 +41,7 @@ _bwrap_args=( '--new-session[Create a new terminal session]' '--perms[Set permissions for next action argument]: :_guard "[0-7]#" "permissions in octal": :->after_perms' '--pidns[Use this user namespace (as parent namespace if using --unshare-pid)]: :' + '--private[Use private propagation instead of slave]' '--proc[Mount new procfs on DEST]:mount point for procfs:_files -/' '--remount-ro[Remount DEST as readonly; does not recursively remount]:mount point to remount read-only:_files' '--ro-bind-try[Equal to --ro-bind but ignores non-existent SRC]:source:_files:destination:_files'