5959 * 2^64 - 2^12. */
6060#define MAX_TMPFS_BYTES ((size_t) (SIZE_MAX >> 1))
6161
62+ #define LATEST_COMPAT_LEVEL 1
63+
6264/* Globals to avoid having to use getuid(), since the uid/gid changes during runtime */
6365static uid_t real_uid ;
6466static gid_t real_gid ;
@@ -75,6 +77,7 @@ static bool opt_as_pid_1;
7577static const char * opt_chdir_path = NULL ;
7678static bool opt_assert_userns_disabled = FALSE;
7779static bool opt_disable_userns = FALSE;
80+ static bool opt_disable_userns_set = FALSE;
7881static bool opt_unshare_user = FALSE;
7982static bool opt_unshare_user_try = FALSE;
8083static bool opt_unshare_pid = FALSE;
@@ -85,6 +88,7 @@ static bool opt_unshare_cgroup = FALSE;
8588static bool opt_unshare_cgroup_try = FALSE;
8689static bool opt_needs_devpts = FALSE;
8790static bool opt_new_session = FALSE;
91+ static bool opt_new_session_set = FALSE;
8892static bool opt_die_with_parent = FALSE;
8993static uid_t opt_sandbox_uid = -1 ;
9094static gid_t opt_sandbox_gid = -1 ;
@@ -99,6 +103,7 @@ static char *opt_args_data = NULL; /* owned */
99103static int opt_userns_fd = -1 ;
100104static int opt_userns2_fd = -1 ;
101105static int opt_pidns_fd = -1 ;
106+ static int opt_compat_level = 0 ;
102107static int next_perms = -1 ;
103108static size_t next_size_arg = 0 ;
104109
@@ -308,6 +313,7 @@ usage (int ecode, FILE *out)
308313 fprintf (out ,
309314 " --help Print this help\n"
310315 " --version Print version\n"
316+ " --compat Set compatability level (negative value means latest)\n"
311317 " --args FD Parse NUL-separated args from FD\n"
312318 " --unshare-all Unshare every namespace we support by default\n"
313319 " --share-net Retain the network namespace (can only combine with --unshare-all)\n"
@@ -321,7 +327,7 @@ usage (int ecode, FILE *out)
321327 " --unshare-cgroup-try Create new cgroup namespace if possible else continue by skipping it\n"
322328 " --userns FD Use this user namespace (cannot combine with --unshare-user)\n"
323329 " --userns2 FD After setup switch to this user namespace, only useful with --userns\n"
324- " -- disable-userns Disable further use of user namespaces inside sandbox\n"
330+ "%s" /* --( disable/allow) -userns */
325331 " --assert-userns-disabled Fail unless further use of user namespace inside sandbox is disabled\n"
326332 " --pidns FD Use this pid namespace (as parent namespace if using --unshare-pid)\n"
327333 " --uid UID Custom uid in the sandbox (requires --unshare-user or --userns)\n"
@@ -357,15 +363,20 @@ usage (int ecode, FILE *out)
357363 " --userns-block-fd FD Block on FD until the user namespace is ready\n"
358364 " --info-fd FD Write information about the running container to FD\n"
359365 " --json-status-fd FD Write container status to FD as multiple JSON documents\n"
360- " -- new-session Create a new terminal session\n"
366+ "%s" /* -(-no)- new-session */
361367 " --die-with-parent Kills with SIGKILL child process (COMMAND) when bwrap or bwrap's parent dies.\n"
362368 " --as-pid-1 Do not install a reaper process with PID=1\n"
363369 " --cap-add CAP Add cap CAP when running as privileged user\n"
364370 " --cap-drop CAP Drop cap CAP when running as privileged user\n"
365371 " --perms OCTAL Set permissions of next argument (--bind-data, --file, etc.)\n"
366372 " --size BYTES Set size of next argument (only for --tmpfs)\n"
367- " --chmod OCTAL PATH Change permissions of PATH (must already exist)\n"
368- );
373+ " --chmod OCTAL PATH Change permissions of PATH (must already exist)\n" ,
374+ opt_compat_level == 0 ?
375+ " --disable-userns Disable further use of user namespaces inside sandbox\n" :
376+ " --allow-userns Allow further use of user namespaces inside sandbox\n" ,
377+ opt_compat_level == 0 ?
378+ " --new-session Create a new terminal session\n" :
379+ " --no-new-session Don't create a new terminal session\n" );
369380 exit (ecode );
370381}
371382
@@ -1652,18 +1663,43 @@ parse_args_recurse (int *argcp,
16521663 if (* total_parsed_argc_p > MAX_ARGS )
16531664 die ("Exceeded maximum number of arguments %u" , MAX_ARGS );
16541665
1666+ bool print_help = FALSE;
16551667 while (argc > 0 )
16561668 {
16571669 const char * arg = argv [0 ];
16581670
16591671 if (strcmp (arg , "--help" ) == 0 )
16601672 {
1661- usage (EXIT_SUCCESS , stdout );
1673+ /* Defer printing help as it now varies depending on the compat level. */
1674+ print_help = TRUE;
16621675 }
16631676 else if (strcmp (arg , "--version" ) == 0 )
16641677 {
16651678 print_version_and_exit ();
16661679 }
1680+ else if (strcmp (arg , "--compat" ) == 0 )
1681+ {
1682+ int the_compat_level ;
1683+ char * endptr ;
1684+
1685+ if (argc < 2 )
1686+ die ("--compat takes an argument" );
1687+
1688+ the_compat_level = strtol (argv [1 ], & endptr , 10 );
1689+ if (argv [1 ][0 ] == 0 || endptr [0 ] != 0 )
1690+ die ("Invalid compat level: %s" , argv [1 ]);
1691+
1692+ if (the_compat_level > LATEST_COMPAT_LEVEL )
1693+ die ("Compat level %d is not suported by this version (latest supported is %d)" , the_compat_level , LATEST_COMPAT_LEVEL );
1694+
1695+ if (the_compat_level < 0 )
1696+ the_compat_level = LATEST_COMPAT_LEVEL ;
1697+
1698+ opt_compat_level = the_compat_level ;
1699+
1700+ argv += 1 ;
1701+ argc -= 1 ;
1702+ }
16671703 else if (strcmp (arg , "--args" ) == 0 )
16681704 {
16691705 int the_fd ;
@@ -1789,13 +1825,20 @@ parse_args_recurse (int *argcp,
17891825 argv ++ ;
17901826 argc -- ;
17911827 }
1792- else if (strcmp (arg , "--disable-userns" ) == 0 )
1828+ else if (opt_compat_level == 0 && strcmp (arg , "--disable-userns" ) == 0 )
17931829 {
17941830 opt_disable_userns = TRUE;
1831+ opt_disable_userns_set = TRUE;
17951832 }
17961833 else if (strcmp (arg , "--assert-userns-disabled" ) == 0 )
17971834 {
17981835 opt_assert_userns_disabled = TRUE;
1836+ opt_disable_userns_set = TRUE;
1837+ }
1838+ else if (opt_compat_level > 0 && strcmp (arg , "--allow-userns" ) == 0 )
1839+ {
1840+ opt_disable_userns = FALSE;
1841+ opt_disable_userns_set = TRUE;
17991842 }
18001843 else if (strcmp (arg , "--remount-ro" ) == 0 )
18011844 {
@@ -1980,7 +2023,10 @@ parse_args_recurse (int *argcp,
19802023 if (next_perms >= 0 )
19812024 op -> perms = next_perms ;
19822025 else
1983- op -> perms = 0666 ;
2026+ if (opt_compat_level == 0 )
2027+ op -> perms = 0666 ;
2028+ else
2029+ op -> perms = 0644 ;
19842030
19852031 next_perms = -1 ;
19862032 argv += 2 ;
@@ -2176,7 +2222,12 @@ parse_args_recurse (int *argcp,
21762222 die ("--seccomp cannot be combined with --add-seccomp-fd" );
21772223
21782224 if (opt_seccomp_fd != -1 )
2179- warn_only_last_option ("--seccomp" );
2225+ {
2226+ if (opt_compat_level == 0 )
2227+ warn_only_last_option ("--seccomp" );
2228+ else
2229+ die ("More than one --seccomp options specified, use --add-seccomp-fd instead." );
2230+ }
21802231
21812232 the_fd = strtol (argv [1 ], & endptr , 10 );
21822233 if (argv [1 ][0 ] == 0 || endptr [0 ] != 0 || the_fd < 0 )
@@ -2349,9 +2400,15 @@ parse_args_recurse (int *argcp,
23492400 argv += 1 ;
23502401 argc -= 1 ;
23512402 }
2352- else if (strcmp (arg , "--new-session" ) == 0 )
2403+ else if (opt_compat_level == 0 && strcmp (arg , "--new-session" ) == 0 )
23532404 {
23542405 opt_new_session = TRUE;
2406+ opt_new_session_set = TRUE;
2407+ }
2408+ else if (opt_compat_level > 0 && strcmp (arg , "--no-new-session" ) == 0 )
2409+ {
2410+ opt_new_session = FALSE;
2411+ opt_new_session_set = TRUE;
23552412 }
23562413 else if (strcmp (arg , "--die-with-parent" ) == 0 )
23572414 {
@@ -2526,6 +2583,15 @@ parse_args_recurse (int *argcp,
25262583 argc -- ;
25272584 }
25282585
2586+ if (print_help )
2587+ usage (EXIT_SUCCESS , stdout );
2588+
2589+ if (opt_compat_level > 0 && opt_unshare_user && !opt_disable_userns_set )
2590+ opt_disable_userns = TRUE;
2591+
2592+ if (opt_compat_level > 0 && !opt_new_session_set )
2593+ opt_new_session = TRUE;
2594+
25292595 * argcp = argc ;
25302596 * argvp = argv ;
25312597}
0 commit comments