diff --git a/bubblewrap.c b/bubblewrap.c index de06305..267b369 100644 --- a/bubblewrap.c +++ b/bubblewrap.c @@ -72,6 +72,7 @@ static const char *opt_exec_label = NULL; static const char *opt_file_label = NULL; static bool opt_as_pid_1; +static const char *opt_argv0 = NULL; static const char *opt_chdir_path = NULL; static bool opt_assert_userns_disabled = FALSE; static bool opt_disable_userns = FALSE; @@ -309,6 +310,7 @@ usage (int ecode, FILE *out) " --help Print this help\n" " --version Print version\n" " --args FD Parse NUL-separated args from FD\n" + " --argv0 VALUE Set argv[0] to the value VALUE before running the program\n" " --unshare-all Unshare every namespace we support by default\n" " --share-net Retain the network namespace (can only combine with --unshare-all)\n" " --unshare-user Create new user namespace (may be automatically implied if not setuid)\n" @@ -1728,6 +1730,18 @@ parse_args_recurse (int *argcp, argv += 1; argc -= 1; } + else if (strcmp (arg, "--argv0") == 0) + { + if (argc < 2) + die ("--argv0 takes one argument"); + + if (opt_argv0 != NULL) + die ("--argv0 used multiple times"); + + opt_argv0 = argv[1]; + argv++; + argc--; + } else if (strcmp (arg, "--unshare-all") == 0) { /* Keep this in order with the older (legacy) --unshare arguments, @@ -2641,6 +2655,7 @@ main (int argc, int res UNUSED; cleanup_free char *args_data UNUSED = NULL; int intermediate_pids_sockets[2] = {-1, -1}; + const char *exec_path = NULL; /* Handle --version early on before we try to acquire/drop * any capabilities so it works in a build environment; @@ -3351,7 +3366,11 @@ main (int argc, we don't want to error out here */ } - if (execvp (argv[0], argv) == -1) + exec_path = argv[0]; + if (opt_argv0 != NULL) + argv[0] = (char *) opt_argv0; + + if (execvp (exec_path, argv) == -1) { if (setup_finished_pipe[1] != -1) { @@ -3362,7 +3381,7 @@ main (int argc, /* Ignore res, if e.g. the parent died and closed setup_finished_pipe[0] we don't want to error out here */ } - die_with_error ("execvp %s", argv[0]); + die_with_error ("execvp %s", exec_path); } return 0; diff --git a/bwrap.xml b/bwrap.xml index 9d770ac..e655524 100644 --- a/bwrap.xml +++ b/bwrap.xml @@ -92,6 +92,10 @@ multiple sources. + + + Set argv[0] to the value VALUE before running the program + Options related to kernel namespaces: diff --git a/completions/bash/bwrap b/completions/bash/bwrap index ca18d89..e6d2846 100644 --- a/completions/bash/bwrap +++ b/completions/bash/bwrap @@ -32,6 +32,7 @@ _bwrap() { $boolean_optons --add-seccomp-fd --args + --argv0 --bind --bind-data --block-fd diff --git a/completions/zsh/_bwrap b/completions/zsh/_bwrap index a2e2caf..fbddda4 100644 --- a/completions/zsh/_bwrap +++ b/completions/zsh/_bwrap @@ -29,6 +29,7 @@ _bwrap_args=( '--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"' + '--argv0[Set argv0 to the value VALUE before running the program]:value:' '--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[Bind mount the host path SRC on DEST]:source:_files:destination:_files' diff --git a/tests/test-run.sh b/tests/test-run.sh index a90f0b1..2d9d385 100755 --- a/tests/test-run.sh +++ b/tests/test-run.sh @@ -8,7 +8,7 @@ srcd=$(cd $(dirname "$0") && pwd) bn=$(basename "$0") -echo "1..58" +echo "1..59" # Test help ${BWRAP} --help > help.txt @@ -532,4 +532,12 @@ echo "PWD=$(pwd -P)" > reference assert_files_equal stdout reference echo "ok - environment manipulation" +$RUN sh -c 'echo $0' > stdout +assert_file_has_content stdout sh +$RUN --argv0 sh sh -c 'echo $0' > stdout +assert_file_has_content stdout sh +$RUN --argv0 right sh -c 'echo $0' > stdout +assert_file_has_content stdout right +echo "ok - argv0 manipulation" + echo "ok - End of test"