LOG_I
("Jail parameters: hostname:'%s', chroot:'%s', process:'%s', port:%d, "
- "max_conns_per_ip:%u, uid:%u, gid:%u, time_limit:%ld, personality:%#lx, daemonize:%s, "
+ "max_conns_per_ip:%u, uid:(ns:%u, global:%u), gid:(ns:%u, global:%u), time_limit:%ld, personality:%#lx, daemonize:%s, "
"clone_newnet:%s, clone_newuser:%s, clone_newns:%s, clone_newpid:%s, "
"clone_newipc:%s, clonew_newuts:%s, apply_sandbox:%s, keep_caps:%s, "
"tmpfs_size:%zu",
nsjconf->hostname, nsjconf->chroot, nsjconf->argv[0], nsjconf->port,
- nsjconf->max_conns_per_ip, nsjconf->uid, nsjconf->gid, nsjconf->tlimit,
- nsjconf->personality, logYesNo(nsjconf->daemonize), logYesNo(nsjconf->clone_newnet),
+ nsjconf->max_conns_per_ip, nsjconf->inside_uid, nsjconf->outside_uid,
+ nsjconf->inside_gid, nsjconf->outside_gid, nsjconf->tlimit, nsjconf->personality,
+ logYesNo(nsjconf->daemonize), logYesNo(nsjconf->clone_newnet),
logYesNo(nsjconf->clone_newuser), logYesNo(nsjconf->clone_newns),
logYesNo(nsjconf->clone_newpid), logYesNo(nsjconf->clone_newipc),
logYesNo(nsjconf->clone_newuts), logYesNo(nsjconf->apply_sandbox),
/* findSpecDestination mutates spec (source:dest) to have a null byte instead
* of ':' in between source and dest, then returns a pointer to the dest
* string. */
-static char *cmdlineMountParam(char *spec)
+static char *cmdlineSplitStrByColon(char *spec)
{
char *dest = spec;
while (*dest != ':' && *dest != '\0') {
}
}
+static bool cmdlineParseUid(struct nsjconf_t *nsjconf, char *str)
+{
+ if (str == NULL) {
+ return true;
+ }
+
+ char *second = cmdlineSplitStrByColon(str);
+
+ struct passwd *pw = getpwnam(str);
+ if (pw != NULL) {
+ nsjconf->inside_uid = pw->pw_uid;
+ } else if (cmdlineIsANumber(str)) {
+ nsjconf->inside_uid = (uid_t) strtoull(str, NULL, 0);
+ } else {
+ LOG_E("No such user '%s'", str);
+ return false;
+ }
+
+ if (str == second) {
+ return true;
+ }
+
+ pw = getpwnam(second);
+ if (pw != NULL) {
+ nsjconf->outside_uid = pw->pw_uid;
+ } else if (cmdlineIsANumber(second)) {
+ nsjconf->outside_uid = (uid_t) strtoull(second, NULL, 0);
+ } else {
+ LOG_E("No such user '%s'", second);
+ return false;
+ }
+ return true;
+}
+
+static bool cmdlineParseGid(struct nsjconf_t *nsjconf, char *str)
+{
+ if (str == NULL) {
+ return true;
+ }
+
+ char *second = cmdlineSplitStrByColon(str);
+
+ struct group *gr = getgrnam(str);
+ if (gr != NULL) {
+ nsjconf->inside_gid = gr->gr_gid;
+ } else if (cmdlineIsANumber(str)) {
+ nsjconf->inside_gid = (gid_t) strtoull(str, NULL, 0);
+ } else {
+ LOG_E("No such group '%s'", str);
+ return false;
+ }
+
+ if (str == second) {
+ return true;
+ }
+
+ gr = getgrnam(second);
+ if (gr != NULL) {
+ nsjconf->outside_gid = gr->gr_gid;
+ } else if (cmdlineIsANumber(second)) {
+ nsjconf->outside_gid = (gid_t) strtoull(second, NULL, 0);
+ } else {
+ LOG_E("No such group '%s'", second);
+ return false;
+ }
+ return true;
+}
+
bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
{
/* *INDENT-OFF* */
.chroot = "",
.argv = NULL,
.port = 31337,
- .uid = -1,
- .gid = -1,
.daemonize = false,
.tlimit = 0,
.apply_sandbox = true,
.is_root_rw = false,
.is_silent = false,
.iface = NULL,
- .initial_uid = getuid(),
- .initial_gid = getgid(),
+ .inside_uid = getuid(),
+ .inside_gid = getgid(),
+ .outside_uid = getuid(),
+ .outside_gid = getgid(),
.max_conns_per_ip = 0,
.tmpfs_size = 4 * (1024 * 1024),
.mount_proc = true,
TAILQ_INIT(&nsjconf->pids);
TAILQ_INIT(&nsjconf->mountpts);
- const char *user = "nobody";
- const char *group = "nobody";
+ char *user = NULL;
+ char *group = NULL;
const char *logfile = NULL;
static char cmdlineTmpfsSz[PATH_MAX] = "size=4194304";
{
struct mounts_t *p = util_malloc(sizeof(struct mounts_t));
p->src = optarg;
- p->dst = cmdlineMountParam(optarg);
+ p->dst = cmdlineSplitStrByColon(optarg);
p->flags = MS_BIND | MS_REC | MS_PRIVATE | MS_RDONLY;
p->options = NULL;
p->fs_type = NULL;
{
struct mounts_t *p = util_malloc(sizeof(struct mounts_t));
p->src = optarg;
- p->dst = cmdlineMountParam(optarg);
+ p->dst = cmdlineSplitStrByColon(optarg);
p->flags = MS_BIND | MS_REC | MS_PRIVATE;
p->options = NULL;
p->fs_type = NULL;
return false;
}
- nsjconf->argv = &argv[optind];
- if (nsjconf->argv[0] == NULL) {
- LOG_E("No command provided");
- cmdlineUsage(argv[0], custom_opts);
+ if (cmdlineParseUid(nsjconf, user) == false) {
return false;
}
-
- struct passwd *pw = getpwnam(user);
- if (pw != NULL) {
- nsjconf->uid = pw->pw_uid;
- } else if (cmdlineIsANumber(user)) {
- nsjconf->uid = (uid_t) strtoull(user, NULL, 0);
- } else {
- LOG_E("No such user '%s'", user);
+ if (cmdlineParseGid(nsjconf, group) == false) {
return false;
}
- struct group *gr = getgrnam(group);
- if (gr != NULL) {
- nsjconf->gid = gr->gr_gid;
- } else if (cmdlineIsANumber(group)) {
- nsjconf->gid = (gid_t) strtoull(group, NULL, 0);
- } else {
- LOG_E("No such group '%s'", group);
+
+ nsjconf->argv = &argv[optind];
+ if (nsjconf->argv[0] == NULL) {
+ LOG_E("No command provided");
+ cmdlineUsage(argv[0], custom_opts);
return false;
}
return true;
}
-static bool containUidGidMap(struct nsjconf_t *nsjconf, uid_t uid, gid_t gid)
+static bool containUidGidMap(struct nsjconf_t *nsjconf)
{
if (nsjconf->clone_newuser == false) {
return true;
PLOG_E("open('/proc/self/uid_map', O_WRONLY | O_CLOEXEC)");
return false;
}
- snprintf(map, sizeof(map), "%lu %lu 1", (unsigned long)uid,
- (unsigned long)nsjconf->initial_uid);
+ snprintf(map, sizeof(map), "%lu %lu 1", (unsigned long)nsjconf->inside_uid,
+ (unsigned long)nsjconf->outside_uid);
LOG_D("Writing '%s' to /proc/self/uid_map", map);
if (write(fd, map, strlen(map)) == -1) {
PLOG_E("write('/proc/self/uid_map', %d, '%s')", fd, map);
PLOG_E("open('/proc/self/gid_map', O_WRONLY | O_CLOEXEC)");
return false;
}
- snprintf(map, sizeof(map), "%lu %lu 1", (unsigned long)gid,
- (unsigned long)nsjconf->initial_gid);
+ snprintf(map, sizeof(map), "%lu %lu 1", (unsigned long)nsjconf->inside_gid,
+ (unsigned long)nsjconf->outside_gid);
LOG_D("Writing '%s' to /proc/self/gid_map", map);
if (write(fd, map, strlen(map)) == -1) {
PLOG_E("write('/proc/self/gid_map', %d, '%s')", fd, map);
if (containSetGroups() == false) {
return false;
}
- if (containUidGidMap(nsjconf, nsjconf->uid, nsjconf->gid) == false) {
+ if (containUidGidMap(nsjconf) == false) {
return false;
}
return true;
if (setgroups(0, group_list) == -1) {
PLOG_D("setgroups(NULL) failed");
}
- if (setresgid(nsjconf->gid, nsjconf->gid, nsjconf->gid) == -1) {
- PLOG_E("setresgid(%u)", nsjconf->gid);
+ if (setresgid(nsjconf->inside_gid, nsjconf->inside_gid, nsjconf->inside_gid) == -1) {
+ PLOG_E("setresgid(%u)", nsjconf->inside_gid);
return false;
}
- if (setresuid(nsjconf->uid, nsjconf->uid, nsjconf->uid) == -1) {
- PLOG_E("setresuid(%u)", nsjconf->uid);
+ if (setresuid(nsjconf->inside_uid, nsjconf->inside_uid, nsjconf->inside_uid) == -1) {
+ PLOG_E("setresuid(%u)", nsjconf->inside_uid);
return false;
}
#ifndef PR_SET_NO_NEW_PRIVS