SETGROUPS_ALLOW = 1,
};
+enum {
+ MAP_USER_NONE,
+ MAP_USER_ROOT,
+ MAP_USER_CURRENT,
+};
+
static const char *setgroups_strings[] =
{
[SETGROUPS_DENY] = "deny",
fputs(USAGE_SEPARATOR, out);
fputs(_(" -f, --fork fork before launching <program>\n"), out);
fputs(_(" -r, --map-root-user map current user to root (implies --user)\n"), out);
+ fputs(_(" -c, --map-current-user map current user to itself (implies --user)\n"), out);
fputs(USAGE_SEPARATOR, out);
fputs(_(" --kill-child[=<signame>] when dying, kill the forked child (implies --fork)\n"
" defaults to SIGKILL\n"), out);
{ "kill-child", optional_argument, NULL, OPT_KILLCHILD },
{ "mount-proc", optional_argument, NULL, OPT_MOUNTPROC },
{ "map-root-user", no_argument, NULL, 'r' },
+ { "map-current-user", no_argument, NULL, 'c' },
{ "propagation", required_argument, NULL, OPT_PROPAGATION },
{ "setgroups", required_argument, NULL, OPT_SETGROUPS },
{ "setuid", required_argument, NULL, 'S' },
int setgrpcmd = SETGROUPS_NONE;
int unshare_flags = 0;
- int c, forkit = 0, maproot = 0;
+ int c, forkit = 0, mapuser = MAP_USER_NONE;
int kill_child_signo = 0; /* 0 means --kill-child was not used */
const char *procmnt = NULL;
const char *newroot = NULL;
procmnt = optarg ? optarg : "/proc";
break;
case 'r':
+ if (mapuser == MAP_USER_CURRENT)
+ errx(EXIT_FAILURE, _("options --map-root-user and "
+ "--map-current-user are mutually exclusive"));
+
+ unshare_flags |= CLONE_NEWUSER;
+ mapuser = MAP_USER_ROOT;
+ break;
+ case 'c':
+ if (mapuser == MAP_USER_ROOT)
+ errx(EXIT_FAILURE, _("options --map-root-user and "
+ "--map-current-user are mutually exclusive"));
+
unshare_flags |= CLONE_NEWUSER;
- maproot = 1;
+ mapuser = MAP_USER_CURRENT;
break;
case OPT_SETGROUPS:
setgrpcmd = setgroups_str2id(optarg);
if (kill_child_signo != 0 && prctl(PR_SET_PDEATHSIG, kill_child_signo) < 0)
err(EXIT_FAILURE, "prctl failed");
- if (maproot) {
+ /* Since Linux 3.19 unprivileged writing of /proc/self/gid_map
+ * has been disabled unless /proc/self/setgroups is written
+ * first to permanently disable the ability to call setgroups
+ * in that user namespace. */
+ switch (mapuser) {
+ case MAP_USER_ROOT:
if (setgrpcmd == SETGROUPS_ALLOW)
errx(EXIT_FAILURE, _("options --setgroups=allow and "
"--map-root-user are mutually exclusive"));
- /* since Linux 3.19 unprivileged writing of /proc/self/gid_map
- * has s been disabled unless /proc/self/setgroups is written
- * first to permanently disable the ability to call setgroups
- * in that user namespace. */
setgroups_control(SETGROUPS_DENY);
map_id(_PATH_PROC_UIDMAP, 0, real_euid);
map_id(_PATH_PROC_GIDMAP, 0, real_egid);
+ break;
+ case MAP_USER_CURRENT:
+ if (setgrpcmd == SETGROUPS_ALLOW)
+ errx(EXIT_FAILURE, _("options --setgroups=allow and "
+ "--map-current-user are mutually exclusive"));
- } else if (setgrpcmd != SETGROUPS_NONE)
- setgroups_control(setgrpcmd);
+ setgroups_control(SETGROUPS_DENY);
+ map_id(_PATH_PROC_UIDMAP, real_euid, real_euid);
+ map_id(_PATH_PROC_GIDMAP, real_egid, real_egid);
+ break;
+ case MAP_USER_NONE:
+ if (setgrpcmd != SETGROUPS_NONE)
+ setgroups_control(setgrpcmd);
+ }
if ((unshare_flags & CLONE_NEWNS) && propagation)
set_propagation(propagation);