Add --assert-userns-disabled option

We can't combine --disable-userns with entering an existing user
namespace via --userns if the existing user namespace was created with
--disable-userns, because its ability to create nested user namespaces
has already been disabled. However, the next best thing is to verify
that we are already in the desired state.

Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
Simon McVittie
2022-12-16 18:46:23 +00:00
committed by Alexander Larsson
parent b33c333bcb
commit b5f672355b
5 changed files with 30 additions and 9 deletions

View File

@@ -73,6 +73,7 @@ static const char *opt_file_label = NULL;
static bool opt_as_pid_1; static bool opt_as_pid_1;
const char *opt_chdir_path = NULL; const char *opt_chdir_path = NULL;
bool opt_assert_userns_disabled = FALSE;
bool opt_disable_userns = FALSE; bool opt_disable_userns = FALSE;
bool opt_unshare_user = FALSE; bool opt_unshare_user = FALSE;
bool opt_unshare_user_try = FALSE; bool opt_unshare_user_try = FALSE;
@@ -313,6 +314,7 @@ usage (int ecode, FILE *out)
" --userns FD Use this user namespace (cannot combine with --unshare-user)\n" " --userns FD Use this user namespace (cannot combine with --unshare-user)\n"
" --userns2 FD After setup switch to this user namespace, only useful with --userns\n" " --userns2 FD After setup switch to this user namespace, only useful with --userns\n"
" --disable-userns Disable further use of user namespaces inside sandbox\n" " --disable-userns Disable further use of user namespaces inside sandbox\n"
" --assert-userns-disabled Fail unless further use of user namespace inside sandbox is disabled\n"
" --pidns FD Use this pid namespace (as parent namespace if using --unshare-pid)\n" " --pidns FD Use this pid namespace (as parent namespace if using --unshare-pid)\n"
" --uid UID Custom uid in the sandbox (requires --unshare-user or --userns)\n" " --uid UID Custom uid in the sandbox (requires --unshare-user or --userns)\n"
" --gid GID Custom gid in the sandbox (requires --unshare-user or --userns)\n" " --gid GID Custom gid in the sandbox (requires --unshare-user or --userns)\n"
@@ -1783,6 +1785,10 @@ parse_args_recurse (int *argcp,
{ {
opt_disable_userns = TRUE; opt_disable_userns = TRUE;
} }
else if (strcmp (arg, "--assert-userns-disabled") == 0)
{
opt_assert_userns_disabled = TRUE;
}
else if (strcmp (arg, "--remount-ro") == 0) else if (strcmp (arg, "--remount-ro") == 0)
{ {
if (argc < 2) if (argc < 2)
@@ -3202,20 +3208,20 @@ main (int argc,
/* We're in a new user namespace, we got back the bounding set, clear it again */ /* We're in a new user namespace, we got back the bounding set, clear it again */
drop_cap_bounding_set (FALSE); drop_cap_bounding_set (FALSE);
if (opt_disable_userns)
{
/* Verify that we can't make a new userns again */
res = unshare (CLONE_NEWUSER);
if (res == 0)
die ("unable to disable creation of new user namespaces");
}
write_uid_gid_map (opt_sandbox_uid, ns_uid, write_uid_gid_map (opt_sandbox_uid, ns_uid,
opt_sandbox_gid, ns_gid, opt_sandbox_gid, ns_gid,
-1, FALSE, FALSE); -1, FALSE, FALSE);
} }
if (opt_disable_userns || opt_assert_userns_disabled)
{
/* Verify that we can't make a new userns again */
res = unshare (CLONE_NEWUSER);
if (res == 0)
die ("creation of new user namespaces was not disabled as requested");
}
/* All privileged ops are done now, so drop caps we don't need */ /* All privileged ops are done now, so drop caps we don't need */
drop_privs (!is_privileged, TRUE); drop_privs (!is_privileged, TRUE);

View File

@@ -158,6 +158,17 @@
in the setuid version of bubblewrap. in the setuid version of bubblewrap.
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--assert-userns-disabled</option></term>
<listitem><para>
Confirm that the process in the sandbox has been prevented from
creating further user namespaces, but without taking any particular
action to prevent that. For example, this can be combined with
<option>--userns</option> to check that the given user namespace
has already been set up to prevent the creation of further user
namespaces.
</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--pidns <arg choice="plain">FD</arg></option></term> <term><option>--pidns <arg choice="plain">FD</arg></option></term>
<listitem><para>Use an existing pid namespace instead of creating one. This is often used with --userns, because the pid namespace must be owned by the same user namespace that bwrap uses. </para> <listitem><para>Use an existing pid namespace instead of creating one. This is often used with --userns, because the pid namespace must be owned by the same user namespace that bwrap uses. </para>

View File

@@ -10,6 +10,7 @@ _bwrap() {
# Please keep sorted in LC_ALL=C order # Please keep sorted in LC_ALL=C order
local boolean_options=" local boolean_options="
--as-pid-1 --as-pid-1
--assert-userns-disabled
--clearenv --clearenv
--disable-userns --disable-userns
--help --help

View File

@@ -27,6 +27,7 @@ _bwrap_args=(
# Please sort alphabetically (in LC_ALL=C order) by option name # Please sort alphabetically (in LC_ALL=C order) by option name
'--add-seccomp-fd[Load and use seccomp rules from FD]: :_guard "[0-9]#" "file descriptor to read seccomp rules from"' '--add-seccomp-fd[Load and use seccomp rules from FD]: :_guard "[0-9]#" "file descriptor to read seccomp rules from"'
'--assert-userns-disabled[Fail unless further use of user namespace inside sandbox is disabled]'
'--args[Parse NUL-separated args from FD]: :_guard "[0-9]#" "file descriptor with NUL-separated arguments"' '--args[Parse NUL-separated args from FD]: :_guard "[0-9]#" "file descriptor with NUL-separated arguments"'
'--as-pid-1[Do not install a reaper process with PID=1]' '--as-pid-1[Do not install a reaper process with PID=1]'
'--bind-try[Equal to --bind but ignores non-existent SRC]:source:_files:destination:_files' '--bind-try[Equal to --bind but ignores non-existent SRC]:source:_files:destination:_files'

View File

@@ -126,10 +126,12 @@ else
echo "ok - can pivot to new rootfs recursively" echo "ok - can pivot to new rootfs recursively"
$BWRAP --dev-bind / / -- true $BWRAP --dev-bind / / -- true
! $BWRAP --assert-userns-disabled --dev-bind / / -- true
$BWRAP --unshare-user --disable-userns --dev-bind / / -- true $BWRAP --unshare-user --disable-userns --dev-bind / / -- true
! $BWRAP --unshare-user --disable-userns --dev-bind / / -- $BWRAP --dev-bind / / -- true ! $BWRAP --unshare-user --disable-userns --dev-bind / / -- $BWRAP --dev-bind / / -- true
$BWRAP --unshare-user --disable-userns --dev-bind / / -- sh -c "echo 2 > /proc/sys/user/max_user_namespaces || true; ! $BWRAP --dev-bind / / -- true" $BWRAP --unshare-user --disable-userns --dev-bind / / -- sh -c "echo 2 > /proc/sys/user/max_user_namespaces || true; ! $BWRAP --dev-bind / / -- true"
$BWRAP --unshare-user --disable-userns --dev-bind / / -- sh -c "echo 100 > /proc/sys/user/max_user_namespaces || true; ! $BWRAP --dev-bind / / -- true" $BWRAP --unshare-user --disable-userns --dev-bind / / -- sh -c "echo 100 > /proc/sys/user/max_user_namespaces || true; ! $BWRAP --dev-bind / / -- true"
$BWRAP --unshare-user --disable-userns --dev-bind / / -- sh -c "! $BWRAP --dev-bind / / --assert-userns-disabled -- true"
echo "ok - can disable nested userns" echo "ok - can disable nested userns"
fi fi