Rewrite uid mapping system
This commit is contained in:
parent
a2a497f089
commit
4eaa6cc9d3
2
Makefile
2
Makefile
@ -102,7 +102,7 @@ indent:
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
nsjail.o: nsjail.h common.h cmdline.h log.h net.h subproc.h
|
||||
cmdline.o: cmdline.h common.h config.h log.h mount.h util.h
|
||||
cmdline.o: cmdline.h common.h config.h log.h mount.h util.h user.h
|
||||
config.o: common.h config.h log.h util.h
|
||||
contain.o: contain.h common.h cgroup.h log.h mount.h net.h pid.h user.h
|
||||
contain.o: util.h uts.h
|
||||
|
224
cmdline.c
224
cmdline.c
@ -45,6 +45,7 @@
|
||||
#include "log.h"
|
||||
#include "mount.h"
|
||||
#include "util.h"
|
||||
#include "user.h"
|
||||
|
||||
struct custom_option {
|
||||
struct option opt;
|
||||
@ -67,8 +68,8 @@ struct custom_option custom_opts[] = {
|
||||
{{"config", required_argument, NULL, 'C'}, "Configuration file in the config.proto ProtoBuf format"},
|
||||
{{"chroot", required_argument, NULL, 'c'}, "Directory containing / of the jail (default: none)"},
|
||||
{{"rw", no_argument, NULL, 0x601}, "Mount / and /proc as RW (default: RO)"},
|
||||
{{"user", required_argument, NULL, 'u'}, "Username/uid of processess inside the jail (default: your current uid). You can also use inside_ns_uid:outside_ns_uid convention here. Can be specified multiple times"},
|
||||
{{"group", required_argument, NULL, 'g'}, "Groupname/gid of processess inside the jail (default: your current gid). You can also use inside_ns_gid:global_ns_gid convention here. Can be specified multiple times"},
|
||||
{{"user", required_argument, NULL, 'u'}, "Username/uid of processess inside the jail (default: your current uid). You can also use inside_ns_uid:outside_ns_uid:count convention here. Can be specified multiple times"},
|
||||
{{"group", required_argument, NULL, 'g'}, "Groupname/gid of processess inside the jail (default: your current gid). You can also use inside_ns_gid:global_ns_gid:count convention here. Can be specified multiple times"},
|
||||
{{"hostname", required_argument, NULL, 'H'}, "UTS name (hostname) of the jail (default: 'NSJAIL')"},
|
||||
{{"cwd", required_argument, NULL, 'D'}, "Directory in the namespace the process will run (default: '/')"},
|
||||
{{"port", required_argument, NULL, 'p'}, "TCP port to bind to (enables MODE_LISTEN_TCP) (default: 0)"},
|
||||
@ -233,13 +234,15 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
|
||||
{
|
||||
struct idmap_t *p;
|
||||
TAILQ_FOREACH(p, &nsjconf->uids, pointers) {
|
||||
LOG_I("Uid map: inside_uid:%d outside_uid:%d", p->inside_id, p->outside_id);
|
||||
LOG_I("Uid map: inside_uid:%d outside_uid:%d count:%zu", p->inside_id,
|
||||
p->outside_id, p->count);
|
||||
if (p->outside_id == 0) {
|
||||
LOG_W("Process will be UID/EUID=0 in the global user namespace");
|
||||
}
|
||||
}
|
||||
TAILQ_FOREACH(p, &nsjconf->gids, pointers) {
|
||||
LOG_I("Gid map: inside_gid:%d outside_gid:%d", p->inside_id, p->outside_id);
|
||||
LOG_I("Gid map: inside_gid:%d outside_gid:%d count:%zu", p->inside_id,
|
||||
p->outside_id, p->count);
|
||||
if (p->outside_id == 0) {
|
||||
LOG_W("Process will be GID/EGID=0 in the global user namespace");
|
||||
}
|
||||
@ -247,17 +250,17 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
|
||||
}
|
||||
|
||||
{
|
||||
struct mapping_t *p;
|
||||
TAILQ_FOREACH(p, &nsjconf->uid_mappings, pointers) {
|
||||
LOG_I("Newuid mapping: inside_uid:'%s' outside_uid:'%s' count:'%s'",
|
||||
struct idmap_t *p;
|
||||
TAILQ_FOREACH(p, &nsjconf->uid_newuidmap, pointers) {
|
||||
LOG_I("Newuid mapping: inside_uid:%u outside_uid:%u count:%zu",
|
||||
p->inside_id, p->outside_id, p->count);
|
||||
if (p->outside_id == 0) {
|
||||
LOG_W("Process will be UID/EUID=0 in the global user namespace");
|
||||
}
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(p, &nsjconf->gid_mappings, pointers) {
|
||||
LOG_I("Newgid mapping: inside_uid:'%s' outside_uid:'%s' count:'%s'",
|
||||
TAILQ_FOREACH(p, &nsjconf->gid_newuidmap, pointers) {
|
||||
LOG_I("Newgid mapping: inside_uid:%u outside_uid:%u count:%zu",
|
||||
p->inside_id, p->outside_id, p->count);
|
||||
if (p->outside_id == 0) {
|
||||
LOG_W("Process will be GID/EGID=0 in the global user namespace");
|
||||
@ -266,16 +269,6 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
|
||||
}
|
||||
}
|
||||
|
||||
static bool cmdlineIsANumber(const char *s)
|
||||
{
|
||||
for (int i = 0; s[i]; s++) {
|
||||
if (!isdigit(s[i]) && s[i] != 'x') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
__rlim64_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
|
||||
{
|
||||
struct rlimit64 cur;
|
||||
@ -288,7 +281,7 @@ __rlim64_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
|
||||
if (strcasecmp(optarg, "def") == 0) {
|
||||
return cur.rlim_cur;
|
||||
}
|
||||
if (cmdlineIsANumber(optarg) == false) {
|
||||
if (utilIsANumber(optarg) == false) {
|
||||
LOG_F("RLIMIT %d needs a numeric or 'max'/'def' value ('%s' provided)", res,
|
||||
optarg);
|
||||
}
|
||||
@ -304,6 +297,10 @@ __rlim64_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
|
||||
* string. */
|
||||
static char *cmdlineSplitStrByColon(char *spec)
|
||||
{
|
||||
if (spec == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *dest = spec;
|
||||
while (*dest != ':' && *dest != '\0') {
|
||||
dest++;
|
||||
@ -314,97 +311,13 @@ static char *cmdlineSplitStrByColon(char *spec)
|
||||
*dest = '\0';
|
||||
return dest + 1;
|
||||
case '\0':
|
||||
return spec;
|
||||
return NULL;
|
||||
default:
|
||||
// not reached
|
||||
return spec;
|
||||
LOG_F("Impossible condition in cmdlineSplitStrByColon()");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static bool cmdlineParseUid(struct nsjconf_t *nsjconf, char *str)
|
||||
{
|
||||
if (str == NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char *second = cmdlineSplitStrByColon(str);
|
||||
pid_t inside_uid;
|
||||
pid_t outside_uid;
|
||||
|
||||
struct passwd *pw = getpwnam(str);
|
||||
if (pw != NULL) {
|
||||
inside_uid = pw->pw_uid;
|
||||
} else if (cmdlineIsANumber(str)) {
|
||||
inside_uid = (uid_t) strtoull(str, NULL, 0);
|
||||
} else {
|
||||
LOG_E("No such user '%s'", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (str == second) {
|
||||
outside_uid = getuid();
|
||||
} else {
|
||||
pw = getpwnam(second);
|
||||
if (pw != NULL) {
|
||||
outside_uid = pw->pw_uid;
|
||||
} else if (cmdlineIsANumber(second)) {
|
||||
outside_uid = (uid_t) strtoull(second, NULL, 0);
|
||||
} else {
|
||||
LOG_E("No such user '%s'", second);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
struct idmap_t *p = utilMalloc(sizeof(struct idmap_t));
|
||||
p->inside_id = inside_uid;
|
||||
p->outside_id = outside_uid;
|
||||
TAILQ_INSERT_TAIL(&nsjconf->uids, p, pointers);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cmdlineParseGid(struct nsjconf_t *nsjconf, char *str)
|
||||
{
|
||||
if (str == NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char *second = cmdlineSplitStrByColon(str);
|
||||
gid_t inside_gid;
|
||||
gid_t outside_gid;
|
||||
|
||||
struct group *gr = getgrnam(str);
|
||||
if (gr != NULL) {
|
||||
inside_gid = gr->gr_gid;
|
||||
} else if (cmdlineIsANumber(str)) {
|
||||
inside_gid = (gid_t) strtoull(str, NULL, 0);
|
||||
} else {
|
||||
LOG_E("No such group '%s'", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (str == second) {
|
||||
outside_gid = getgid();
|
||||
} else {
|
||||
gr = getgrnam(second);
|
||||
if (gr != NULL) {
|
||||
outside_gid = gr->gr_gid;
|
||||
} else if (cmdlineIsANumber(second)) {
|
||||
outside_gid = (gid_t) strtoull(second, NULL, 0);
|
||||
} else {
|
||||
LOG_E("No such group '%s'", second);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
struct idmap_t *p = utilMalloc(sizeof(struct idmap_t));
|
||||
p->inside_id = inside_gid;
|
||||
p->outside_id = outside_gid;
|
||||
TAILQ_INSERT_TAIL(&nsjconf->gids, p, pointers);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
||||
{
|
||||
/* *INDENT-OFF* */
|
||||
@ -460,14 +373,14 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
TAILQ_INIT(&nsjconf->uids);
|
||||
TAILQ_INIT(&nsjconf->gids);
|
||||
TAILQ_INIT(&nsjconf->envs);
|
||||
TAILQ_INIT(&nsjconf->pids);
|
||||
TAILQ_INIT(&nsjconf->mountpts);
|
||||
TAILQ_INIT(&nsjconf->open_fds);
|
||||
TAILQ_INIT(&nsjconf->uid_mappings);
|
||||
TAILQ_INIT(&nsjconf->gid_mappings);
|
||||
TAILQ_INIT(&nsjconf->envs);
|
||||
TAILQ_INIT(&nsjconf->uids);
|
||||
TAILQ_INIT(&nsjconf->gids);
|
||||
TAILQ_INIT(&nsjconf->uid_newuidmap);
|
||||
TAILQ_INIT(&nsjconf->gid_newuidmap);
|
||||
|
||||
static char cmdlineTmpfsSz[PATH_MAX] = "size=4194304";
|
||||
|
||||
@ -528,16 +441,6 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
||||
case 'i':
|
||||
nsjconf->max_conns_per_ip = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'u':
|
||||
if (cmdlineParseUid(nsjconf, optarg) == false) {
|
||||
LOG_F("cmdlineParseUid('%s')", optarg);
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
if (cmdlineParseGid(nsjconf, optarg) == false) {
|
||||
LOG_F("cmdlineParseGid('%s')", optarg);
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
nsjconf->logfile = optarg;
|
||||
if (logInitLogFile(nsjconf) == false) {
|
||||
@ -663,17 +566,72 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
||||
p->val = optarg;
|
||||
TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers);
|
||||
} break;
|
||||
case 'U':
|
||||
case 'G':{
|
||||
struct mapping_t *p = utilMalloc(sizeof(struct mapping_t));
|
||||
p->inside_id = optarg;
|
||||
char *outside_id = cmdlineSplitStrByColon(optarg);
|
||||
p->outside_id = outside_id;
|
||||
p->count = cmdlineSplitStrByColon(outside_id);
|
||||
if (c == 'U') {
|
||||
TAILQ_INSERT_TAIL(&nsjconf->uid_mappings, p, pointers);
|
||||
case 'u':{
|
||||
char *i_id = optarg;
|
||||
char *o_id = cmdlineSplitStrByColon(i_id);
|
||||
char *cnt = cmdlineSplitStrByColon(o_id);
|
||||
size_t count = (cnt == NULL
|
||||
|| strlen(cnt) == 0) ? 1U : (size_t) strtoull(cnt,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
struct idmap_t *p =
|
||||
userParseId(i_id, o_id, count, false /* is_gid */ );
|
||||
if (p) {
|
||||
TAILQ_INSERT_TAIL(&nsjconf->uids, p, pointers);
|
||||
} else {
|
||||
TAILQ_INSERT_TAIL(&nsjconf->gid_mappings, p, pointers);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'g':{
|
||||
char *i_id = optarg;
|
||||
char *o_id = cmdlineSplitStrByColon(i_id);
|
||||
char *cnt = cmdlineSplitStrByColon(o_id);
|
||||
size_t count = (cnt == NULL
|
||||
|| strlen(cnt) == 0) ? 1U : (size_t) strtoull(cnt,
|
||||
NULL,
|
||||
0);
|
||||
struct idmap_t *p =
|
||||
userParseId(i_id, o_id, count, true /* is_gid */ );
|
||||
if (p) {
|
||||
TAILQ_INSERT_TAIL(&nsjconf->gids, p, pointers);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'U':{
|
||||
char *i_id = optarg;
|
||||
char *o_id = cmdlineSplitStrByColon(i_id);
|
||||
char *cnt = cmdlineSplitStrByColon(o_id);
|
||||
size_t count = (cnt == NULL
|
||||
|| strlen(cnt) == 0) ? 1U : (size_t) strtoull(cnt,
|
||||
NULL,
|
||||
0);
|
||||
struct idmap_t *p =
|
||||
userParseId(i_id, o_id, count, false /* is_gid */ );
|
||||
if (p) {
|
||||
TAILQ_INSERT_TAIL(&nsjconf->uid_newuidmap, p, pointers);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'G':{
|
||||
char *i_id = optarg;
|
||||
char *o_id = cmdlineSplitStrByColon(i_id);
|
||||
char *cnt = cmdlineSplitStrByColon(o_id);
|
||||
size_t count = (cnt == NULL
|
||||
|| strlen(cnt) == 0) ? 1U : (size_t) strtoull(cnt,
|
||||
NULL,
|
||||
0);
|
||||
struct idmap_t *p =
|
||||
userParseId(i_id, o_id, count, true /* is_gid */ );
|
||||
if (p) {
|
||||
TAILQ_INSERT_TAIL(&nsjconf->gid_newuidmap, p, pointers);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -822,12 +780,14 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
||||
struct idmap_t *p = utilMalloc(sizeof(struct idmap_t));
|
||||
p->inside_id = getuid();
|
||||
p->outside_id = getuid();
|
||||
p->count = 1U;
|
||||
TAILQ_INSERT_HEAD(&nsjconf->uids, p, pointers);
|
||||
}
|
||||
if (TAILQ_EMPTY(&nsjconf->gids)) {
|
||||
struct idmap_t *p = utilMalloc(sizeof(struct idmap_t));
|
||||
p->inside_id = getgid();
|
||||
p->outside_id = getgid();
|
||||
p->count = 1U;
|
||||
TAILQ_INSERT_HEAD(&nsjconf->gids, p, pointers);
|
||||
}
|
||||
|
||||
|
16
common.h
16
common.h
@ -74,16 +74,10 @@ struct mounts_t {
|
||||
TAILQ_ENTRY(mounts_t) pointers;
|
||||
};
|
||||
|
||||
struct mapping_t {
|
||||
const char *inside_id;
|
||||
const char *outside_id;
|
||||
const char *count;
|
||||
TAILQ_ENTRY(mapping_t) pointers;
|
||||
};
|
||||
|
||||
struct idmap_t {
|
||||
uid_t inside_id;
|
||||
uid_t outside_id;
|
||||
size_t count;
|
||||
TAILQ_ENTRY(idmap_t) pointers;
|
||||
};
|
||||
|
||||
@ -164,14 +158,14 @@ struct nsjconf_t {
|
||||
size_t cgroup_pids_max;
|
||||
FILE *kafel_file;
|
||||
char *kafel_string;
|
||||
TAILQ_HEAD(uidlist, idmap_t) uids;
|
||||
TAILQ_HEAD(gidlist, idmap_t) gids;
|
||||
TAILQ_HEAD(udmaplist, idmap_t) uids;
|
||||
TAILQ_HEAD(gdmaplist, idmap_t) gids;
|
||||
TAILQ_HEAD(newuidmaplist, idmap_t) uid_newuidmap;
|
||||
TAILQ_HEAD(newgidmaplist, idmap_t) gid_newuidmap;
|
||||
TAILQ_HEAD(envlist, charptr_t) envs;
|
||||
TAILQ_HEAD(pidslist, pids_t) pids;
|
||||
TAILQ_HEAD(mountptslist, mounts_t) mountpts;
|
||||
TAILQ_HEAD(fdslistt, fds_t) open_fds;
|
||||
TAILQ_HEAD(uidmaplistt, mapping_t) uid_mappings;
|
||||
TAILQ_HEAD(gidmaplistt, mapping_t) gid_mappings;
|
||||
};
|
||||
|
||||
#endif /* NS_COMMON_H */
|
||||
|
154
user.c
154
user.c
@ -24,12 +24,14 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "log.h"
|
||||
@ -65,8 +67,8 @@ static bool userUidMapSelf(struct nsjconf_t *nsjconf, pid_t pid)
|
||||
|
||||
struct idmap_t *p;
|
||||
TAILQ_FOREACH(p, &nsjconf->uids, pointers) {
|
||||
utilSSnPrintf(map, sizeof(map), "%lu %lu 1\n", (unsigned long)p->inside_id,
|
||||
(unsigned long)p->outside_id);
|
||||
utilSSnPrintf(map, sizeof(map), "%lu %lu %zu\n", (unsigned long)p->inside_id,
|
||||
(unsigned long)p->outside_id, p->count);
|
||||
}
|
||||
|
||||
LOG_D("Writing '%s' to '%s'", map, fname);
|
||||
@ -87,8 +89,8 @@ static bool userGidMapSelf(struct nsjconf_t *nsjconf, pid_t pid)
|
||||
|
||||
struct idmap_t *p;
|
||||
TAILQ_FOREACH(p, &nsjconf->gids, pointers) {
|
||||
utilSSnPrintf(map, sizeof(map), "%lu %lu 1\n", (unsigned long)p->inside_id,
|
||||
(unsigned long)p->outside_id);
|
||||
utilSSnPrintf(map, sizeof(map), "%lu %lu %zu\n", (unsigned long)p->inside_id,
|
||||
(unsigned long)p->outside_id, p->count);
|
||||
}
|
||||
|
||||
LOG_D("Writing '%s' to '%s'", map, fname);
|
||||
@ -103,23 +105,38 @@ static bool userGidMapSelf(struct nsjconf_t *nsjconf, pid_t pid)
|
||||
/* Use /usr/bin/newgidmap for writing the gid map */
|
||||
static bool userGidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
|
||||
{
|
||||
char pid_str[128];
|
||||
snprintf(pid_str, sizeof(pid_str), "%d", (int)pid);
|
||||
const char *argv[1024] = { "/usr/bin/newgidmap", pid_str };
|
||||
size_t argv_idx = 2;
|
||||
static size_t idx = 0;
|
||||
|
||||
struct mapping_t *p;
|
||||
TAILQ_FOREACH(p, &nsjconf->gid_mappings, pointers) {
|
||||
if (argv_idx >= ARRAYSIZE(argv)) {
|
||||
const char *argv[1024];
|
||||
char parms[1024][256];
|
||||
|
||||
argv[idx++] = "/usr/bin/newgidmap";
|
||||
|
||||
snprintf(parms[idx], sizeof(parms[idx]), "%u", (unsigned)pid);
|
||||
argv[idx] = parms[idx];
|
||||
idx++;
|
||||
|
||||
struct idmap_t *p;
|
||||
TAILQ_FOREACH(p, &nsjconf->gid_newuidmap, pointers) {
|
||||
if ((idx + 4) >= ARRAYSIZE(argv)) {
|
||||
LOG_W("Number of arguments to '/usr/bin/newgidmap' too big");
|
||||
return false;
|
||||
}
|
||||
|
||||
argv[argv_idx++] = p->inside_id;
|
||||
argv[argv_idx++] = p->outside_id;
|
||||
argv[argv_idx++] = p->count;
|
||||
snprintf(parms[idx], sizeof(parms[idx]), "%u", (unsigned)p->inside_id);
|
||||
argv[idx] = parms[idx];
|
||||
idx++;
|
||||
|
||||
snprintf(parms[idx], sizeof(parms[idx]), "%u", (unsigned)p->outside_id);
|
||||
argv[idx] = parms[idx];
|
||||
idx++;
|
||||
|
||||
snprintf(parms[idx], sizeof(parms[idx]), "%zu", p->count);
|
||||
argv[idx] = parms[idx];
|
||||
idx++;
|
||||
}
|
||||
argv[argv_idx++] = NULL;
|
||||
|
||||
argv[idx] = NULL;
|
||||
|
||||
if (subprocSystem(argv, environ) != 0) {
|
||||
LOG_E("'/usr/bin/newgidmap' failed");
|
||||
@ -132,23 +149,38 @@ static bool userGidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
|
||||
/* Use /usr/bin/newuidmap for writing the uid map */
|
||||
static bool userUidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
|
||||
{
|
||||
char pid_str[128];
|
||||
snprintf(pid_str, sizeof(pid_str), "%d", (int)pid);
|
||||
const char *argv[1024] = { "/usr/bin/newuidmap", pid_str };
|
||||
size_t argv_idx = 2;
|
||||
static size_t idx = 0;
|
||||
|
||||
struct mapping_t *p;
|
||||
TAILQ_FOREACH(p, &nsjconf->uid_mappings, pointers) {
|
||||
if (argv_idx >= ARRAYSIZE(argv)) {
|
||||
const char *argv[1024];
|
||||
char parms[1024][256];
|
||||
|
||||
argv[idx++] = "/usr/bin/newuidmap";
|
||||
|
||||
snprintf(parms[idx], sizeof(parms[idx]), "%u", (unsigned)pid);
|
||||
argv[idx] = parms[idx];
|
||||
idx++;
|
||||
|
||||
struct idmap_t *p;
|
||||
TAILQ_FOREACH(p, &nsjconf->uid_newuidmap, pointers) {
|
||||
if ((idx + 4) >= ARRAYSIZE(argv)) {
|
||||
LOG_W("Number of arguments to '/usr/bin/newuidmap' too big");
|
||||
return false;
|
||||
}
|
||||
|
||||
argv[argv_idx++] = p->inside_id;
|
||||
argv[argv_idx++] = p->outside_id;
|
||||
argv[argv_idx++] = p->count;
|
||||
snprintf(parms[idx], sizeof(parms[idx]), "%u", (unsigned)p->inside_id);
|
||||
argv[idx] = parms[idx];
|
||||
idx++;
|
||||
|
||||
snprintf(parms[idx], sizeof(parms[idx]), "%u", (unsigned)p->outside_id);
|
||||
argv[idx] = parms[idx];
|
||||
idx++;
|
||||
|
||||
snprintf(parms[idx], sizeof(parms[idx]), "%zu", p->count);
|
||||
argv[idx] = parms[idx];
|
||||
idx++;
|
||||
}
|
||||
argv[argv_idx++] = NULL;
|
||||
|
||||
argv[idx] = NULL;
|
||||
|
||||
if (subprocSystem(argv, environ) != 0) {
|
||||
LOG_E("'/usr/bin/newuidmap' failed");
|
||||
@ -160,7 +192,7 @@ static bool userUidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
|
||||
|
||||
static bool userUidGidMap(struct nsjconf_t *nsjconf, pid_t pid)
|
||||
{
|
||||
if (TAILQ_EMPTY(&nsjconf->gid_mappings)) {
|
||||
if (TAILQ_EMPTY(&nsjconf->gid_newuidmap)) {
|
||||
if (!userGidMapSelf(nsjconf, pid)) {
|
||||
return false;
|
||||
}
|
||||
@ -169,7 +201,7 @@ static bool userUidGidMap(struct nsjconf_t *nsjconf, pid_t pid)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (TAILQ_EMPTY(&nsjconf->uid_mappings)) {
|
||||
if (TAILQ_EMPTY(&nsjconf->gid_newuidmap)) {
|
||||
return userUidMapSelf(nsjconf, pid);
|
||||
} else {
|
||||
return userUidMapExternal(nsjconf, pid);
|
||||
@ -221,3 +253,69 @@ bool userInitNsFromChild(struct nsjconf_t * nsjconf)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uid_t cmdParseUid(const char *id)
|
||||
{
|
||||
if (id == NULL || strlen(id) == 0) {
|
||||
return getuid();
|
||||
}
|
||||
struct passwd *pw = getpwnam(id);
|
||||
if (pw != NULL) {
|
||||
return pw->pw_uid;
|
||||
}
|
||||
if (utilIsANumber(id)) {
|
||||
return (uid_t) strtoull(id, NULL, 0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static gid_t cmdParseGid(const char *id)
|
||||
{
|
||||
if (id == NULL || strlen(id) == 0) {
|
||||
return getgid();
|
||||
}
|
||||
struct group *gr = getgrnam(id);
|
||||
if (gr != NULL) {
|
||||
return gr->gr_gid;
|
||||
}
|
||||
if (utilIsANumber(id)) {
|
||||
return (gid_t) strtoull(id, NULL, 0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct idmap_t *userParseId(const char *i_id, const char *o_id, size_t cnt, bool is_gid)
|
||||
{
|
||||
uid_t inside_id;
|
||||
uid_t outside_id;
|
||||
|
||||
if (is_gid) {
|
||||
inside_id = cmdParseGid(i_id);
|
||||
if (inside_id == (uid_t) - 1) {
|
||||
LOG_E("Cannot parse '%s' as GID", i_id);
|
||||
return NULL;
|
||||
}
|
||||
outside_id = cmdParseGid(o_id);
|
||||
if (inside_id == (uid_t) - 1) {
|
||||
LOG_E("Cannot parse '%s' as GID", o_id);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
inside_id = cmdParseUid(i_id);
|
||||
if (inside_id == (uid_t) - 1) {
|
||||
LOG_E("Cannot parse '%s' as UID", i_id);
|
||||
return NULL;
|
||||
}
|
||||
outside_id = cmdParseUid(o_id);
|
||||
if (inside_id == (uid_t) - 1) {
|
||||
LOG_E("Cannot parse '%s' as UID", o_id);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct idmap_t *p = utilMalloc(sizeof(struct idmap_t));
|
||||
p->inside_id = inside_id;
|
||||
p->outside_id = outside_id;
|
||||
p->count = cnt;
|
||||
return p;
|
||||
}
|
||||
|
3
user.h
3
user.h
@ -27,7 +27,8 @@
|
||||
#include "common.h"
|
||||
|
||||
bool userInitNsFromParent(struct nsjconf_t *nsjconf, pid_t pid);
|
||||
|
||||
bool userInitNsFromChild(struct nsjconf_t *nsjconf);
|
||||
|
||||
struct idmap_t *userParseId(const char *i_id, const char *o_id, size_t cnt, bool is_gid);
|
||||
|
||||
#endif /* NS_USER_H */
|
||||
|
11
util.c
11
util.c
@ -21,6 +21,7 @@
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
@ -190,3 +191,13 @@ int utilSSnPrintf(char *str, size_t size, const char *format, ...)
|
||||
|
||||
return snprintf(str, size, "%s%s", buf1, buf2);
|
||||
}
|
||||
|
||||
bool utilIsANumber(const char *s)
|
||||
{
|
||||
for (int i = 0; s[i]; s++) {
|
||||
if (!isdigit(s[i]) && s[i] != 'x') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
1
util.h
1
util.h
@ -36,5 +36,6 @@ ssize_t utilWriteToFd(int fd, const void *buf, size_t len);
|
||||
bool utilWriteBufToFile(const char *filename, const void *buf, size_t len, int open_flags);
|
||||
bool utilCreateDirRecursively(const char *dir);
|
||||
int utilSSnPrintf(char *str, size_t size, const char *format, ...);
|
||||
bool utilIsANumber(const char *s);
|
||||
|
||||
#endif /* NS_UTIL_H */
|
||||
|
Loading…
Reference in New Issue
Block a user