minijail0: Remount mounts as MS_SLAVE by default.
When executing the sandboxed program in a new mount namespace the
Minijail library will by default remount all mounts with the MS_PRIVATE
flag. While this is an appropriate, safe default for the library,
MS_PRIVATE can be problematic: unmount events will not propagate into
mountpoints marked as MS_PRIVATE. This can cause bugs (see code
comments for details.)
Fix by keeping MS_PRIVATE as default in libminijail.c but switch the
default in minijail0_cli.c to MS_SLAVE.
In order to avoid command-lines like "-Kprivate -v" overriding the -K
option, call set_remount_mode() after all command-line options have
been processed.
Bug: 147609789
Test: Unit tests pass.
Test: See repro steps in bug.
Test: "minijail0 -Kprivate -v" remounts with MS_PRIVATE.
Change-Id: I4788ffb92309d9b6e02a38ef2998bcecf5314b50
diff --git a/minijail0_cli.c b/minijail0_cli.c
index 940bd3c..94d8578 100644
--- a/minijail0_cli.c
+++ b/minijail0_cli.c
@@ -645,6 +645,7 @@
int binding = 0;
int chroot = 0, pivot_root = 0;
int mount_ns = 0, change_remount = 0;
+ const char *remount_mode = NULL;
int inherit_suppl_gids = 0, keep_suppl_gids = 0;
int caps = 0, ambient_caps = 0;
int seccomp = -1;
@@ -746,11 +747,7 @@
add_mount(j, optarg);
break;
case 'K':
- if (optarg) {
- set_remount_mode(j, optarg);
- } else {
- minijail_skip_remount_private(j);
- }
+ remount_mode = optarg;
change_remount = 1;
break;
case 'P':
@@ -780,6 +777,37 @@
break;
case 'v':
minijail_namespace_vfs(j);
+ /*
+ * Set the default mount propagation in the command-line
+ * tool to MS_SLAVE.
+ *
+ * When executing the sandboxed program in a new mount
+ * namespace the Minijail library will by default
+ * remount all mounts with the MS_PRIVATE flag. While
+ * this is an appropriate, safe default for the library,
+ * MS_PRIVATE can be problematic: unmount events will
+ * not propagate into mountpoints marked as MS_PRIVATE.
+ * This means that if a mount is unmounted in the root
+ * mount namespace, it will not be unmounted in the
+ * non-root mount namespace.
+ * This in turn can be problematic because activity in
+ * the non-root mount namespace can now directly
+ * influence the root mount namespace (e.g. preventing
+ * re-mounts of said mount), which would be a privilege
+ * inversion.
+ *
+ * Setting the default in the command-line to MS_SLAVE
+ * will still prevent mounts from leaking out of the
+ * non-root mount namespace but avoid these
+ * privilege-inversion issues.
+ * For cases where mounts should not flow *into* the
+ * namespace either, the user can pass -Kprivate.
+ * Note that mounts are marked as MS_PRIVATE by default
+ * by the kernel, so unless the init process (like
+ * systemd) or something else marks them as shared, this
+ * won't do anything.
+ */
+ minijail_remount_mode(j, MS_SLAVE);
mount_ns = 1;
break;
case 'V':
@@ -990,6 +1018,15 @@
exit(1);
}
+ /* Configure the remount flag here to avoid having -v override it. */
+ if (change_remount) {
+ if (remount_mode != NULL) {
+ set_remount_mode(j, remount_mode);
+ } else {
+ minijail_skip_remount_private(j);
+ }
+ }
+
/*
* Proceed in setting the supplementary gids specified on the
* cmdline options.