Allow to specify multiple uid/gid maps

This commit is contained in:
Robert Swiecki 2017-02-08 00:36:32 +01:00
parent f7b9fede69
commit 4a154733e0
6 changed files with 143 additions and 90 deletions

View File

@ -22,6 +22,7 @@ CC ?= gcc
CFLAGS += -O2 -c -std=gnu11 \ CFLAGS += -O2 -c -std=gnu11 \
-D_GNU_SOURCE \ -D_GNU_SOURCE \
-fstack-protector-all -Wformat -Wformat=2 -Wformat-security -fPIE \ -fstack-protector-all -Wformat -Wformat=2 -Wformat-security -fPIE \
-Wno-format-nonliteral \
-Wall -Wextra -Werror -Wall -Wextra -Werror
LDFLAGS += -Wl,-z,now -Wl,-z,relro -pie -Wl,-z,noexecstack LDFLAGS += -Wl,-z,now -Wl,-z,relro -pie -Wl,-z,noexecstack

123
cmdline.c
View File

@ -101,13 +101,12 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
LOG_I LOG_I
("Jail parameters: hostname:'%s', chroot:'%s', process:'%s', bind:[%s]:%d, " ("Jail parameters: hostname:'%s', chroot:'%s', process:'%s', bind:[%s]:%d, "
"max_conns_per_ip:%u, uid:(ns:%u, global:%u), gid:(ns:%u, global:%u), time_limit:%ld, personality:%#lx, daemonize:%s, " "max_conns_per_ip:%u, time_limit:%ld, personality:%#lx, daemonize:%s, "
"clone_newnet:%s, clone_newuser:%s, clone_newns:%s, clone_newpid:%s, " "clone_newnet:%s, clone_newuser:%s, clone_newns:%s, clone_newpid:%s, "
"clone_newipc:%s, clonew_newuts:%s, clone_newcgroup:%s, keep_caps:%s, " "clone_newipc:%s, clonew_newuts:%s, clone_newcgroup:%s, keep_caps:%s, "
"tmpfs_size:%zu, disable_no_new_privs:%s, pivot_root_only:%s", "tmpfs_size:%zu, disable_no_new_privs:%s, pivot_root_only:%s",
nsjconf->hostname, nsjconf->chroot, nsjconf->argv[0], nsjconf->bindhost, nsjconf->port, nsjconf->hostname, nsjconf->chroot, nsjconf->argv[0], nsjconf->bindhost, nsjconf->port,
nsjconf->max_conns_per_ip, nsjconf->inside_uid, nsjconf->outside_uid, nsjconf->max_conns_per_ip, nsjconf->tlimit, nsjconf->personality,
nsjconf->inside_gid, nsjconf->outside_gid, nsjconf->tlimit, nsjconf->personality,
logYesNo(nsjconf->daemonize), logYesNo(nsjconf->clone_newnet), logYesNo(nsjconf->daemonize), logYesNo(nsjconf->clone_newnet),
logYesNo(nsjconf->clone_newuser), logYesNo(nsjconf->clone_newns), logYesNo(nsjconf->clone_newuser), logYesNo(nsjconf->clone_newns),
logYesNo(nsjconf->clone_newpid), logYesNo(nsjconf->clone_newipc), logYesNo(nsjconf->clone_newpid), logYesNo(nsjconf->clone_newipc),
@ -122,15 +121,25 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
p->src, p->dst, p->fs_type, p->flags, p->options); p->src, p->dst, p->fs_type, p->flags, p->options);
} }
} }
{
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);
}
TAILQ_FOREACH(p, &nsjconf->gids, pointers) {
LOG_I("Gid map: inside_gid:%d outside_gid:%d", p->inside_id, p->outside_id);
}
}
{ {
struct mapping_t *p; struct mapping_t *p;
TAILQ_FOREACH(p, &nsjconf->uid_mappings, pointers) { TAILQ_FOREACH(p, &nsjconf->uid_mappings, pointers) {
LOG_I("Uid mapping: inside_uid:'%s' outside_uid:'%s' count:'%s'", LOG_I("Newuid mapping: inside_uid:'%s' outside_uid:'%s' count:'%s'",
p->inside_id, p->outside_id, p->count); p->inside_id, p->outside_id, p->count);
} }
TAILQ_FOREACH(p, &nsjconf->gid_mappings, pointers) { TAILQ_FOREACH(p, &nsjconf->gid_mappings, pointers) {
LOG_I("Gid mapping: inside_uid:'%s' outside_uid:'%s' count:'%s'", LOG_I("Newgid mapping: inside_uid:'%s' outside_uid:'%s' count:'%s'",
p->inside_id, p->outside_id, p->count); p->inside_id, p->outside_id, p->count);
} }
} }
@ -204,30 +213,38 @@ static bool cmdlineParseUid(struct nsjconf_t *nsjconf, char *str)
} }
char *second = cmdlineSplitStrByColon(str); char *second = cmdlineSplitStrByColon(str);
pid_t inside_uid;
pid_t outside_uid;
struct passwd *pw = getpwnam(str); struct passwd *pw = getpwnam(str);
if (pw != NULL) { if (pw != NULL) {
nsjconf->inside_uid = pw->pw_uid; inside_uid = pw->pw_uid;
} else if (cmdlineIsANumber(str)) { } else if (cmdlineIsANumber(str)) {
nsjconf->inside_uid = (uid_t) strtoull(str, NULL, 0); inside_uid = (uid_t) strtoull(str, NULL, 0);
} else { } else {
LOG_E("No such user '%s'", str); LOG_E("No such user '%s'", str);
return false; return false;
} }
if (str == second) { if (str == second) {
return true; outside_uid = inside_uid;
} 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;
}
} }
pw = getpwnam(second); struct idmap_t *p = utilMalloc(sizeof(struct idmap_t));
if (pw != NULL) { p->inside_id = inside_uid;
nsjconf->outside_uid = pw->pw_uid; p->outside_id = outside_uid;
} else if (cmdlineIsANumber(second)) { TAILQ_INSERT_TAIL(&nsjconf->uids, p, pointers);
nsjconf->outside_uid = (uid_t) strtoull(second, NULL, 0);
} else {
LOG_E("No such user '%s'", second);
return false;
}
return true; return true;
} }
@ -238,30 +255,39 @@ static bool cmdlineParseGid(struct nsjconf_t *nsjconf, char *str)
} }
char *second = cmdlineSplitStrByColon(str); char *second = cmdlineSplitStrByColon(str);
gid_t inside_gid;
gid_t outside_gid;
struct group *gr = getgrnam(str); struct group *gr = getgrnam(str);
if (gr != NULL) { if (gr != NULL) {
nsjconf->inside_gid = gr->gr_gid; inside_gid = gr->gr_gid;
} else if (cmdlineIsANumber(str)) { } else if (cmdlineIsANumber(str)) {
nsjconf->inside_gid = (gid_t) strtoull(str, NULL, 0); inside_gid = (gid_t) strtoull(str, NULL, 0);
} else { } else {
LOG_E("No such group '%s'", str); LOG_E("No such group '%s'", str);
return false; return false;
} }
if (str == second) { if (str == second) {
return true; outside_gid = inside_gid;
} 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;
}
} }
gr = getgrnam(second); struct idmap_t *p = utilMalloc(sizeof(struct idmap_t));
if (gr != NULL) { p->inside_id = inside_gid;
nsjconf->outside_gid = gr->gr_gid; p->outside_id = outside_gid;
} else if (cmdlineIsANumber(second)) { TAILQ_INSERT_TAIL(&nsjconf->gids, p, pointers);
nsjconf->outside_gid = (gid_t) strtoull(second, NULL, 0);
} else {
LOG_E("No such group '%s'", second);
return false;
}
return true; return true;
} }
@ -300,10 +326,6 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
.is_root_rw = false, .is_root_rw = false,
.is_silent = false, .is_silent = false,
.skip_setsid = false, .skip_setsid = false,
.inside_uid = getuid(),
.inside_gid = getgid(),
.outside_uid = getuid(),
.outside_gid = getgid(),
.max_conns_per_ip = 0, .max_conns_per_ip = 0,
.tmpfs_size = 4 * (1024 * 1024), .tmpfs_size = 4 * (1024 * 1024),
.mount_proc = true, .mount_proc = true,
@ -320,6 +342,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
}; };
/* *INDENT-OFF* */ /* *INDENT-OFF* */
TAILQ_INIT(&nsjconf->uids);
TAILQ_INIT(&nsjconf->gids);
TAILQ_INIT(&nsjconf->envs); TAILQ_INIT(&nsjconf->envs);
TAILQ_INIT(&nsjconf->pids); TAILQ_INIT(&nsjconf->pids);
TAILQ_INIT(&nsjconf->mountpts); TAILQ_INIT(&nsjconf->mountpts);
@ -327,8 +351,6 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
TAILQ_INIT(&nsjconf->uid_mappings); TAILQ_INIT(&nsjconf->uid_mappings);
TAILQ_INIT(&nsjconf->gid_mappings); TAILQ_INIT(&nsjconf->gid_mappings);
char *user = NULL;
char *group = NULL;
const char *logfile = NULL; const char *logfile = NULL;
static char cmdlineTmpfsSz[PATH_MAX] = "size=4194304"; static char cmdlineTmpfsSz[PATH_MAX] = "size=4194304";
@ -353,8 +375,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
"\tr: Immediately launch a single process on the console, keep doing it forever [MODE_STANDALONE_RERUN]"}, "\tr: Immediately launch a single process on the console, keep doing it forever [MODE_STANDALONE_RERUN]"},
{{"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 / as RW (default: RO)"}, {{"rw", no_argument, NULL, 0x601}, "Mount / 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"}, {{"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"}, {{"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"},
{{"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)"},
@ -445,10 +467,14 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
nsjconf->max_conns_per_ip = strtoul(optarg, NULL, 0); nsjconf->max_conns_per_ip = strtoul(optarg, NULL, 0);
break; break;
case 'u': case 'u':
user = optarg; if (cmdlineParseUid(nsjconf, optarg) == false) {
LOG_F("cmdlineParseUid('%s')", optarg);
}
break; break;
case 'g': case 'g':
group = optarg; if (cmdlineParseGid(nsjconf, optarg) == false) {
LOG_F("cmdlineParseGid('%s')", optarg);
}
break; break;
case 'l': case 'l':
logfile = optarg; logfile = optarg;
@ -711,6 +737,18 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
TAILQ_INSERT_HEAD(&nsjconf->mountpts, p, pointers); TAILQ_INSERT_HEAD(&nsjconf->mountpts, p, pointers);
} }
if (TAILQ_EMPTY(&nsjconf->uids)) {
struct idmap_t *p = utilMalloc(sizeof(struct idmap_t));
p->inside_id = getuid();
p->outside_id = getuid();
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();
TAILQ_INSERT_HEAD(&nsjconf->gids, p, pointers);
}
#if !defined(USE_KAFEL) #if !defined(USE_KAFEL)
if (nsjconf->kafel_file != NULL || nsjconf->kafel_string != NULL) { if (nsjconf->kafel_file != NULL || nsjconf->kafel_string != NULL) {
LOG_F("Kafel policy specified but the kafel/ is not compiled in"); LOG_F("Kafel policy specified but the kafel/ is not compiled in");
@ -721,13 +759,6 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
return false; return false;
} }
if (cmdlineParseUid(nsjconf, user) == false) {
return false;
}
if (cmdlineParseGid(nsjconf, group) == false) {
return false;
}
nsjconf->argv = &argv[optind]; nsjconf->argv = &argv[optind];
if (nsjconf->argv[0] == NULL) { if (nsjconf->argv[0] == NULL) {
LOG_E("No command provided"); LOG_E("No command provided");

View File

@ -31,6 +31,7 @@
#include <sys/types.h> #include <sys/types.h>
#define ARRAYSIZE(array) (sizeof(array) / sizeof(*array)) #define ARRAYSIZE(array) (sizeof(array) / sizeof(*array))
#define UNUSED __attribute__((unused))
#if 0 /* Works, but needs -fblocks and libBlocksRuntime with clang */ #if 0 /* Works, but needs -fblocks and libBlocksRuntime with clang */
/* Go-style defer implementation */ /* Go-style defer implementation */
@ -79,6 +80,12 @@ struct mapping_t {
TAILQ_ENTRY(mapping_t) pointers; TAILQ_ENTRY(mapping_t) pointers;
}; };
struct idmap_t {
pid_t inside_id;
pid_t outside_id;
TAILQ_ENTRY(idmap_t) pointers;
};
struct fds_t { struct fds_t {
int fd; int fd;
TAILQ_ENTRY(fds_t) pointers; TAILQ_ENTRY(fds_t) pointers;
@ -129,10 +136,6 @@ struct nsjconf_t {
bool is_root_rw; bool is_root_rw;
bool is_silent; bool is_silent;
bool skip_setsid; bool skip_setsid;
uid_t outside_uid;
gid_t outside_gid;
uid_t inside_uid;
gid_t inside_gid;
unsigned int max_conns_per_ip; unsigned int max_conns_per_ip;
size_t tmpfs_size; size_t tmpfs_size;
bool mount_proc; bool mount_proc;
@ -146,6 +149,8 @@ struct nsjconf_t {
size_t cgroup_mem_max; size_t cgroup_mem_max;
FILE *kafel_file; FILE *kafel_file;
char *kafel_string; char *kafel_string;
TAILQ_HEAD(uidlist, idmap_t) uids;
TAILQ_HEAD(gidlist, idmap_t) gids;
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;

79
user.c
View File

@ -59,11 +59,16 @@ static bool userSetGroups(pid_t pid)
static bool userUidMapSelf(struct nsjconf_t *nsjconf, pid_t pid) static bool userUidMapSelf(struct nsjconf_t *nsjconf, pid_t pid)
{ {
char fname[PATH_MAX]; char fname[PATH_MAX];
char map[128];
snprintf(fname, sizeof(fname), "/proc/%d/uid_map", pid); snprintf(fname, sizeof(fname), "/proc/%d/uid_map", pid);
snprintf(map, sizeof(map), "%lu %lu 1", (unsigned long)nsjconf->inside_uid,
(unsigned long)nsjconf->outside_uid); char map[4096] = {[0] = '\0' };
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);
}
LOG_D("Writing '%s' to '%s'", map, fname); LOG_D("Writing '%s' to '%s'", map, fname);
if (utilWriteBufToFile(fname, map, strlen(map), O_WRONLY) == false) { if (utilWriteBufToFile(fname, map, strlen(map), O_WRONLY) == false) {
LOG_E("utilWriteBufToFile('%s', '%s') failed", fname, map); LOG_E("utilWriteBufToFile('%s', '%s') failed", fname, map);
@ -76,36 +81,34 @@ static bool userUidMapSelf(struct nsjconf_t *nsjconf, pid_t pid)
static bool userGidMapSelf(struct nsjconf_t *nsjconf, pid_t pid) static bool userGidMapSelf(struct nsjconf_t *nsjconf, pid_t pid)
{ {
char fname[PATH_MAX]; char fname[PATH_MAX];
char map[128];
snprintf(fname, sizeof(fname), "/proc/%d/gid_map", pid); snprintf(fname, sizeof(fname), "/proc/%d/gid_map", pid);
snprintf(map, sizeof(map), "%lu %lu 1", (unsigned long)nsjconf->inside_gid,
(unsigned long)nsjconf->outside_gid); char map[4096] = {[0] = '\0' };
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);
}
LOG_D("Writing '%s' to '%s'", map, fname); LOG_D("Writing '%s' to '%s'", map, fname);
if (utilWriteBufToFile(fname, map, strlen(map), O_WRONLY) == false) { if (utilWriteBufToFile(fname, map, strlen(map), O_WRONLY) == false) {
LOG_E("utilWriteBufToFile('%s', '%s') failed", fname, map); LOG_E("utilWriteBufToFile('%s', '%s') failed", fname, map);
return false; return false;
} }
return true; return true;
} }
/* 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) static bool userGidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
{ {
char pid_str[16]; const char *argv[1024] = { "/usr/bin/newgidmap" };
char ins_gid_str[16]; size_t argv_idx = 1;
char out_gid_str[16];
snprintf(pid_str, sizeof(pid_str), "%lu", (unsigned long)pid);
snprintf(ins_gid_str, sizeof(ins_gid_str), "%lu", (unsigned long)nsjconf->inside_gid);
snprintf(out_gid_str, sizeof(out_gid_str), "%lu", (unsigned long)nsjconf->outside_gid);
const char *argv[1024] = { "/usr/bin/newgidmap", pid_str, ins_gid_str, out_gid_str, "1" };
size_t argv_idx = 5;
struct mapping_t *p; struct mapping_t *p;
TAILQ_FOREACH(p, &nsjconf->gid_mappings, pointers) { TAILQ_FOREACH(p, &nsjconf->gid_mappings, pointers) {
if ((argv_idx + 4) >= ARRAYSIZE(argv)) { if (argv_idx >= 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;
} }
@ -125,22 +128,14 @@ static bool userGidMapExternal(struct nsjconf_t *nsjconf, pid_t pid)
} }
/* 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) static bool userUidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
{ {
char pid_str[16]; const char *argv[1024] = { "/usr/bin/newuidmap" };
char ins_uid_str[16]; size_t argv_idx = 1;
char out_uid_str[16];
snprintf(pid_str, sizeof(pid_str), "%lu", (unsigned long)pid);
snprintf(ins_uid_str, sizeof(ins_uid_str), "%lu", (unsigned long)nsjconf->inside_uid);
snprintf(out_uid_str, sizeof(out_uid_str), "%lu", (unsigned long)nsjconf->outside_uid);
const char *argv[1024] = { "/usr/bin/newuidmap", pid_str, ins_uid_str, out_uid_str, "1" };
size_t argv_idx = 5;
struct mapping_t *p; struct mapping_t *p;
TAILQ_FOREACH(p, &nsjconf->uid_mappings, pointers) { TAILQ_FOREACH(p, &nsjconf->uid_mappings, pointers) {
if ((argv_idx + 4) >= ARRAYSIZE(argv)) { if (argv_idx >= 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;
} }
@ -201,18 +196,22 @@ bool userInitNsFromChild(struct nsjconf_t * nsjconf)
if (setgroups(0, group_list) == -1) { if (setgroups(0, group_list) == -1) {
PLOG_D("setgroups(NULL) failed"); PLOG_D("setgroups(NULL) failed");
} }
LOG_D("setresgid(%d, %d, %d)", nsjconf->inside_gid, nsjconf->inside_gid, LOG_D("setresgid(%d, %d, %d)", TAILQ_FIRST(&nsjconf->gids)->inside_id,
nsjconf->inside_gid); TAILQ_FIRST(&nsjconf->gids)->inside_id, TAILQ_FIRST(&nsjconf->gids)->inside_id);
if (syscall(__NR_setresgid, nsjconf->inside_gid, nsjconf->inside_gid, nsjconf->inside_gid) if (syscall
(__NR_setresgid, TAILQ_FIRST(&nsjconf->gids)->inside_id,
TAILQ_FIRST(&nsjconf->gids)->inside_id, TAILQ_FIRST(&nsjconf->gids)->inside_id)
== -1) { == -1) {
PLOG_E("setresgid(%u)", nsjconf->inside_gid); PLOG_E("setresgid(%u)", TAILQ_FIRST(&nsjconf->gids)->inside_id);
return false; return false;
} }
LOG_D("setresuid(%d, %d, %d)", nsjconf->inside_uid, nsjconf->inside_uid, LOG_D("setresuid(%d, %d, %d)", TAILQ_FIRST(&nsjconf->uids)->inside_id,
nsjconf->inside_uid); TAILQ_FIRST(&nsjconf->uids)->inside_id, TAILQ_FIRST(&nsjconf->uids)->inside_id);
if (syscall(__NR_setresuid, nsjconf->inside_uid, nsjconf->inside_uid, nsjconf->inside_uid) if (syscall
(__NR_setresuid, TAILQ_FIRST(&nsjconf->uids)->inside_id,
TAILQ_FIRST(&nsjconf->uids)->inside_id, TAILQ_FIRST(&nsjconf->uids)->inside_id)
== -1) { == -1) {
PLOG_E("setresuid(%u)", nsjconf->inside_uid); PLOG_E("setresuid(%u)", TAILQ_FIRST(&nsjconf->uids)->inside_id);
return false; return false;
} }

16
util.c
View File

@ -23,6 +23,7 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -157,3 +158,18 @@ bool utilCreateDirRecursively(const char *dir)
curr = next + 1; curr = next + 1;
} }
} }
int utilSSnPrintf(char *str, size_t size, const char *format, ...)
{
char buf1[size];
char buf2[size];
snprintf(buf1, sizeof(buf1), "%s", str);
va_list args;
va_start(args, format);
vsnprintf(buf2, size, format, args);
va_end(args);
return snprintf(str, size, "%s%s", buf1, buf2);
}

1
util.h
View File

@ -33,5 +33,6 @@ ssize_t utilReadFromFile(const char *fname, void *buf, size_t len);
ssize_t utilWriteToFd(int fd, const void *buf, size_t len); 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, ...);
#endif /* NS_UTIL_H */ #endif /* NS_UTIL_H */