cmdline: move to C++

This commit is contained in:
Robert Swiecki 2018-02-09 15:44:29 +01:00
parent 0a311af2ad
commit 840b75025c
5 changed files with 174 additions and 160 deletions

View File

@ -30,13 +30,13 @@ COMMON_FLAGS += -O2 -c \
CFLAGS += $(COMMON_FLAGS) \ CFLAGS += $(COMMON_FLAGS) \
-std=gnu11 -std=gnu11
CXXFLAGS += $(COMMON_FLAGS) $(shell pkg-config --cflags protobuf) \ CXXFLAGS += $(COMMON_FLAGS) $(shell pkg-config --cflags protobuf) \
-std=c++11 -Wno-unused -Wno-unused-parameter -std=c++14 -fno-exceptions -Wno-unused -Wno-unused-parameter
LDFLAGS += -pie -Wl,-z,noexecstack -lpthread $(shell pkg-config --libs protobuf) LDFLAGS += -pie -Wl,-z,noexecstack -lpthread $(shell pkg-config --libs protobuf)
BIN = nsjail BIN = nsjail
LIBS = kafel/libkafel.a LIBS = kafel/libkafel.a
SRCS_C = caps.c cmdline.c contain.c log.c cgroup.c mount.c net.c pid.c sandbox.c subproc.c user.c util.c uts.c cpu.c SRCS_C = caps.c contain.c log.c cgroup.c mount.c net.c pid.c sandbox.c subproc.c user.c util.c uts.c cpu.c
SRCS_CXX = nsjail.cc config.cc SRCS_CXX = cmdline.cc config.cc nsjail.cc
SRCS_PROTO = config.proto SRCS_PROTO = config.proto
SRCS_PB_CXX = $(SRCS_PROTO:.proto=.pb.cc) SRCS_PB_CXX = $(SRCS_PROTO:.proto=.pb.cc)
SRCS_PB_H = $(SRCS_PROTO:.proto=.pb.h) SRCS_PB_H = $(SRCS_PROTO:.proto=.pb.h)
@ -97,10 +97,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 cmdline.h common.h log.h net.h subproc.h util.h
caps.o: caps.h nsjail.h common.h log.h util.h caps.o: caps.h nsjail.h common.h log.h util.h
cmdline.o: cmdline.h nsjail.h caps.h common.h config.h log.h mount.h
cmdline.o: sandbox.h user.h util.h
contain.o: contain.h nsjail.h caps.h cgroup.h cpu.h log.h mount.h net.h pid.h contain.o: contain.h nsjail.h caps.h cgroup.h cpu.h log.h mount.h net.h pid.h
contain.o: user.h uts.h contain.o: user.h uts.h
log.o: log.h nsjail.h log.o: log.h nsjail.h
@ -115,5 +112,8 @@ user.o: user.h nsjail.h common.h log.h subproc.h util.h
util.o: util.h nsjail.h common.h log.h util.o: util.h nsjail.h common.h log.h
uts.o: uts.h nsjail.h log.h uts.o: uts.h nsjail.h log.h
cpu.o: cpu.h nsjail.h log.h util.h cpu.o: cpu.h nsjail.h log.h util.h
config.o: common.h caps.h nsjail.h cmdline.h config.h log.h mount.h user.h cmdline.o: cmdline.h nsjail.h caps.h common.h log.h mount.h sandbox.h user.h
config.o: util.h cmdline.o: util.h config.h
config.o: common.h caps.h nsjail.h config.h log.h mount.h user.h util.h
config.o: cmdline.h
nsjail.o: nsjail.h cmdline.h common.h log.h net.h subproc.h util.h

View File

@ -36,19 +36,27 @@
#include <strings.h> #include <strings.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/personality.h> #include <sys/personality.h>
#include <sys/resource.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <memory>
extern "C" {
#include "caps.h" #include "caps.h"
#include "common.h" #include "common.h"
#include "config.h"
#include "log.h" #include "log.h"
#include "mount.h" #include "mount.h"
#include "sandbox.h" #include "sandbox.h"
#include "user.h" #include "user.h"
#include "util.h" #include "util.h"
}
#include "config.h"
namespace cmdline {
struct custom_option { struct custom_option {
struct option opt; struct option opt;
@ -194,7 +202,7 @@ static void cmdlineUsage(const char* pname) {
LOG_HELP_BOLD(" nsjail -Me --chroot / --disable_proc -- /bin/echo \"ABC\""); LOG_HELP_BOLD(" nsjail -Me --chroot / --disable_proc -- /bin/echo \"ABC\"");
} }
void cmdlineLogParams(struct nsjconf_t* nsjconf) { void logParams(struct nsjconf_t* nsjconf) {
switch (nsjconf->mode) { switch (nsjconf->mode) {
case MODE_LISTEN_TCP: case MODE_LISTEN_TCP:
LOG_I("Mode: LISTEN_TCP"); LOG_I("Mode: LISTEN_TCP");
@ -263,7 +271,7 @@ void cmdlineLogParams(struct nsjconf_t* nsjconf) {
} }
} }
uint64_t cmdlineParseRLimit(int res, const char* optarg, unsigned long mul) { uint64_t parseRLimit(int res, const char* optarg, unsigned long mul) {
if (strcasecmp(optarg, "inf") == 0) { if (strcasecmp(optarg, "inf") == 0) {
return RLIM64_INFINITY; return RLIM64_INFINITY;
} }
@ -315,71 +323,71 @@ static char* cmdlineSplitStrByColon(char* spec) {
} }
} }
bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) { std::unique_ptr<struct nsjconf_t> parseArgs(int argc, char* argv[]) {
(*nsjconf) = (const struct nsjconf_t){ std::unique_ptr<struct nsjconf_t> nsjconf = std::make_unique<struct nsjconf_t>();
.exec_file = NULL,
.use_execveat = false, nsjconf->exec_file = NULL;
.exec_fd = -1, nsjconf->use_execveat = false;
.argv = NULL, nsjconf->exec_fd = -1;
.hostname = "NSJAIL", nsjconf->argv = NULL;
.cwd = "/", nsjconf->hostname = "NSJAIL";
.chroot = NULL, nsjconf->cwd = "/";
.port = 0, nsjconf->chroot = NULL;
.bindhost = "::", nsjconf->port = 0;
.log_fd = STDERR_FILENO, nsjconf->bindhost = "::";
.logfile = NULL, nsjconf->log_fd = STDERR_FILENO;
.loglevel = INFO, nsjconf->logfile = NULL;
.daemonize = false, nsjconf->loglevel = INFO;
.tlimit = 0, nsjconf->daemonize = false;
.max_cpus = 0, nsjconf->tlimit = 0;
.keep_caps = false, nsjconf->max_cpus = 0;
.disable_no_new_privs = false, nsjconf->keep_caps = false;
.rl_as = 512 * (1024 * 1024), nsjconf->disable_no_new_privs = false;
.rl_core = 0, nsjconf->rl_as = 512 * (1024 * 1024);
.rl_cpu = 600, nsjconf->rl_core = 0;
.rl_fsize = 1 * (1024 * 1024), nsjconf->rl_cpu = 600;
.rl_nofile = 32, nsjconf->rl_fsize = 1 * (1024 * 1024);
.rl_nproc = cmdlineParseRLimit(RLIMIT_NPROC, "soft", 1), nsjconf->rl_nofile = 32;
.rl_stack = cmdlineParseRLimit(RLIMIT_STACK, "soft", 1), nsjconf->rl_nproc = parseRLimit(RLIMIT_NPROC, "soft", 1);
.personality = 0, nsjconf->rl_stack = parseRLimit(RLIMIT_STACK, "soft", 1);
.clone_newnet = true, nsjconf->personality = 0;
.clone_newuser = true, nsjconf->clone_newnet = true;
.clone_newns = true, nsjconf->clone_newuser = true;
.clone_newpid = true, nsjconf->clone_newns = true;
.clone_newipc = true, nsjconf->clone_newpid = true;
.clone_newuts = true, nsjconf->clone_newipc = true;
.clone_newcgroup = true, nsjconf->clone_newuts = true;
.mode = MODE_STANDALONE_ONCE, nsjconf->clone_newcgroup = true;
.is_root_rw = false, nsjconf->mode = MODE_STANDALONE_ONCE;
.is_silent = false, nsjconf->is_root_rw = false;
.skip_setsid = false, nsjconf->is_silent = false;
.max_conns_per_ip = 0, nsjconf->skip_setsid = false;
.tmpfs_size = 4 * (1024 * 1024), nsjconf->max_conns_per_ip = 0;
.mount_proc = true, nsjconf->tmpfs_size = 4 * (1024 * 1024);
.proc_path = "/proc", nsjconf->mount_proc = true;
.is_proc_rw = false, nsjconf->proc_path = "/proc";
.cgroup_mem_mount = "/sys/fs/cgroup/memory", nsjconf->is_proc_rw = false;
.cgroup_mem_parent = "NSJAIL", nsjconf->cgroup_mem_mount = "/sys/fs/cgroup/memory";
.cgroup_mem_max = (size_t)0, nsjconf->cgroup_mem_parent = "NSJAIL";
.cgroup_pids_mount = "/sys/fs/cgroup/pids", nsjconf->cgroup_mem_max = (size_t)0;
.cgroup_pids_parent = "NSJAIL", nsjconf->cgroup_pids_mount = "/sys/fs/cgroup/pids";
.cgroup_pids_max = 0U, nsjconf->cgroup_pids_parent = "NSJAIL";
.cgroup_net_cls_mount = "/sys/fs/cgroup/net_cls", nsjconf->cgroup_pids_max = 0U;
.cgroup_net_cls_parent = "NSJAIL", nsjconf->cgroup_net_cls_mount = "/sys/fs/cgroup/net_cls";
.cgroup_net_cls_classid = 0U, nsjconf->cgroup_net_cls_parent = "NSJAIL";
.cgroup_cpu_mount = "/sys/fs/cgroup/cpu", nsjconf->cgroup_net_cls_classid = 0U;
.cgroup_cpu_parent = "NSJAIL", nsjconf->cgroup_cpu_mount = "/sys/fs/cgroup/cpu";
.cgroup_cpu_ms_per_sec = 0U, nsjconf->cgroup_cpu_parent = "NSJAIL";
.iface_no_lo = false, nsjconf->cgroup_cpu_ms_per_sec = 0U;
.iface_vs = NULL, nsjconf->iface_no_lo = false;
.iface_vs_ip = "0.0.0.0", nsjconf->iface_vs = NULL;
.iface_vs_nm = "255.255.255.0", nsjconf->iface_vs_ip = "0.0.0.0";
.iface_vs_gw = "0.0.0.0", nsjconf->iface_vs_nm = "255.255.255.0";
.kafel_file_path = NULL, nsjconf->iface_vs_gw = "0.0.0.0";
.kafel_string = NULL, nsjconf->kafel_file_path = NULL;
.orig_uid = getuid(), nsjconf->kafel_string = NULL;
.num_cpus = sysconf(_SC_NPROCESSORS_ONLN), nsjconf->orig_uid = getuid();
}; nsjconf->num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
TAILQ_INIT(&nsjconf->pids); TAILQ_INIT(&nsjconf->pids);
TAILQ_INIT(&nsjconf->mountpts); TAILQ_INIT(&nsjconf->mountpts);
@ -392,13 +400,13 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
static char cmdlineTmpfsSz[PATH_MAX] = "size=4194304"; static char cmdlineTmpfsSz[PATH_MAX] = "size=4194304";
struct ints_t* f; struct ints_t* f;
f = utilMalloc(sizeof(struct ints_t)); f = reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
f->val = STDIN_FILENO; f->val = STDIN_FILENO;
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers); TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
f = utilMalloc(sizeof(struct ints_t)); f = reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
f->val = STDOUT_FILENO; f->val = STDOUT_FILENO;
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers); TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
f = utilMalloc(sizeof(struct ints_t)); f = reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
f->val = STDERR_FILENO; f->val = STDERR_FILENO;
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers); TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
@ -433,7 +441,7 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
nsjconf->cwd = optarg; nsjconf->cwd = optarg;
break; break;
case 'C': case 'C':
if (configParse(nsjconf, optarg) == false) { if (configParse(nsjconf.get(), optarg) == false) {
LOG_F("Couldn't parse configuration from '%s' file", optarg); LOG_F("Couldn't parse configuration from '%s' file", optarg);
} }
break; break;
@ -452,14 +460,14 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
break; break;
case 'l': case 'l':
nsjconf->logfile = optarg; nsjconf->logfile = optarg;
if (logInitLogFile(nsjconf) == false) { if (logInitLogFile(nsjconf.get()) == false) {
return false; return nullptr;
} }
break; break;
case 'L': case 'L':
nsjconf->log_fd = strtol(optarg, NULL, 0); nsjconf->log_fd = strtol(optarg, NULL, 0);
if (logInitLogFile(nsjconf) == false) { if (logInitLogFile(nsjconf.get()) == false) {
return false; return nullptr;
} }
break; break;
case 'd': case 'd':
@ -467,20 +475,20 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
break; break;
case 'v': case 'v':
nsjconf->loglevel = DEBUG; nsjconf->loglevel = DEBUG;
if (logInitLogFile(nsjconf) == false) { if (logInitLogFile(nsjconf.get()) == false) {
return false; return nullptr;
} }
break; break;
case 'q': case 'q':
nsjconf->loglevel = WARNING; nsjconf->loglevel = WARNING;
if (logInitLogFile(nsjconf) == false) { if (logInitLogFile(nsjconf.get()) == false) {
return false; return nullptr;
} }
break; break;
case 'Q': case 'Q':
nsjconf->loglevel = FATAL; nsjconf->loglevel = FATAL;
if (logInitLogFile(nsjconf) == false) { if (logInitLogFile(nsjconf.get()) == false) {
return false; return nullptr;
} }
break; break;
case 'e': case 'e':
@ -494,25 +502,25 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
exit(0); exit(0);
break; break;
case 0x0201: case 0x0201:
nsjconf->rl_as = cmdlineParseRLimit(RLIMIT_AS, optarg, (1024 * 1024)); nsjconf->rl_as = parseRLimit(RLIMIT_AS, optarg, (1024 * 1024));
break; break;
case 0x0202: case 0x0202:
nsjconf->rl_core = cmdlineParseRLimit(RLIMIT_CORE, optarg, (1024 * 1024)); nsjconf->rl_core = parseRLimit(RLIMIT_CORE, optarg, (1024 * 1024));
break; break;
case 0x0203: case 0x0203:
nsjconf->rl_cpu = cmdlineParseRLimit(RLIMIT_CPU, optarg, 1); nsjconf->rl_cpu = parseRLimit(RLIMIT_CPU, optarg, 1);
break; break;
case 0x0204: case 0x0204:
nsjconf->rl_fsize = cmdlineParseRLimit(RLIMIT_FSIZE, optarg, (1024 * 1024)); nsjconf->rl_fsize = parseRLimit(RLIMIT_FSIZE, optarg, (1024 * 1024));
break; break;
case 0x0205: case 0x0205:
nsjconf->rl_nofile = cmdlineParseRLimit(RLIMIT_NOFILE, optarg, 1); nsjconf->rl_nofile = parseRLimit(RLIMIT_NOFILE, optarg, 1);
break; break;
case 0x0206: case 0x0206:
nsjconf->rl_nproc = cmdlineParseRLimit(RLIMIT_NPROC, optarg, 1); nsjconf->rl_nproc = parseRLimit(RLIMIT_NPROC, optarg, 1);
break; break;
case 0x0207: case 0x0207:
nsjconf->rl_stack = cmdlineParseRLimit(RLIMIT_STACK, optarg, (1024 * 1024)); nsjconf->rl_stack = parseRLimit(RLIMIT_STACK, optarg, (1024 * 1024));
break; break;
case 0x0301: case 0x0301:
nsjconf->personality |= ADDR_COMPAT_LAYOUT; nsjconf->personality |= ADDR_COMPAT_LAYOUT;
@ -564,7 +572,7 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
break; break;
case 0x0505: { case 0x0505: {
struct ints_t* f; struct ints_t* f;
f = utilMalloc(sizeof(struct ints_t)); f = reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
f->val = (int)strtol(optarg, NULL, 0); f->val = (int)strtol(optarg, NULL, 0);
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers); TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
} break; } break;
@ -575,10 +583,11 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
nsjconf->max_cpus = strtoul(optarg, NULL, 0); nsjconf->max_cpus = strtoul(optarg, NULL, 0);
break; break;
case 0x0509: { case 0x0509: {
struct ints_t* f = utilMalloc(sizeof(struct ints_t)); struct ints_t* f =
reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
f->val = capsNameToVal(optarg); f->val = capsNameToVal(optarg);
if (f->val == -1) { if (f->val == -1) {
return false; return nullptr;
} }
TAILQ_INSERT_HEAD(&nsjconf->caps, f, pointers); TAILQ_INSERT_HEAD(&nsjconf->caps, f, pointers);
} break; } break;
@ -603,7 +612,8 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
nsjconf->use_execveat = true; nsjconf->use_execveat = true;
break; break;
case 'E': { case 'E': {
struct charptr_t* p = utilMalloc(sizeof(struct charptr_t)); struct charptr_t* p = reinterpret_cast<struct charptr_t*>(
utilMalloc(sizeof(struct charptr_t)));
p->val = optarg; p->val = optarg;
TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers); TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers);
} break; } break;
@ -613,9 +623,9 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
char* cnt = cmdlineSplitStrByColon(o_id); char* cnt = cmdlineSplitStrByColon(o_id);
size_t count = size_t count =
(cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0); (cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0);
if (userParseId(nsjconf, i_id, o_id, count, false /* is_gid */, if (userParseId(nsjconf.get(), i_id, o_id, count, false /* is_gid */,
false /* is_newidmap */) == false) { false /* is_newidmap */) == false) {
return false; return nullptr;
} }
} break; } break;
case 'g': { case 'g': {
@ -624,9 +634,9 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
char* cnt = cmdlineSplitStrByColon(o_id); char* cnt = cmdlineSplitStrByColon(o_id);
size_t count = size_t count =
(cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0); (cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0);
if (userParseId(nsjconf, i_id, o_id, count, true /* is_gid */, if (userParseId(nsjconf.get(), i_id, o_id, count, true /* is_gid */,
false /* is_newidmap */) == false) { false /* is_newidmap */) == false) {
return false; return nullptr;
} }
} break; } break;
case 'U': { case 'U': {
@ -635,9 +645,9 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
char* cnt = cmdlineSplitStrByColon(o_id); char* cnt = cmdlineSplitStrByColon(o_id);
size_t count = size_t count =
(cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0); (cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0);
if (userParseId(nsjconf, i_id, o_id, count, false /* is_gid */, if (userParseId(nsjconf.get(), i_id, o_id, count, false /* is_gid */,
true /* is_newidmap */) == false) { true /* is_newidmap */) == false) {
return false; return nullptr;
} }
} break; } break;
case 'G': { case 'G': {
@ -646,38 +656,40 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
char* cnt = cmdlineSplitStrByColon(o_id); char* cnt = cmdlineSplitStrByColon(o_id);
size_t count = size_t count =
(cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0); (cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0);
if (userParseId(nsjconf, i_id, o_id, count, true /* is_gid */, if (userParseId(nsjconf.get(), i_id, o_id, count, true /* is_gid */,
true /* is_newidmap */) == false) { true /* is_newidmap */) == false) {
return false; return nullptr;
} }
} break; } break;
case 'R': { case 'R': {
const char* dst = cmdlineSplitStrByColon(optarg); const char* dst = cmdlineSplitStrByColon(optarg);
dst = dst ? dst : optarg; dst = dst ? dst : optarg;
if (!mountAddMountPtTail(nsjconf, /* src= */ optarg, dst, /* fs_type= */ "", if (!mountAddMountPtTail(nsjconf.get(), /* src= */ optarg, dst,
/* fs_type= */ "",
/* options= */ "", MS_BIND | MS_REC | MS_PRIVATE | MS_RDONLY, /* options= */ "", MS_BIND | MS_REC | MS_PRIVATE | MS_RDONLY,
/* isDir= */ NS_DIR_MAYBE, /* mandatory= */ true, NULL, NULL, NULL, /* isDir= */ NS_DIR_MAYBE, /* mandatory= */ true, NULL, NULL, NULL,
0, /* is_symlink= */ false)) { 0, /* is_symlink= */ false)) {
return false; return nullptr;
} }
}; break; }; break;
case 'B': { case 'B': {
const char* dst = cmdlineSplitStrByColon(optarg); const char* dst = cmdlineSplitStrByColon(optarg);
dst = dst ? dst : optarg; dst = dst ? dst : optarg;
if (!mountAddMountPtTail(nsjconf, /* src= */ optarg, dst, /* fs_type= */ "", if (!mountAddMountPtTail(nsjconf.get(), /* src= */ optarg, dst,
/* fs_type= */ "",
/* options= */ "", MS_BIND | MS_REC | MS_PRIVATE, /* options= */ "", MS_BIND | MS_REC | MS_PRIVATE,
/* isDir= */ NS_DIR_MAYBE, /* mandatory= */ true, NULL, NULL, NULL, /* isDir= */ NS_DIR_MAYBE, /* mandatory= */ true, NULL, NULL, NULL,
0, /* is_symlink= */ false)) { 0, /* is_symlink= */ false)) {
return false; return nullptr;
} }
}; break; }; break;
case 'T': { case 'T': {
if (!mountAddMountPtTail(nsjconf, /* src= */ NULL, optarg, "tmpfs", if (!mountAddMountPtTail(nsjconf.get(), /* src= */ NULL, optarg, "tmpfs",
/* options= */ cmdlineTmpfsSz, /* flags= */ 0, /* options= */ cmdlineTmpfsSz, /* flags= */ 0,
/* isDir= */ NS_DIR_YES, /* isDir= */ NS_DIR_YES,
/* mandatory= */ true, NULL, NULL, NULL, 0, /* mandatory= */ true, NULL, NULL, NULL, 0,
/* is_symlink= */ false)) { /* is_symlink= */ false)) {
return false; return nullptr;
} }
}; break; }; break;
case 'M': case 'M':
@ -700,7 +712,7 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
LOG_E(" -M r - MODE_STANDALONE_RERUN"); LOG_E(" -M r - MODE_STANDALONE_RERUN");
LOG_E(" -M e - MODE_STANDALONE_EXECVE"); LOG_E(" -M e - MODE_STANDALONE_EXECVE");
cmdlineUsage(argv[0]); cmdlineUsage(argv[0]);
return false; return nullptr;
break; break;
} }
break; break;
@ -760,7 +772,7 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
if (access(nsjconf->kafel_file_path, R_OK) == -1) { if (access(nsjconf->kafel_file_path, R_OK) == -1) {
PLOG_E("kafel config file '%s' cannot be opened for reading", PLOG_E("kafel config file '%s' cannot be opened for reading",
nsjconf->kafel_file_path); nsjconf->kafel_file_path);
return false; return nullptr;
} }
break; break;
case 0x0901: case 0x0901:
@ -768,37 +780,39 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
break; break;
default: default:
cmdlineUsage(argv[0]); cmdlineUsage(argv[0]);
return false; return nullptr;
break; break;
} }
} }
if (nsjconf->mount_proc) { if (nsjconf->mount_proc) {
if (!mountAddMountPtTail(nsjconf, /* src= */ NULL, nsjconf->proc_path, "proc", "", if (!mountAddMountPtTail(nsjconf.get(), /* src= */ NULL, nsjconf->proc_path, "proc",
nsjconf->is_proc_rw ? 0 : MS_RDONLY, /* isDir= */ NS_DIR_YES, "", nsjconf->is_proc_rw ? 0 : MS_RDONLY, /* isDir= */ NS_DIR_YES,
/* mandatory= */ true, NULL, NULL, NULL, 0, /* is_symlink= */ false)) { /* mandatory= */ true, NULL, NULL, NULL, 0, /* is_symlink= */ false)) {
return false; return nullptr;
} }
} }
if (nsjconf->chroot) { if (nsjconf->chroot) {
if (!mountAddMountPtHead(nsjconf, nsjconf->chroot, "/", /* fs_type= */ "", if (!mountAddMountPtHead(nsjconf.get(), nsjconf->chroot, "/", /* fs_type= */ "",
/* options= */ "", /* options= */ "",
nsjconf->is_root_rw ? (MS_BIND | MS_REC | MS_PRIVATE) nsjconf->is_root_rw ? (MS_BIND | MS_REC | MS_PRIVATE)
: (MS_BIND | MS_REC | MS_PRIVATE | MS_RDONLY), : (MS_BIND | MS_REC | MS_PRIVATE | MS_RDONLY),
/* isDir= */ NS_DIR_YES, /* mandatory= */ true, NULL, NULL, NULL, 0, /* isDir= */ NS_DIR_YES, /* mandatory= */ true, NULL, NULL, NULL, 0,
/* is_symlink= */ false)) { /* is_symlink= */ false)) {
return false; return nullptr;
} }
} else { } else {
if (!mountAddMountPtHead(nsjconf, /* src= */ NULL, "/", "tmpfs", /* options= */ "", if (!mountAddMountPtHead(nsjconf.get(), /* src= */ NULL, "/", "tmpfs",
nsjconf->is_root_rw ? 0 : MS_RDONLY, /* isDir= */ NS_DIR_YES, /* options= */ "", nsjconf->is_root_rw ? 0 : MS_RDONLY,
/* isDir= */ NS_DIR_YES,
/* mandatory= */ true, NULL, NULL, NULL, 0, /* is_symlink= */ false)) { /* mandatory= */ true, NULL, NULL, NULL, 0, /* is_symlink= */ false)) {
return false; return nullptr;
} }
} }
if (TAILQ_EMPTY(&nsjconf->uids)) { if (TAILQ_EMPTY(&nsjconf->uids)) {
struct idmap_t* p = utilMalloc(sizeof(struct idmap_t)); struct idmap_t* p =
reinterpret_cast<struct idmap_t*>(utilMalloc(sizeof(struct idmap_t)));
p->inside_id = getuid(); p->inside_id = getuid();
p->outside_id = getuid(); p->outside_id = getuid();
p->count = 1U; p->count = 1U;
@ -806,7 +820,8 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
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 =
reinterpret_cast<struct idmap_t*>(utilMalloc(sizeof(struct idmap_t)));
p->inside_id = getgid(); p->inside_id = getgid();
p->outside_id = getgid(); p->outside_id = getgid();
p->count = 1U; p->count = 1U;
@ -814,8 +829,8 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
TAILQ_INSERT_HEAD(&nsjconf->gids, p, pointers); TAILQ_INSERT_HEAD(&nsjconf->gids, p, pointers);
} }
if (logInitLogFile(nsjconf) == false) { if (logInitLogFile(nsjconf.get()) == false) {
return false; return nullptr;
} }
if (argv[optind]) { if (argv[optind]) {
@ -824,7 +839,7 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
if (nsjconf->argv == NULL || nsjconf->argv[0] == NULL) { if (nsjconf->argv == NULL || nsjconf->argv[0] == NULL) {
cmdlineUsage(argv[0]); cmdlineUsage(argv[0]);
LOG_E("No command provided"); LOG_E("No command provided");
return false; return nullptr;
} }
if (nsjconf->exec_file == NULL) { if (nsjconf->exec_file == NULL) {
nsjconf->exec_file = nsjconf->argv[0]; nsjconf->exec_file = nsjconf->argv[0];
@ -835,19 +850,21 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
LOG_E( LOG_E(
"Your nsjail is compiled without support for the execveat() syscall, yet you " "Your nsjail is compiled without support for the execveat() syscall, yet you "
"specified the --execute_fd flag"); "specified the --execute_fd flag");
return false; return nullptr;
#endif /* !defined(__NR_execveat) */ #endif /* !defined(__NR_execveat) */
if ((nsjconf->exec_fd = open(nsjconf->exec_file, O_RDONLY | O_PATH | O_CLOEXEC)) == if ((nsjconf->exec_fd = open(nsjconf->exec_file, O_RDONLY | O_PATH | O_CLOEXEC)) ==
-1) { -1) {
PLOG_W("Couldn't open '%s' file", nsjconf->exec_file); PLOG_W("Couldn't open '%s' file", nsjconf->exec_file);
return false; return nullptr;
} }
} }
if (!sandboxPrepare(nsjconf)) { if (!sandboxPrepare(nsjconf.get())) {
LOG_E("Couldn't prepare sandboxing setup"); LOG_E("Couldn't prepare sandboxing setup");
return false; return nullptr;
} }
return true; return nsjconf;
} }
} // namespace cmdline

View File

@ -22,23 +22,18 @@
#ifndef NS_CMDLINE_H #ifndef NS_CMDLINE_H
#define NS_CMDLINE_H #define NS_CMDLINE_H
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <sys/resource.h>
#include <sys/time.h> #include <memory>
#include "nsjail.h" #include "nsjail.h"
#ifdef __cplusplus namespace cmdline {
extern "C" {
#endif
uint64_t cmdlineParseRLimit(int res, const char* optarg, unsigned long mul); uint64_t parseRLimit(int res, const char* optarg, unsigned long mul);
void cmdlineLogParams(struct nsjconf_t* nsjconf); void logParams(struct nsjconf_t* nsjconf);
bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf); std::unique_ptr<struct nsjconf_t> parseArgs(int argc, char* argv[]);
#ifdef __cplusplus } // namespace cmdline
} // extern "C"
#endif
#endif /* _CMDLINE_H */ #endif /* _CMDLINE_H */

View File

@ -26,11 +26,11 @@ extern "C" {
#include <stdio.h> #include <stdio.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/personality.h> #include <sys/personality.h>
#include <sys/resource.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include "caps.h" #include "caps.h"
#include "cmdline.h"
#include "config.h" #include "config.h"
#include "log.h" #include "log.h"
#include "mount.h" #include "mount.h"
@ -38,6 +38,8 @@ extern "C" {
#include "util.h" #include "util.h"
} }
#include "cmdline.h"
#include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/text_format.h> #include <google/protobuf/text_format.h>
#include <fstream> #include <fstream>
@ -54,10 +56,10 @@ static uint64_t configRLimit(
return (val * mul); return (val * mul);
} }
if (rl == nsjail::RLimit::SOFT) { if (rl == nsjail::RLimit::SOFT) {
return cmdlineParseRLimit(res, "soft", mul); return cmdline::parseRLimit(res, "soft", mul);
} }
if (rl == nsjail::RLimit::HARD) { if (rl == nsjail::RLimit::HARD) {
return cmdlineParseRLimit(res, "hard", mul); return cmdline::parseRLimit(res, "hard", mul);
} }
if (rl == nsjail::RLimit::INF) { if (rl == nsjail::RLimit::INF) {
return RLIM64_INFINITY; return RLIM64_INFINITY;

View File

@ -157,28 +157,28 @@ static int nsjailStandaloneMode(struct nsjconf_t* nsjconf) {
} }
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
struct nsjconf_t nsjconf; std::unique_ptr<struct nsjconf_t> nsjconf = cmdline::parseArgs(argc, argv);
if (!cmdlineParse(argc, argv, &nsjconf)) { if (!nsjconf) {
LOG_F("Couldn't parse cmdline options"); LOG_F("Couldn't parse cmdline options");
} }
if (nsjconf.clone_newuser == false && geteuid() != 0) { if (nsjconf->clone_newuser == false && geteuid() != 0) {
LOG_W("--disable_clone_newuser might require root() privs"); LOG_W("--disable_clone_newuser might require root() privs");
} }
if (nsjconf.daemonize && (daemon(0, 0) == -1)) { if (nsjconf->daemonize && (daemon(0, 0) == -1)) {
PLOG_F("daemon"); PLOG_F("daemon");
} }
cmdlineLogParams(&nsjconf); cmdline::logParams(nsjconf.get());
if (nsjailSetSigHandlers() == false) { if (nsjailSetSigHandlers() == false) {
LOG_F("nsjailSetSigHandlers() failed"); LOG_F("nsjailSetSigHandlers() failed");
} }
if (nsjailSetTimer(&nsjconf) == false) { if (nsjailSetTimer(nsjconf.get()) == false) {
LOG_F("nsjailSetTimer() failed"); LOG_F("nsjailSetTimer() failed");
} }
if (nsjconf.mode == MODE_LISTEN_TCP) { if (nsjconf->mode == MODE_LISTEN_TCP) {
nsjailListenMode(&nsjconf); nsjailListenMode(nsjconf.get());
} else { } else {
return nsjailStandaloneMode(&nsjconf); return nsjailStandaloneMode(nsjconf.get());
} }
return 0; return 0;
} }