*--mount-proc*[**=**__mountpoint__]::
Just before running the program, mount the proc filesystem at _mountpoint_ (default is _/proc_). This is useful when creating a new PID namespace. It also implies creating a new mount namespace since the _/proc_ mount would otherwise mess up existing programs on the system. The new proc filesystem is explicitly mounted as private (with *MS_PRIVATE*|*MS_REC*).
+*--mount-binfmt*[**=**__mountpoint__]::
+Just before running the program, mount the binfmt_misc filesystem at _mountpoint_ (default is /proc/sys/fs/binfmt_misc). It also implies creating a new mount namespace since the binfmt_misc mount would otherwise mess up existing programs on the system. The new binfmt_misc filesystem is explicitly mounted as private (with *MS_PRIVATE*|*MS_REC*).
+
**--map-user=**__uid|name__::
Run the program only after the current effective user ID has been mapped to _uid_. If this option is specified multiple times, the last occurrence takes precedence. This option implies *--user*.
fputs(_(" --kill-child[=<signame>] when dying, kill the forked child (implies --fork)\n"
" defaults to SIGKILL\n"), out);
fputs(_(" --mount-proc[=<dir>] mount proc filesystem first (implies --mount)\n"), out);
+ fputs(_(" --mount-binfmt[=<dir>] mount binfmt filesystem first (implies --user and --mount)\n"), out);
fputs(_(" --propagation slave|shared|private|unchanged\n"
" modify mount propagation in mount namespace\n"), out);
fputs(_(" --setgroups allow|deny control the setgroups syscall in user namespaces\n"), out);
{
enum {
OPT_MOUNTPROC = CHAR_MAX + 1,
+ OPT_MOUNTBINFMT,
OPT_PROPAGATION,
OPT_SETGROUPS,
OPT_KILLCHILD,
{ "fork", no_argument, NULL, 'f' },
{ "kill-child", optional_argument, NULL, OPT_KILLCHILD },
{ "mount-proc", optional_argument, NULL, OPT_MOUNTPROC },
+ { "mount-binfmt", optional_argument, NULL, OPT_MOUNTBINFMT },
{ "map-user", required_argument, NULL, OPT_MAPUSER },
{ "map-users", required_argument, NULL, OPT_MAPUSERS },
{ "map-group", required_argument, NULL, OPT_MAPGROUP },
struct map_range *groupmap = NULL;
int kill_child_signo = 0; /* 0 means --kill-child was not used */
const char *procmnt = NULL;
+ const char *binfmt_mnt = NULL;
const char *newroot = NULL;
const char *newdir = NULL;
pid_t pid_bind = 0, pid_idmap = 0;
unshare_flags |= CLONE_NEWNS;
procmnt = optarg ? optarg : "/proc";
break;
+ case OPT_MOUNTBINFMT:
+ unshare_flags |= CLONE_NEWNS | CLONE_NEWUSER;
+ binfmt_mnt = optarg;
+ if (!binfmt_mnt) {
+ if (!procmnt)
+ procmnt = "/proc";
+ binfmt_mnt = _PATH_PROC_BINFMT_MISC;
+ }
+ break;
case OPT_MAPUSER:
unshare_flags |= CLONE_NEWUSER;
mapuser = get_user(optarg, _("failed to parse uid"));
err(EXIT_FAILURE, _("mount %s failed"), procmnt);
}
+ if (binfmt_mnt) {
+ if (mount("binfmt_misc", binfmt_mnt, "binfmt_misc",
+ MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) != 0)
+ err(EXIT_FAILURE, _("mount %s failed"), binfmt_mnt);
+ }
+
if (force_gid) {
if (setgroups(0, NULL) != 0) /* drop supplementary groups */
err(EXIT_FAILURE, _("setgroups failed"));