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.
|
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||||
|
|
||||||
nsjail.o: nsjail.h common.h cmdline.h log.h net.h subproc.h
|
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
|
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: contain.h common.h cgroup.h log.h mount.h net.h pid.h user.h
|
||||||
contain.o: util.h uts.h
|
contain.o: util.h uts.h
|
||||||
|
224
cmdline.c
224
cmdline.c
@ -45,6 +45,7 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "mount.h"
|
#include "mount.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "user.h"
|
||||||
|
|
||||||
struct custom_option {
|
struct custom_option {
|
||||||
struct option opt;
|
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"},
|
{{"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)"},
|
{{"chroot", required_argument, NULL, 'c'}, "Directory containing / of the jail (default: none)"},
|
||||||
{{"rw", no_argument, NULL, 0x601}, "Mount / and /proc as RW (default: RO)"},
|
{{"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"},
|
{{"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 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')"},
|
{{"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: '/')"},
|
{{"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)"},
|
{{"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;
|
struct idmap_t *p;
|
||||||
TAILQ_FOREACH(p, &nsjconf->uids, pointers) {
|
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) {
|
if (p->outside_id == 0) {
|
||||||
LOG_W("Process will be UID/EUID=0 in the global user namespace");
|
LOG_W("Process will be UID/EUID=0 in the global user namespace");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TAILQ_FOREACH(p, &nsjconf->gids, pointers) {
|
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) {
|
if (p->outside_id == 0) {
|
||||||
LOG_W("Process will be GID/EGID=0 in the global user namespace");
|
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;
|
struct idmap_t *p;
|
||||||
TAILQ_FOREACH(p, &nsjconf->uid_mappings, pointers) {
|
TAILQ_FOREACH(p, &nsjconf->uid_newuidmap, pointers) {
|
||||||
LOG_I("Newuid mapping: inside_uid:'%s' outside_uid:'%s' count:'%s'",
|
LOG_I("Newuid mapping: inside_uid:%u outside_uid:%u count:%zu",
|
||||||
p->inside_id, p->outside_id, p->count);
|
p->inside_id, p->outside_id, p->count);
|
||||||
if (p->outside_id == 0) {
|
if (p->outside_id == 0) {
|
||||||
LOG_W("Process will be UID/EUID=0 in the global user namespace");
|
LOG_W("Process will be UID/EUID=0 in the global user namespace");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(p, &nsjconf->gid_mappings, pointers) {
|
TAILQ_FOREACH(p, &nsjconf->gid_newuidmap, pointers) {
|
||||||
LOG_I("Newgid mapping: inside_uid:'%s' outside_uid:'%s' count:'%s'",
|
LOG_I("Newgid mapping: inside_uid:%u outside_uid:%u count:%zu",
|
||||||
p->inside_id, p->outside_id, p->count);
|
p->inside_id, p->outside_id, p->count);
|
||||||
if (p->outside_id == 0) {
|
if (p->outside_id == 0) {
|
||||||
LOG_W("Process will be GID/EGID=0 in the global user namespace");
|
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)
|
__rlim64_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
|
||||||
{
|
{
|
||||||
struct rlimit64 cur;
|
struct rlimit64 cur;
|
||||||
@ -288,7 +281,7 @@ __rlim64_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
|
|||||||
if (strcasecmp(optarg, "def") == 0) {
|
if (strcasecmp(optarg, "def") == 0) {
|
||||||
return cur.rlim_cur;
|
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,
|
LOG_F("RLIMIT %d needs a numeric or 'max'/'def' value ('%s' provided)", res,
|
||||||
optarg);
|
optarg);
|
||||||
}
|
}
|
||||||
@ -304,6 +297,10 @@ __rlim64_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
|
|||||||
* string. */
|
* string. */
|
||||||
static char *cmdlineSplitStrByColon(char *spec)
|
static char *cmdlineSplitStrByColon(char *spec)
|
||||||
{
|
{
|
||||||
|
if (spec == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
char *dest = spec;
|
char *dest = spec;
|
||||||
while (*dest != ':' && *dest != '\0') {
|
while (*dest != ':' && *dest != '\0') {
|
||||||
dest++;
|
dest++;
|
||||||
@ -314,97 +311,13 @@ static char *cmdlineSplitStrByColon(char *spec)
|
|||||||
*dest = '\0';
|
*dest = '\0';
|
||||||
return dest + 1;
|
return dest + 1;
|
||||||
case '\0':
|
case '\0':
|
||||||
return spec;
|
return NULL;
|
||||||
default:
|
default:
|
||||||
// not reached
|
LOG_F("Impossible condition in cmdlineSplitStrByColon()");
|
||||||
return spec;
|
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)
|
bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
||||||
{
|
{
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
@ -460,14 +373,14 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
|||||||
};
|
};
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
TAILQ_INIT(&nsjconf->uids);
|
|
||||||
TAILQ_INIT(&nsjconf->gids);
|
|
||||||
TAILQ_INIT(&nsjconf->envs);
|
|
||||||
TAILQ_INIT(&nsjconf->pids);
|
TAILQ_INIT(&nsjconf->pids);
|
||||||
TAILQ_INIT(&nsjconf->mountpts);
|
TAILQ_INIT(&nsjconf->mountpts);
|
||||||
TAILQ_INIT(&nsjconf->open_fds);
|
TAILQ_INIT(&nsjconf->open_fds);
|
||||||
TAILQ_INIT(&nsjconf->uid_mappings);
|
TAILQ_INIT(&nsjconf->envs);
|
||||||
TAILQ_INIT(&nsjconf->gid_mappings);
|
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";
|
static char cmdlineTmpfsSz[PATH_MAX] = "size=4194304";
|
||||||
|
|
||||||
@ -528,16 +441,6 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
|||||||
case 'i':
|
case 'i':
|
||||||
nsjconf->max_conns_per_ip = strtoul(optarg, NULL, 0);
|
nsjconf->max_conns_per_ip = strtoul(optarg, NULL, 0);
|
||||||
break;
|
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':
|
case 'l':
|
||||||
nsjconf->logfile = optarg;
|
nsjconf->logfile = optarg;
|
||||||
if (logInitLogFile(nsjconf) == false) {
|
if (logInitLogFile(nsjconf) == false) {
|
||||||
@ -663,17 +566,72 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
|||||||
p->val = optarg;
|
p->val = optarg;
|
||||||
TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers);
|
TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers);
|
||||||
} break;
|
} break;
|
||||||
case 'U':
|
case 'u':{
|
||||||
case 'G':{
|
char *i_id = optarg;
|
||||||
struct mapping_t *p = utilMalloc(sizeof(struct mapping_t));
|
char *o_id = cmdlineSplitStrByColon(i_id);
|
||||||
p->inside_id = optarg;
|
char *cnt = cmdlineSplitStrByColon(o_id);
|
||||||
char *outside_id = cmdlineSplitStrByColon(optarg);
|
size_t count = (cnt == NULL
|
||||||
p->outside_id = outside_id;
|
|| strlen(cnt) == 0) ? 1U : (size_t) strtoull(cnt,
|
||||||
p->count = cmdlineSplitStrByColon(outside_id);
|
NULL,
|
||||||
if (c == 'U') {
|
0);
|
||||||
TAILQ_INSERT_TAIL(&nsjconf->uid_mappings, p, pointers);
|
|
||||||
|
struct idmap_t *p =
|
||||||
|
userParseId(i_id, o_id, count, false /* is_gid */ );
|
||||||
|
if (p) {
|
||||||
|
TAILQ_INSERT_TAIL(&nsjconf->uids, p, pointers);
|
||||||
} else {
|
} 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;
|
break;
|
||||||
@ -822,12 +780,14 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
|||||||
struct idmap_t *p = utilMalloc(sizeof(struct idmap_t));
|
struct idmap_t *p = utilMalloc(sizeof(struct idmap_t));
|
||||||
p->inside_id = getuid();
|
p->inside_id = getuid();
|
||||||
p->outside_id = getuid();
|
p->outside_id = getuid();
|
||||||
|
p->count = 1U;
|
||||||
TAILQ_INSERT_HEAD(&nsjconf->uids, p, pointers);
|
TAILQ_INSERT_HEAD(&nsjconf->uids, p, pointers);
|
||||||
}
|
}
|
||||||
if (TAILQ_EMPTY(&nsjconf->gids)) {
|
if (TAILQ_EMPTY(&nsjconf->gids)) {
|
||||||
struct idmap_t *p = utilMalloc(sizeof(struct idmap_t));
|
struct idmap_t *p = utilMalloc(sizeof(struct idmap_t));
|
||||||
p->inside_id = getgid();
|
p->inside_id = getgid();
|
||||||
p->outside_id = getgid();
|
p->outside_id = getgid();
|
||||||
|
p->count = 1U;
|
||||||
TAILQ_INSERT_HEAD(&nsjconf->gids, p, pointers);
|
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;
|
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 {
|
struct idmap_t {
|
||||||
uid_t inside_id;
|
uid_t inside_id;
|
||||||
uid_t outside_id;
|
uid_t outside_id;
|
||||||
|
size_t count;
|
||||||
TAILQ_ENTRY(idmap_t) pointers;
|
TAILQ_ENTRY(idmap_t) pointers;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -164,14 +158,14 @@ struct nsjconf_t {
|
|||||||
size_t cgroup_pids_max;
|
size_t cgroup_pids_max;
|
||||||
FILE *kafel_file;
|
FILE *kafel_file;
|
||||||
char *kafel_string;
|
char *kafel_string;
|
||||||
TAILQ_HEAD(uidlist, idmap_t) uids;
|
TAILQ_HEAD(udmaplist, idmap_t) uids;
|
||||||
TAILQ_HEAD(gidlist, idmap_t) gids;
|
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(envlist, charptr_t) envs;
|
||||||
TAILQ_HEAD(pidslist, pids_t) pids;
|
TAILQ_HEAD(pidslist, pids_t) pids;
|
||||||
TAILQ_HEAD(mountptslist, mounts_t) mountpts;
|
TAILQ_HEAD(mountptslist, mounts_t) mountpts;
|
||||||
TAILQ_HEAD(fdslistt, fds_t) open_fds;
|
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 */
|
#endif /* NS_COMMON_H */
|
||||||
|
154
user.c
154
user.c
@ -24,12 +24,14 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
@ -65,8 +67,8 @@ static bool userUidMapSelf(struct nsjconf_t *nsjconf, pid_t pid)
|
|||||||
|
|
||||||
struct idmap_t *p;
|
struct idmap_t *p;
|
||||||
TAILQ_FOREACH(p, &nsjconf->uids, pointers) {
|
TAILQ_FOREACH(p, &nsjconf->uids, pointers) {
|
||||||
utilSSnPrintf(map, sizeof(map), "%lu %lu 1\n", (unsigned long)p->inside_id,
|
utilSSnPrintf(map, sizeof(map), "%lu %lu %zu\n", (unsigned long)p->inside_id,
|
||||||
(unsigned long)p->outside_id);
|
(unsigned long)p->outside_id, p->count);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_D("Writing '%s' to '%s'", map, fname);
|
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;
|
struct idmap_t *p;
|
||||||
TAILQ_FOREACH(p, &nsjconf->gids, pointers) {
|
TAILQ_FOREACH(p, &nsjconf->gids, pointers) {
|
||||||
utilSSnPrintf(map, sizeof(map), "%lu %lu 1\n", (unsigned long)p->inside_id,
|
utilSSnPrintf(map, sizeof(map), "%lu %lu %zu\n", (unsigned long)p->inside_id,
|
||||||
(unsigned long)p->outside_id);
|
(unsigned long)p->outside_id, p->count);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_D("Writing '%s' to '%s'", map, fname);
|
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 */
|
/* Use /usr/bin/newgidmap for writing the gid map */
|
||||||
static bool userGidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
|
static bool userGidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
|
||||||
{
|
{
|
||||||
char pid_str[128];
|
static size_t idx = 0;
|
||||||
snprintf(pid_str, sizeof(pid_str), "%d", (int)pid);
|
|
||||||
const char *argv[1024] = { "/usr/bin/newgidmap", pid_str };
|
|
||||||
size_t argv_idx = 2;
|
|
||||||
|
|
||||||
struct mapping_t *p;
|
const char *argv[1024];
|
||||||
TAILQ_FOREACH(p, &nsjconf->gid_mappings, pointers) {
|
char parms[1024][256];
|
||||||
if (argv_idx >= ARRAYSIZE(argv)) {
|
|
||||||
|
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");
|
LOG_W("Number of arguments to '/usr/bin/newgidmap' too big");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
argv[argv_idx++] = p->inside_id;
|
snprintf(parms[idx], sizeof(parms[idx]), "%u", (unsigned)p->inside_id);
|
||||||
argv[argv_idx++] = p->outside_id;
|
argv[idx] = parms[idx];
|
||||||
argv[argv_idx++] = p->count;
|
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) {
|
if (subprocSystem(argv, environ) != 0) {
|
||||||
LOG_E("'/usr/bin/newgidmap' failed");
|
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 */
|
/* Use /usr/bin/newuidmap for writing the uid map */
|
||||||
static bool userUidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
|
static bool userUidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
|
||||||
{
|
{
|
||||||
char pid_str[128];
|
static size_t idx = 0;
|
||||||
snprintf(pid_str, sizeof(pid_str), "%d", (int)pid);
|
|
||||||
const char *argv[1024] = { "/usr/bin/newuidmap", pid_str };
|
|
||||||
size_t argv_idx = 2;
|
|
||||||
|
|
||||||
struct mapping_t *p;
|
const char *argv[1024];
|
||||||
TAILQ_FOREACH(p, &nsjconf->uid_mappings, pointers) {
|
char parms[1024][256];
|
||||||
if (argv_idx >= ARRAYSIZE(argv)) {
|
|
||||||
|
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");
|
LOG_W("Number of arguments to '/usr/bin/newuidmap' too big");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
argv[argv_idx++] = p->inside_id;
|
snprintf(parms[idx], sizeof(parms[idx]), "%u", (unsigned)p->inside_id);
|
||||||
argv[argv_idx++] = p->outside_id;
|
argv[idx] = parms[idx];
|
||||||
argv[argv_idx++] = p->count;
|
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) {
|
if (subprocSystem(argv, environ) != 0) {
|
||||||
LOG_E("'/usr/bin/newuidmap' failed");
|
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)
|
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)) {
|
if (!userGidMapSelf(nsjconf, pid)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -169,7 +201,7 @@ static bool userUidGidMap(struct nsjconf_t *nsjconf, pid_t pid)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (TAILQ_EMPTY(&nsjconf->uid_mappings)) {
|
if (TAILQ_EMPTY(&nsjconf->gid_newuidmap)) {
|
||||||
return userUidMapSelf(nsjconf, pid);
|
return userUidMapSelf(nsjconf, pid);
|
||||||
} else {
|
} else {
|
||||||
return userUidMapExternal(nsjconf, pid);
|
return userUidMapExternal(nsjconf, pid);
|
||||||
@ -221,3 +253,69 @@ bool userInitNsFromChild(struct nsjconf_t * nsjconf)
|
|||||||
|
|
||||||
return true;
|
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"
|
#include "common.h"
|
||||||
|
|
||||||
bool userInitNsFromParent(struct nsjconf_t *nsjconf, pid_t pid);
|
bool userInitNsFromParent(struct nsjconf_t *nsjconf, pid_t pid);
|
||||||
|
|
||||||
bool userInitNsFromChild(struct nsjconf_t *nsjconf);
|
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 */
|
#endif /* NS_USER_H */
|
||||||
|
11
util.c
11
util.c
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdarg.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);
|
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 utilWriteBufToFile(const char *filename, const void *buf, size_t len, int open_flags);
|
||||||
bool utilCreateDirRecursively(const char *dir);
|
bool utilCreateDirRecursively(const char *dir);
|
||||||
int utilSSnPrintf(char *str, size_t size, const char *format, ...);
|
int utilSSnPrintf(char *str, size_t size, const char *format, ...);
|
||||||
|
bool utilIsANumber(const char *s);
|
||||||
|
|
||||||
#endif /* NS_UTIL_H */
|
#endif /* NS_UTIL_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user