make indent

This commit is contained in:
Robert Swiecki 2017-10-08 23:00:45 +02:00
parent 414e999787
commit 74b43346bd
34 changed files with 871 additions and 871 deletions

View File

@ -92,7 +92,7 @@ depend:
makedepend -Y -Ykafel/include -- -- $(SRCS_C) $(SRCS_CXX) $(SRCS_PB_CXX)
indent:
clang-format --style=WebKit -i -sort-includes *.c *.h $(SRCS_CXX)
clang-format -style="{BasedOnStyle: webkit, IndentWidth: 8, UseTab: Always, IndentCaseLabels: false}" -i -sort-includes *.c *.h $(SRCS_CXX)
# DO NOT DELETE THIS LINE -- make depend depends on it.

36
caps.c
View File

@ -32,13 +32,13 @@
#include "util.h"
#define VALSTR_STRUCT(x) \
{ \
x, #x \
}
{ \
x, #x \
}
#if !defined(CAP_AUDIT_READ)
#define CAP_AUDIT_READ 37
#endif /* !defined(CAP_AUDIT_READ) */
#endif /* !defined(CAP_AUDIT_READ) */
// clang-format off
static struct {
@ -86,7 +86,7 @@ static struct {
};
// clang-format on
int capsNameToVal(const char *name)
int capsNameToVal(const char* name)
{
for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
if (strcmp(name, capNames[i].name) == 0) {
@ -97,7 +97,7 @@ int capsNameToVal(const char *name)
return -1;
}
static const char *capsValToStr(int val)
static const char* capsValToStr(int val)
{
static __thread char capsStr[1024];
for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
@ -177,7 +177,7 @@ static void capsSetInheritable(cap_user_data_t cap_data, unsigned int cap)
#define PR_CAP_AMBIENT 47
#define PR_CAP_AMBIENT_RAISE 2
#define PR_CAP_AMBIENT_CLEAR_ALL 4
#endif /* !defined(PR_CAP_AMBIENT) */
#endif /* !defined(PR_CAP_AMBIENT) */
static bool CapsInitNsKeepCaps(cap_user_data_t cap_data)
{
char dbgmsg[4096];
@ -203,7 +203,7 @@ static bool CapsInitNsKeepCaps(cap_user_data_t cap_data)
continue;
}
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, (unsigned long)capNames[i].val, 0UL,
0UL)
0UL)
== -1) {
PLOG_W("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, %s)", capNames[i].name);
} else {
@ -215,10 +215,10 @@ static bool CapsInitNsKeepCaps(cap_user_data_t cap_data)
return true;
}
bool capsInitNs(struct nsjconf_t * nsjconf)
bool capsInitNs(struct nsjconf_t* nsjconf)
{
char dbgmsg[4096];
struct ints_t *p;
struct ints_t* p;
cap_user_data_t cap_data = capsGet();
if (cap_data == NULL) {
@ -241,10 +241,11 @@ bool capsInitNs(struct nsjconf_t * nsjconf)
/* Set all requested caps in the inheritable set if these are present in the permitted set */
dbgmsg[0] = '\0';
TAILQ_FOREACH(p, &nsjconf->caps, pointers) {
TAILQ_FOREACH(p, &nsjconf->caps, pointers)
{
if (capsGetPermitted(cap_data, p->val) == false) {
LOG_W("Capability %s is not permitted in the namespace",
capsValToStr(p->val));
capsValToStr(p->val));
return false;
}
utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capsValToStr(p->val));
@ -267,8 +268,7 @@ bool capsInitNs(struct nsjconf_t * nsjconf)
continue;
}
utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
if (prctl(PR_CAPBSET_DROP, (unsigned long)capNames[i].val, 0UL, 0UL, 0UL) ==
-1) {
if (prctl(PR_CAPBSET_DROP, (unsigned long)capNames[i].val, 0UL, 0UL, 0UL) == -1) {
PLOG_W("prctl(PR_CAPBSET_DROP, %s)", capNames[i].name);
return false;
}
@ -278,11 +278,11 @@ bool capsInitNs(struct nsjconf_t * nsjconf)
/* Make sure inheritable set is preserved across execve via the modified ambient set */
dbgmsg[0] = '\0';
TAILQ_FOREACH(p, &nsjconf->caps, pointers) {
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, (unsigned long)p->val, 0UL, 0UL) ==
-1) {
TAILQ_FOREACH(p, &nsjconf->caps, pointers)
{
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, (unsigned long)p->val, 0UL, 0UL) == -1) {
PLOG_W("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, %s)",
capsValToStr(p->val));
capsValToStr(p->val));
} else {
utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capsValToStr(p->val));
}

6
caps.h
View File

@ -24,7 +24,7 @@
#include "common.h"
int capsNameToVal(const char *name);
bool capsInitNs(struct nsjconf_t *nsjconf);
int capsNameToVal(const char* name);
bool capsInitNs(struct nsjconf_t* nsjconf);
#endif /* NS_CAPS_H */
#endif /* NS_CAPS_H */

View File

@ -36,15 +36,15 @@
#include "log.h"
#include "util.h"
static bool cgroupInitNsFromParentMem(struct nsjconf_t *nsjconf, pid_t pid)
static bool cgroupInitNsFromParentMem(struct nsjconf_t* nsjconf, pid_t pid)
{
if (nsjconf->cgroup_mem_max == (size_t) 0) {
if (nsjconf->cgroup_mem_max == (size_t)0) {
return true;
}
char mem_cgroup_path[PATH_MAX];
snprintf(mem_cgroup_path, sizeof(mem_cgroup_path), "%s/%s/NSJAIL.%d",
nsjconf->cgroup_mem_mount, nsjconf->cgroup_mem_parent, (int)pid);
nsjconf->cgroup_mem_mount, nsjconf->cgroup_mem_parent, (int)pid);
LOG_D("Create '%s' for PID=%d", mem_cgroup_path, (int)pid);
if (mkdir(mem_cgroup_path, 0700) == -1 && errno != EEXIST) {
PLOG_E("mkdir('%s', 0711) failed", mem_cgroup_path);
@ -52,7 +52,7 @@ static bool cgroupInitNsFromParentMem(struct nsjconf_t *nsjconf, pid_t pid)
}
char fname[PATH_MAX];
if (nsjconf->cgroup_mem_max != (size_t) 0) {
if (nsjconf->cgroup_mem_max != (size_t)0) {
char mem_max_str[512];
snprintf(mem_max_str, sizeof(mem_max_str), "%zu", nsjconf->cgroup_mem_max);
snprintf(fname, sizeof(fname), "%s/memory.limit_in_bytes", mem_cgroup_path);
@ -85,15 +85,15 @@ static bool cgroupInitNsFromParentMem(struct nsjconf_t *nsjconf, pid_t pid)
return true;
}
static bool cgroupInitNsFromParentPids(struct nsjconf_t *nsjconf, pid_t pid)
static bool cgroupInitNsFromParentPids(struct nsjconf_t* nsjconf, pid_t pid)
{
if (nsjconf->cgroup_pids_max == (size_t) 0) {
if (nsjconf->cgroup_pids_max == (size_t)0) {
return true;
}
char pids_cgroup_path[PATH_MAX];
snprintf(pids_cgroup_path, sizeof(pids_cgroup_path), "%s/%s/NSJAIL.%d",
nsjconf->cgroup_pids_mount, nsjconf->cgroup_pids_parent, (int)pid);
nsjconf->cgroup_pids_mount, nsjconf->cgroup_pids_parent, (int)pid);
LOG_D("Create '%s' for PID=%d", pids_cgroup_path, (int)pid);
if (mkdir(pids_cgroup_path, 0700) == -1 && errno != EEXIST) {
PLOG_E("mkdir('%s', 0711) failed", pids_cgroup_path);
@ -101,13 +101,12 @@ static bool cgroupInitNsFromParentPids(struct nsjconf_t *nsjconf, pid_t pid)
}
char fname[PATH_MAX];
if (nsjconf->cgroup_pids_max != (size_t) 0) {
if (nsjconf->cgroup_pids_max != (size_t)0) {
char pids_max_str[512];
snprintf(pids_max_str, sizeof(pids_max_str), "%zu", nsjconf->cgroup_pids_max);
snprintf(fname, sizeof(fname), "%s/pids.max", pids_cgroup_path);
LOG_D("Setting '%s' to '%s'", fname, pids_max_str);
if (utilWriteBufToFile(fname, pids_max_str, strlen(pids_max_str), O_WRONLY) ==
false) {
if (utilWriteBufToFile(fname, pids_max_str, strlen(pids_max_str), O_WRONLY) == false) {
LOG_E("Could not update pids cgroup max limit");
return false;
}
@ -125,7 +124,7 @@ static bool cgroupInitNsFromParentPids(struct nsjconf_t *nsjconf, pid_t pid)
return true;
}
bool cgroupInitNsFromParent(struct nsjconf_t * nsjconf, pid_t pid)
bool cgroupInitNsFromParent(struct nsjconf_t* nsjconf, pid_t pid)
{
if (cgroupInitNsFromParentMem(nsjconf, pid) == false) {
return false;
@ -136,14 +135,14 @@ bool cgroupInitNsFromParent(struct nsjconf_t * nsjconf, pid_t pid)
return true;
}
void cgroupFinishFromParentMem(struct nsjconf_t *nsjconf, pid_t pid)
void cgroupFinishFromParentMem(struct nsjconf_t* nsjconf, pid_t pid)
{
if (nsjconf->cgroup_mem_max == (size_t) 0) {
if (nsjconf->cgroup_mem_max == (size_t)0) {
return;
}
char mem_cgroup_path[PATH_MAX];
snprintf(mem_cgroup_path, sizeof(mem_cgroup_path), "%s/%s/NSJAIL.%d",
nsjconf->cgroup_mem_mount, nsjconf->cgroup_mem_parent, (int)pid);
nsjconf->cgroup_mem_mount, nsjconf->cgroup_mem_parent, (int)pid);
LOG_D("Remove '%s'", mem_cgroup_path);
if (rmdir(mem_cgroup_path) == -1) {
PLOG_W("rmdir('%s') failed", mem_cgroup_path);
@ -151,14 +150,14 @@ void cgroupFinishFromParentMem(struct nsjconf_t *nsjconf, pid_t pid)
return;
}
void cgroupFinishFromParentPids(struct nsjconf_t *nsjconf, pid_t pid)
void cgroupFinishFromParentPids(struct nsjconf_t* nsjconf, pid_t pid)
{
if (nsjconf->cgroup_pids_max == (size_t) 0) {
if (nsjconf->cgroup_pids_max == (size_t)0) {
return;
}
char pids_cgroup_path[PATH_MAX];
snprintf(pids_cgroup_path, sizeof(pids_cgroup_path), "%s/%s/NSJAIL.%d",
nsjconf->cgroup_pids_mount, nsjconf->cgroup_pids_parent, (int)pid);
nsjconf->cgroup_pids_mount, nsjconf->cgroup_pids_parent, (int)pid);
LOG_D("Remove '%s'", pids_cgroup_path);
if (rmdir(pids_cgroup_path) == -1) {
PLOG_W("rmdir('%s') failed", pids_cgroup_path);
@ -166,7 +165,7 @@ void cgroupFinishFromParentPids(struct nsjconf_t *nsjconf, pid_t pid)
return;
}
void cgroupFinishFromParent(struct nsjconf_t *nsjconf, pid_t pid)
void cgroupFinishFromParent(struct nsjconf_t* nsjconf, pid_t pid)
{
cgroupFinishFromParentMem(nsjconf, pid);
cgroupFinishFromParentPids(nsjconf, pid);

View File

@ -27,8 +27,8 @@
#include "common.h"
bool cgroupInitNsFromParent(struct nsjconf_t *nsjconf, pid_t pid);
bool cgroupInitNsFromParent(struct nsjconf_t* nsjconf, pid_t pid);
bool cgroupInitNs(void);
void cgroupFinishFromParent(struct nsjconf_t *nsjconf, pid_t pid);
void cgroupFinishFromParent(struct nsjconf_t* nsjconf, pid_t pid);
#endif /* _CGROUP_H */
#endif /* _CGROUP_H */

335
cmdline.c
View File

@ -50,7 +50,7 @@
struct custom_option {
struct option opt;
const char *descr;
const char* descr;
};
// clang-format off
@ -140,24 +140,24 @@ struct custom_option deprecated_opts[] = {
};
// clang-format on
static const char *logYesNo(bool yes)
static const char* logYesNo(bool yes)
{
return (yes ? "true" : "false");
}
static void cmdlineOptUsage(struct custom_option *option)
static void cmdlineOptUsage(struct custom_option* option)
{
if (option->opt.val < 0x80) {
LOG_HELP_BOLD(" --%s%s%c %s", option->opt.name, "|-", option->opt.val,
option->opt.has_arg == required_argument ? "VALUE" : "");
option->opt.has_arg == required_argument ? "VALUE" : "");
} else {
LOG_HELP_BOLD(" --%s %s", option->opt.name,
option->opt.has_arg == required_argument ? "VALUE" : "");
option->opt.has_arg == required_argument ? "VALUE" : "");
}
LOG_HELP("\t%s", option->descr);
}
static void cmdlineUsage(const char *pname)
static void cmdlineUsage(const char* pname)
{
LOG_HELP_BOLD("Usage: %s [options] -- path_to_command [args]", pname);
LOG_HELP_BOLD("Options:");
@ -171,7 +171,7 @@ static void cmdlineUsage(const char *pname)
for (size_t j = 0; j < ARRAYSIZE(custom_opts); j++) {
if (custom_opts[j].opt.val == deprecated_opts[i].opt.val) {
LOG_HELP_BOLD("\tDEPRECATED: Use %s instead.",
custom_opts[j].opt.name);
custom_opts[j].opt.name);
break;
}
}
@ -187,7 +187,7 @@ static void cmdlineUsage(const char *pname)
LOG_HELP_BOLD(" nsjail -Me --chroot / --disable_proc -- /bin/echo \"ABC\"");
}
void cmdlineLogParams(struct nsjconf_t *nsjconf)
void cmdlineLogParams(struct nsjconf_t* nsjconf)
{
switch (nsjconf->mode) {
case MODE_LISTEN_TCP:
@ -213,46 +213,47 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
"clone_newnet:%s, clone_newuser:%s, clone_newns:%s, clone_newpid:%s, "
"clone_newipc:%s, clonew_newuts:%s, clone_newcgroup:%s, keep_caps:%s, "
"tmpfs_size:%zu, disable_no_new_privs:%s, max_cpus:%zu",
nsjconf->hostname, nsjconf->chroot ? nsjconf->chroot : "[NULL]", nsjconf->argv[0],
nsjconf->bindhost, nsjconf->port, nsjconf->max_conns_per_ip, nsjconf->tlimit,
nsjconf->personality, logYesNo(nsjconf->daemonize), logYesNo(nsjconf->clone_newnet),
logYesNo(nsjconf->clone_newuser), logYesNo(nsjconf->clone_newns),
logYesNo(nsjconf->clone_newpid), logYesNo(nsjconf->clone_newipc),
logYesNo(nsjconf->clone_newuts), logYesNo(nsjconf->clone_newcgroup),
logYesNo(nsjconf->keep_caps), nsjconf->tmpfs_size,
logYesNo(nsjconf->disable_no_new_privs), nsjconf->max_cpus);
nsjconf->hostname, nsjconf->chroot ? nsjconf->chroot : "[NULL]", nsjconf->argv[0],
nsjconf->bindhost, nsjconf->port, nsjconf->max_conns_per_ip, nsjconf->tlimit,
nsjconf->personality, logYesNo(nsjconf->daemonize), logYesNo(nsjconf->clone_newnet),
logYesNo(nsjconf->clone_newuser), logYesNo(nsjconf->clone_newns),
logYesNo(nsjconf->clone_newpid), logYesNo(nsjconf->clone_newipc),
logYesNo(nsjconf->clone_newuts), logYesNo(nsjconf->clone_newcgroup),
logYesNo(nsjconf->keep_caps), nsjconf->tmpfs_size,
logYesNo(nsjconf->disable_no_new_privs), nsjconf->max_cpus);
{
struct mounts_t *p;
TAILQ_FOREACH(p, &nsjconf->mountpts, pointers) {
struct mounts_t* p;
TAILQ_FOREACH(p, &nsjconf->mountpts, pointers)
{
LOG_I("%s: %s", p->isSymlink ? "Symlink" : "Mount point",
mountDescribeMountPt(p));
mountDescribeMountPt(p));
}
}
{
struct idmap_t *p;
TAILQ_FOREACH(p, &nsjconf->uids, pointers) {
struct idmap_t* p;
TAILQ_FOREACH(p, &nsjconf->uids, pointers)
{
LOG_I("Uid map: inside_uid:%lu outside_uid:%lu count:%zu newuidmap:%s",
(unsigned long)p->inside_id, (unsigned long)p->outside_id, p->count,
p->is_newidmap ? "true" : "false");
(unsigned long)p->inside_id, (unsigned long)p->outside_id, p->count,
p->is_newidmap ? "true" : "false");
if (p->outside_id == 0 && nsjconf->clone_newuser) {
LOG_W
("Process will be UID/EUID=0 in the global user namespace, and will have user root-level access to files");
LOG_W("Process will be UID/EUID=0 in the global user namespace, and will have user root-level access to files");
}
}
TAILQ_FOREACH(p, &nsjconf->gids, pointers) {
TAILQ_FOREACH(p, &nsjconf->gids, pointers)
{
LOG_I("Gid map: inside_gid:%lu outside_gid:%lu count:%zu newgidmap:%s",
(unsigned long)p->inside_id, (unsigned long)p->outside_id, p->count,
p->is_newidmap ? "true" : "false");
(unsigned long)p->inside_id, (unsigned long)p->outside_id, p->count,
p->is_newidmap ? "true" : "false");
if (p->outside_id == 0 && nsjconf->clone_newuser) {
LOG_W
("Process will be GID/EGID=0 in the global user namespace, and will have group root-level access to files");
LOG_W("Process will be GID/EGID=0 in the global user namespace, and will have group root-level access to files");
}
}
}
}
__rlim64_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
__rlim64_t cmdlineParseRLimit(int res, const char* optarg, unsigned long mul)
{
if (strcasecmp(optarg, "inf") == 0) {
return RLIM64_INFINITY;
@ -268,9 +269,8 @@ __rlim64_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
return cur.rlim_max;
}
if (utilIsANumber(optarg) == false) {
LOG_F
("RLIMIT %d needs a numeric or 'max'/'hard'/'def'/'soft'/'inf' value ('%s' provided)",
res, optarg);
LOG_F("RLIMIT %d needs a numeric or 'max'/'hard'/'def'/'soft'/'inf' value ('%s' provided)",
res, optarg);
}
__rlim64_t val = strtoull(optarg, NULL, 0) * mul;
if (val == ULLONG_MAX && errno != 0) {
@ -282,13 +282,13 @@ __rlim64_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
/* findSpecDestination mutates spec (source:dest) to have a null byte instead
* of ':' in between source and dest, then returns a pointer to the dest
* string. */
static char *cmdlineSplitStrByColon(char *spec)
static char* cmdlineSplitStrByColon(char* spec)
{
if (spec == NULL) {
return NULL;
}
char *dest = spec;
char* dest = spec;
while (*dest != ':' && *dest != '\0') {
dest++;
}
@ -305,9 +305,9 @@ static char *cmdlineSplitStrByColon(char *spec)
}
}
bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf)
{
// clang-format off
// clang-format off
(*nsjconf) = (const struct nsjconf_t){
.exec_file = NULL,
.hostname = "NSJAIL",
@ -361,7 +361,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
.kafel_string = NULL,
.num_cpus = sysconf(_SC_NPROCESSORS_ONLN),
};
// clang-format on
// clang-format on
TAILQ_INIT(&nsjconf->pids);
TAILQ_INIT(&nsjconf->mountpts);
@ -373,7 +373,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
static char cmdlineTmpfsSz[PATH_MAX] = "size=4194304";
struct ints_t *f;
struct ints_t* f;
f = utilMalloc(sizeof(struct ints_t));
f->val = STDIN_FILENO;
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
@ -400,8 +400,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
int opt_index = 0;
for (;;) {
int c = getopt_long(argc, argv,
"x:H:D:C:c:p:i:u:g:l:L:t:M:NdvqQeh?E:R:B:T:P:I:U:G:", opts,
&opt_index);
"x:H:D:C:c:p:i:u:g:l:L:t:M:NdvqQeh?E:R:B:T:P:I:U:G:", opts,
&opt_index);
if (c == -1) {
break;
}
@ -472,7 +472,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
case 't':
nsjconf->tlimit = strtol(optarg, NULL, 0);
break;
case 'h': /* help */
case 'h': /* help */
cmdlineUsage(argv[0]);
exit(0);
break;
@ -542,138 +542,134 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
case 0x0504:
nsjconf->skip_setsid = true;
break;
case 0x0505:{
struct ints_t *f;
f = utilMalloc(sizeof(struct ints_t));
f->val = (int)strtol(optarg, NULL, 0);
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
} break;
case 0x0505: {
struct ints_t* f;
f = utilMalloc(sizeof(struct ints_t));
f->val = (int)strtol(optarg, NULL, 0);
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
} break;
case 0x0507:
nsjconf->disable_no_new_privs = true;
break;
case 0x0508:
nsjconf->max_cpus = strtoul(optarg, NULL, 0);
break;
case 0x509:{
struct ints_t *f = utilMalloc(sizeof(struct ints_t));
f->val = capsNameToVal(optarg);
if (f->val == -1) {
return false;
}
TAILQ_INSERT_HEAD(&nsjconf->caps, f, pointers);
case 0x509: {
struct ints_t* f = utilMalloc(sizeof(struct ints_t));
f->val = capsNameToVal(optarg);
if (f->val == -1) {
return false;
}
break;
TAILQ_INSERT_HEAD(&nsjconf->caps, f, pointers);
} break;
case 0x0601:
nsjconf->is_root_rw = true;
break;
case 0x0602:
nsjconf->tmpfs_size = strtoull(optarg, NULL, 0);
snprintf(cmdlineTmpfsSz, sizeof(cmdlineTmpfsSz), "size=%zu",
nsjconf->tmpfs_size);
nsjconf->tmpfs_size);
break;
case 0x0603:
nsjconf->mount_proc = false;
break;
case 'E':{
struct charptr_t *p = utilMalloc(sizeof(struct charptr_t));
p->val = optarg;
TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers);
} 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);
if (userParseId(nsjconf, i_id, o_id, count, false /* is_gid */ ,
false /* is_newidmap */ )
== false) {
return false;
}
case 'E': {
struct charptr_t* p = utilMalloc(sizeof(struct charptr_t));
p->val = optarg;
TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers);
} 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);
if (userParseId(nsjconf, i_id, o_id, count, false /* is_gid */,
false /* is_newidmap */)
== false) {
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);
if (userParseId(nsjconf, i_id, o_id, count, true /* is_gid */ ,
false /* is_newidmap */ )
== false) {
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);
if (userParseId(nsjconf, i_id, o_id, count, true /* is_gid */,
false /* is_newidmap */)
== false) {
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);
if (userParseId(nsjconf, i_id, o_id, count, false /* is_gid */ ,
true /* is_newidmap */ )
== false) {
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);
if (userParseId(nsjconf, i_id, o_id, count, false /* is_gid */,
true /* is_newidmap */)
== false) {
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);
if (userParseId(nsjconf, i_id, o_id, count, true /* is_gid */ ,
true /* is_newidmap */ )
== false) {
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);
if (userParseId(nsjconf, i_id, o_id, count, true /* is_gid */,
true /* is_newidmap */)
== false) {
return false;
}
break;
case 'R':{
const char *dst = cmdlineSplitStrByColon(optarg);
dst = dst ? dst : optarg;
if (!mountAddMountPtTail
(nsjconf, /* src= */ optarg, dst, /* fs_type= */ "",
/* options= */ "", MS_BIND | MS_REC | MS_RDONLY,
/* isDir= */
NS_DIR_MAYBE, /* mandatory= */ true, NULL, NULL, NULL, 0,
/* is_symlink= */ false)) {
return false;
}
};
break;
case 'B':{
const char *dst = cmdlineSplitStrByColon(optarg);
dst = dst ? dst : optarg;
if (!mountAddMountPtTail
(nsjconf, /* src= */ optarg, dst, /* fs_type= */ "",
/* options= */ "", MS_BIND | MS_REC, /* isDir= */ NS_DIR_MAYBE,
/* mandatory= */ true, NULL, NULL, NULL, 0,
/* is_symlink= */
false)) {
return false;
}
};
break;
case 'T':{
if (!mountAddMountPtTail
(nsjconf, /* src= */ NULL, optarg, "tmpfs", /* options= */ "",
/* flags= */ 0, /* isDir= */ true, /* mandatory= */ true, NULL,
NULL, NULL, 0, /* is_symlink= */ false)) {
return false;
}
};
break;
} break;
case 'R': {
const char* dst = cmdlineSplitStrByColon(optarg);
dst = dst ? dst : optarg;
if (!mountAddMountPtTail(nsjconf, /* src= */ optarg, dst, /* fs_type= */ "",
/* options= */ "", MS_BIND | MS_REC | MS_RDONLY,
/* isDir= */
NS_DIR_MAYBE, /* mandatory= */ true, NULL, NULL, NULL, 0,
/* is_symlink= */ false)) {
return false;
}
};
break;
case 'B': {
const char* dst = cmdlineSplitStrByColon(optarg);
dst = dst ? dst : optarg;
if (!mountAddMountPtTail(nsjconf, /* src= */ optarg, dst, /* fs_type= */ "",
/* options= */ "", MS_BIND | MS_REC, /* isDir= */ NS_DIR_MAYBE,
/* mandatory= */ true, NULL, NULL, NULL, 0,
/* is_symlink= */
false)) {
return false;
}
};
break;
case 'T': {
if (!mountAddMountPtTail(nsjconf, /* src= */ NULL, optarg, "tmpfs", /* options= */ "",
/* flags= */ 0, /* isDir= */ true, /* mandatory= */ true, NULL,
NULL, NULL, 0, /* is_symlink= */ false)) {
return false;
}
};
break;
case 'M':
switch (optarg[0]) {
case 'l':
@ -714,7 +710,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
nsjconf->iface_vs_gw = optarg;
break;
case 0x801:
nsjconf->cgroup_mem_max = (size_t) strtoull(optarg, NULL, 0);
nsjconf->cgroup_mem_max = (size_t)strtoull(optarg, NULL, 0);
break;
case 0x802:
nsjconf->cgroup_mem_mount = optarg;
@ -723,7 +719,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
nsjconf->cgroup_mem_parent = optarg;
break;
case 0x811:
nsjconf->cgroup_pids_max = (size_t) strtoull(optarg, NULL, 0);
nsjconf->cgroup_pids_max = (size_t)strtoull(optarg, NULL, 0);
break;
case 0x812:
nsjconf->cgroup_pids_mount = optarg;
@ -748,31 +744,30 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
if (nsjconf->mount_proc == true) {
if (!mountAddMountPtHead(nsjconf, /* src= */ NULL, "/proc", "proc", "",
nsjconf->is_root_rw ? 0 : MS_RDONLY, /* isDir= */ true,
/* mandatory= */ true,
NULL, NULL, NULL, 0, /* is_symlink= */ false)) {
nsjconf->is_root_rw ? 0 : MS_RDONLY, /* isDir= */ true,
/* mandatory= */ true,
NULL, NULL, NULL, 0, /* is_symlink= */ false)) {
return false;
}
}
if (nsjconf->chroot != NULL) {
if (!mountAddMountPtHead
(nsjconf, nsjconf->chroot, "/", /* fs_type= */ "", /* options= */ "",
nsjconf->is_root_rw ? (MS_BIND | MS_REC) : (MS_BIND | MS_REC | MS_RDONLY),
/* isDir= */ true, /* mandatory= */ true, NULL, NULL, NULL, 0,
/* is_symlink= */ false)) {
if (!mountAddMountPtHead(nsjconf, nsjconf->chroot, "/", /* fs_type= */ "", /* options= */ "",
nsjconf->is_root_rw ? (MS_BIND | MS_REC) : (MS_BIND | MS_REC | MS_RDONLY),
/* isDir= */ true, /* mandatory= */ true, NULL, NULL, NULL, 0,
/* is_symlink= */ false)) {
return false;
}
} else {
if (!mountAddMountPtHead(nsjconf, /* src= */ NULL, "/", "tmpfs", /* options= */ "",
nsjconf->is_root_rw ? 0 : MS_RDONLY, /* isDir= */ true,
/* mandatory= */ true,
NULL, NULL, NULL, 0, /* is_symlink= */ false)) {
nsjconf->is_root_rw ? 0 : MS_RDONLY, /* isDir= */ true,
/* mandatory= */ true,
NULL, NULL, NULL, 0, /* is_symlink= */ false)) {
return false;
}
}
if (TAILQ_EMPTY(&nsjconf->uids)) {
struct idmap_t *p = utilMalloc(sizeof(struct idmap_t));
struct idmap_t* p = utilMalloc(sizeof(struct idmap_t));
p->inside_id = getuid();
p->outside_id = getuid();
p->count = 1U;
@ -780,7 +775,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
TAILQ_INSERT_HEAD(&nsjconf->uids, p, pointers);
}
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->outside_id = getgid();
p->count = 1U;
@ -793,7 +788,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
}
if (argv[optind]) {
nsjconf->argv = (const char **)&argv[optind];
nsjconf->argv = (const char**)&argv[optind];
}
if (nsjconf->argv == NULL || nsjconf->argv[0] == NULL) {
cmdlineUsage(argv[0]);

View File

@ -27,8 +27,8 @@
#include "common.h"
__rlim64_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul);
void cmdlineLogParams(struct nsjconf_t *nsjconf);
bool cmdlineParse(int argc, char *argv[], struct nsjconf_t *nsjconf);
__rlim64_t cmdlineParseRLimit(int res, const char* optarg, unsigned long mul);
void cmdlineLogParams(struct nsjconf_t* nsjconf);
bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf);
#endif /* _CMDLINE_H */
#endif /* _CMDLINE_H */

106
common.h
View File

@ -33,7 +33,7 @@
#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 */
#define __STRMERGE(a, b) a##b
#define _STRMERGE(a, b) __STRMERGE(a, b)
@ -47,10 +47,10 @@ static void __attribute__ ((unused)) __clang_cleanup_func(void (^*dfunc) (void))
#define defer void (^_STRMERGE(__defer_f_, __COUNTER__))(void) __attribute__((cleanup(__clang_cleanup_func))) __attribute__((unused)) = ^
#else
#define __block
#define _DEFER(a, count) \
auto void _STRMERGE(__defer_f_, count)(void* _defer_arg __attribute__((unused))); \
int _STRMERGE(__defer_var_, count) __attribute__((cleanup(_STRMERGE(__defer_f_, count)))) __attribute__((unused)); \
void _STRMERGE(__defer_f_, count)(void* _defer_arg __attribute__((unused)))
#define _DEFER(a, count) \
auto void _STRMERGE(__defer_f_, count)(void* _defer_arg __attribute__((unused))); \
int _STRMERGE(__defer_var_, count) __attribute__((cleanup(_STRMERGE(__defer_f_, count)))) __attribute__((unused)); \
void _STRMERGE(__defer_f_, count)(void* _defer_arg __attribute__((unused)))
#define defer _DEFER(a, __COUNTER__)
#endif
#endif
@ -61,24 +61,24 @@ struct pids_t {
char remote_txt[64];
struct sockaddr_in6 remote_addr;
int pid_syscall_fd;
TAILQ_ENTRY(pids_t)
pointers;
TAILQ_ENTRY(pids_t)
pointers;
};
struct mounts_t {
const char *src;
const uint8_t *src_content;
const char* src;
const uint8_t* src_content;
size_t src_content_len;
const char *dst;
const char *fs_type;
const char *options;
const char* dst;
const char* fs_type;
const char* options;
uintptr_t flags;
bool isDir;
bool isSymlink;
bool mandatory;
bool mounted;
TAILQ_ENTRY(mounts_t)
pointers;
TAILQ_ENTRY(mounts_t)
pointers;
};
struct idmap_t {
@ -86,14 +86,14 @@ struct idmap_t {
uid_t outside_id;
size_t count;
bool is_newidmap;
TAILQ_ENTRY(idmap_t)
pointers;
TAILQ_ENTRY(idmap_t)
pointers;
};
struct ints_t {
int val;
TAILQ_ENTRY(ints_t)
pointers;
TAILQ_ENTRY(ints_t)
pointers;
};
enum ns_mode_t {
@ -104,9 +104,9 @@ enum ns_mode_t {
};
struct charptr_t {
const char *val;
TAILQ_ENTRY(charptr_t)
pointers;
const char* val;
TAILQ_ENTRY(charptr_t)
pointers;
};
enum llevel_t {
@ -120,14 +120,14 @@ enum llevel_t {
};
struct nsjconf_t {
const char *exec_file;
const char *hostname;
const char *cwd;
const char **argv;
const char* exec_file;
const char* hostname;
const char* cwd;
const char** argv;
int port;
const char *bindhost;
const char* bindhost;
int log_fd;
const char *logfile;
const char* logfile;
enum llevel_t loglevel;
bool daemonize;
time_t tlimit;
@ -151,7 +151,7 @@ struct nsjconf_t {
bool clone_newuts;
bool clone_newcgroup;
enum ns_mode_t mode;
const char *chroot;
const char* chroot;
bool is_root_rw;
bool is_silent;
bool skip_setsid;
@ -159,34 +159,34 @@ struct nsjconf_t {
size_t tmpfs_size;
bool mount_proc;
bool iface_no_lo;
const char *iface_vs;
const char *iface_vs_ip;
const char *iface_vs_nm;
const char *iface_vs_gw;
const char *cgroup_mem_mount;
const char *cgroup_mem_parent;
const char* iface_vs;
const char* iface_vs_ip;
const char* iface_vs_nm;
const char* iface_vs_gw;
const char* cgroup_mem_mount;
const char* cgroup_mem_parent;
size_t cgroup_mem_max;
const char *cgroup_pids_mount;
const char *cgroup_pids_parent;
const char* cgroup_pids_mount;
const char* cgroup_pids_parent;
size_t cgroup_pids_max;
FILE *kafel_file;
char *kafel_string;
FILE* kafel_file;
char* kafel_string;
uid_t orig_euid;
long num_cpus;
TAILQ_HEAD(udmaplist, idmap_t)
uids;
TAILQ_HEAD(gdmaplist, idmap_t)
gids;
TAILQ_HEAD(envlist, charptr_t)
envs;
TAILQ_HEAD(pidslist, pids_t)
pids;
TAILQ_HEAD(mountptslist, mounts_t)
mountpts;
TAILQ_HEAD(fdslistt, ints_t)
open_fds;
TAILQ_HEAD(capslistt, ints_t)
caps;
TAILQ_HEAD(udmaplist, idmap_t)
uids;
TAILQ_HEAD(gdmaplist, idmap_t)
gids;
TAILQ_HEAD(envlist, charptr_t)
envs;
TAILQ_HEAD(pidslist, pids_t)
pids;
TAILQ_HEAD(mountptslist, mounts_t)
mountpts;
TAILQ_HEAD(fdslistt, ints_t)
open_fds;
TAILQ_HEAD(capslistt, ints_t)
caps;
};
#endif /* NS_COMMON_H */
#endif /* NS_COMMON_H */

464
config.cc
View File

@ -50,276 +50,276 @@ extern "C" {
static __rlim64_t configRLimit(int res, const nsjail::RLimit& rl, const uint64_t val, unsigned long mul = 1UL)
{
if (rl == nsjail::RLimit::VALUE) {
return (val * mul);
}
if (rl == nsjail::RLimit::SOFT) {
return cmdlineParseRLimit(res, "soft", mul);
}
if (rl == nsjail::RLimit::HARD) {
return cmdlineParseRLimit(res, "hard", mul);
}
if (rl == nsjail::RLimit::INF) {
return RLIM64_INFINITY;
}
LOG_F("Unknown rlimit value type for rlimit:%d", res);
abort();
if (rl == nsjail::RLimit::VALUE) {
return (val * mul);
}
if (rl == nsjail::RLimit::SOFT) {
return cmdlineParseRLimit(res, "soft", mul);
}
if (rl == nsjail::RLimit::HARD) {
return cmdlineParseRLimit(res, "hard", mul);
}
if (rl == nsjail::RLimit::INF) {
return RLIM64_INFINITY;
}
LOG_F("Unknown rlimit value type for rlimit:%d", res);
abort();
}
static bool configParseInternal(struct nsjconf_t* nsjconf,
const nsjail::NsJailConfig& njc)
{
switch (njc.mode()) {
case nsjail::Mode::LISTEN:
nsjconf->mode = MODE_LISTEN_TCP;
break;
case nsjail::Mode::ONCE:
nsjconf->mode = MODE_STANDALONE_ONCE;
break;
case nsjail::Mode::RERUN:
nsjconf->mode = MODE_STANDALONE_RERUN;
break;
case nsjail::Mode::EXECVE:
nsjconf->mode = MODE_STANDALONE_EXECVE;
break;
default:
LOG_E("Uknown running mode: %d", njc.mode());
return false;
}
nsjconf->chroot = DUP_IF_SET(njc, chroot_dir);
nsjconf->is_root_rw = njc.is_root_rw();
nsjconf->hostname = njc.hostname().c_str();
nsjconf->cwd = njc.cwd().c_str();
nsjconf->port = njc.port();
nsjconf->bindhost = njc.bindhost().c_str();
nsjconf->max_conns_per_ip = njc.max_conns_per_ip();
nsjconf->tlimit = njc.time_limit();
nsjconf->max_cpus = njc.max_cpus();
nsjconf->daemonize = njc.daemon();
switch (njc.mode()) {
case nsjail::Mode::LISTEN:
nsjconf->mode = MODE_LISTEN_TCP;
break;
case nsjail::Mode::ONCE:
nsjconf->mode = MODE_STANDALONE_ONCE;
break;
case nsjail::Mode::RERUN:
nsjconf->mode = MODE_STANDALONE_RERUN;
break;
case nsjail::Mode::EXECVE:
nsjconf->mode = MODE_STANDALONE_EXECVE;
break;
default:
LOG_E("Uknown running mode: %d", njc.mode());
return false;
}
nsjconf->chroot = DUP_IF_SET(njc, chroot_dir);
nsjconf->is_root_rw = njc.is_root_rw();
nsjconf->hostname = njc.hostname().c_str();
nsjconf->cwd = njc.cwd().c_str();
nsjconf->port = njc.port();
nsjconf->bindhost = njc.bindhost().c_str();
nsjconf->max_conns_per_ip = njc.max_conns_per_ip();
nsjconf->tlimit = njc.time_limit();
nsjconf->max_cpus = njc.max_cpus();
nsjconf->daemonize = njc.daemon();
if (njc.has_log_fd()) {
nsjconf->log_fd = njc.log_fd();
}
nsjconf->logfile = DUP_IF_SET(njc, log_file);
if (njc.has_log_level()) {
switch (njc.log_level()) {
case nsjail::LogLevel::DEBUG:
nsjconf->loglevel = DEBUG;
break;
case nsjail::LogLevel::INFO:
nsjconf->loglevel = INFO;
break;
case nsjail::LogLevel::WARNING:
nsjconf->loglevel = WARNING;
break;
case nsjail::LogLevel::ERROR:
nsjconf->loglevel = ERROR;
break;
case nsjail::LogLevel::FATAL:
nsjconf->loglevel = FATAL;
break;
default:
LOG_E("Unknown log_level: %d", njc.log_level());
return false;
}
}
if (njc.has_log_fd()) {
nsjconf->log_fd = njc.log_fd();
}
nsjconf->logfile = DUP_IF_SET(njc, log_file);
if (njc.has_log_level()) {
switch (njc.log_level()) {
case nsjail::LogLevel::DEBUG:
nsjconf->loglevel = DEBUG;
break;
case nsjail::LogLevel::INFO:
nsjconf->loglevel = INFO;
break;
case nsjail::LogLevel::WARNING:
nsjconf->loglevel = WARNING;
break;
case nsjail::LogLevel::ERROR:
nsjconf->loglevel = ERROR;
break;
case nsjail::LogLevel::FATAL:
nsjconf->loglevel = FATAL;
break;
default:
LOG_E("Unknown log_level: %d", njc.log_level());
return false;
}
}
if (njc.has_log_fd() || njc.has_log_file() || njc.has_log_level()) {
if (logInitLogFile(nsjconf) == false) {
return false;
}
}
if (njc.has_log_fd() || njc.has_log_file() || njc.has_log_level()) {
if (logInitLogFile(nsjconf) == false) {
return false;
}
}
nsjconf->keep_env = njc.keep_env();
for (ssize_t i = 0; i < njc.envar_size(); i++) {
struct charptr_t* p = reinterpret_cast<charptr_t*>(utilMalloc(sizeof(struct charptr_t)));
p->val = njc.envar(i).c_str();
TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers);
}
nsjconf->keep_env = njc.keep_env();
for (ssize_t i = 0; i < njc.envar_size(); i++) {
struct charptr_t* p = reinterpret_cast<charptr_t*>(utilMalloc(sizeof(struct charptr_t)));
p->val = njc.envar(i).c_str();
TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers);
}
nsjconf->keep_caps = njc.keep_caps();
for (ssize_t i = 0; i < njc.cap_size(); i++) {
struct ints_t* f = reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
f->val = capsNameToVal(njc.cap(i).c_str());
if (f->val == -1) {
return false;
}
TAILQ_INSERT_HEAD(&nsjconf->caps, f, pointers);
}
nsjconf->keep_caps = njc.keep_caps();
for (ssize_t i = 0; i < njc.cap_size(); i++) {
struct ints_t* f = reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
f->val = capsNameToVal(njc.cap(i).c_str());
if (f->val == -1) {
return false;
}
TAILQ_INSERT_HEAD(&nsjconf->caps, f, pointers);
}
nsjconf->is_silent = njc.silent();
nsjconf->skip_setsid = njc.skip_setsid();
nsjconf->is_silent = njc.silent();
nsjconf->skip_setsid = njc.skip_setsid();
for (ssize_t i = 0; i < njc.pass_fd_size(); i++) {
struct ints_t* f = reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
f->val = njc.pass_fd(i);
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
}
for (ssize_t i = 0; i < njc.pass_fd_size(); i++) {
struct ints_t* f = reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
f->val = njc.pass_fd(i);
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
}
nsjconf->disable_no_new_privs = njc.disable_no_new_privs();
nsjconf->disable_no_new_privs = njc.disable_no_new_privs();
nsjconf->rl_as = configRLimit(RLIMIT_AS, njc.rlimit_as_type(), njc.rlimit_as(), 1024UL * 1024UL);
nsjconf->rl_core = configRLimit(RLIMIT_CORE, njc.rlimit_core_type(), njc.rlimit_core(), 1024UL * 1024UL);
nsjconf->rl_cpu = configRLimit(RLIMIT_CPU, njc.rlimit_cpu_type(), njc.rlimit_cpu());
nsjconf->rl_fsize = configRLimit(RLIMIT_FSIZE, njc.rlimit_fsize_type(), njc.rlimit_fsize(), 1024UL * 1024UL);
nsjconf->rl_nofile = configRLimit(RLIMIT_NOFILE, njc.rlimit_nofile_type(), njc.rlimit_nofile());
nsjconf->rl_nproc = configRLimit(RLIMIT_NPROC, njc.rlimit_nproc_type(), njc.rlimit_nproc());
nsjconf->rl_stack = configRLimit(RLIMIT_STACK, njc.rlimit_stack_type(), njc.rlimit_stack(), 1024UL * 1024UL);
nsjconf->rl_as = configRLimit(RLIMIT_AS, njc.rlimit_as_type(), njc.rlimit_as(), 1024UL * 1024UL);
nsjconf->rl_core = configRLimit(RLIMIT_CORE, njc.rlimit_core_type(), njc.rlimit_core(), 1024UL * 1024UL);
nsjconf->rl_cpu = configRLimit(RLIMIT_CPU, njc.rlimit_cpu_type(), njc.rlimit_cpu());
nsjconf->rl_fsize = configRLimit(RLIMIT_FSIZE, njc.rlimit_fsize_type(), njc.rlimit_fsize(), 1024UL * 1024UL);
nsjconf->rl_nofile = configRLimit(RLIMIT_NOFILE, njc.rlimit_nofile_type(), njc.rlimit_nofile());
nsjconf->rl_nproc = configRLimit(RLIMIT_NPROC, njc.rlimit_nproc_type(), njc.rlimit_nproc());
nsjconf->rl_stack = configRLimit(RLIMIT_STACK, njc.rlimit_stack_type(), njc.rlimit_stack(), 1024UL * 1024UL);
if (njc.persona_addr_compat_layout()) {
nsjconf->personality |= ADDR_COMPAT_LAYOUT;
}
if (njc.persona_mmap_page_zero()) {
nsjconf->personality |= MMAP_PAGE_ZERO;
}
if (njc.persona_read_implies_exec()) {
nsjconf->personality |= READ_IMPLIES_EXEC;
}
if (njc.persona_addr_limit_3gb()) {
nsjconf->personality |= ADDR_LIMIT_3GB;
}
if (njc.persona_addr_no_randomize()) {
nsjconf->personality |= ADDR_NO_RANDOMIZE;
}
if (njc.persona_addr_compat_layout()) {
nsjconf->personality |= ADDR_COMPAT_LAYOUT;
}
if (njc.persona_mmap_page_zero()) {
nsjconf->personality |= MMAP_PAGE_ZERO;
}
if (njc.persona_read_implies_exec()) {
nsjconf->personality |= READ_IMPLIES_EXEC;
}
if (njc.persona_addr_limit_3gb()) {
nsjconf->personality |= ADDR_LIMIT_3GB;
}
if (njc.persona_addr_no_randomize()) {
nsjconf->personality |= ADDR_NO_RANDOMIZE;
}
nsjconf->clone_newnet = njc.clone_newnet();
nsjconf->clone_newuser = njc.clone_newuser();
nsjconf->clone_newns = njc.clone_newns();
nsjconf->clone_newpid = njc.clone_newpid();
nsjconf->clone_newipc = njc.clone_newipc();
nsjconf->clone_newuts = njc.clone_newuts();
nsjconf->clone_newcgroup = njc.clone_newcgroup();
nsjconf->clone_newnet = njc.clone_newnet();
nsjconf->clone_newuser = njc.clone_newuser();
nsjconf->clone_newns = njc.clone_newns();
nsjconf->clone_newpid = njc.clone_newpid();
nsjconf->clone_newipc = njc.clone_newipc();
nsjconf->clone_newuts = njc.clone_newuts();
nsjconf->clone_newcgroup = njc.clone_newcgroup();
for (ssize_t i = 0; i < njc.uidmap_size(); i++) {
if (userParseId(nsjconf, DUP_IF_SET(njc.uidmap(i), inside_id), DUP_IF_SET(njc.uidmap(i), outside_id),
njc.uidmap(i).count(), false /* is_gid */,
njc.uidmap(i).use_newidmap())
== false) {
return false;
}
}
for (ssize_t i = 0; i < njc.gidmap_size(); i++) {
if (userParseId(nsjconf, DUP_IF_SET(njc.gidmap(i), inside_id), DUP_IF_SET(njc.gidmap(i), outside_id),
njc.gidmap(i).count(), true /* is_gid */,
njc.gidmap(i).use_newidmap())
== false) {
return false;
}
}
for (ssize_t i = 0; i < njc.uidmap_size(); i++) {
if (userParseId(nsjconf, DUP_IF_SET(njc.uidmap(i), inside_id), DUP_IF_SET(njc.uidmap(i), outside_id),
njc.uidmap(i).count(), false /* is_gid */,
njc.uidmap(i).use_newidmap())
== false) {
return false;
}
}
for (ssize_t i = 0; i < njc.gidmap_size(); i++) {
if (userParseId(nsjconf, DUP_IF_SET(njc.gidmap(i), inside_id), DUP_IF_SET(njc.gidmap(i), outside_id),
njc.gidmap(i).count(), true /* is_gid */,
njc.gidmap(i).use_newidmap())
== false) {
return false;
}
}
nsjconf->mount_proc = njc.mount_proc();
for (ssize_t i = 0; i < njc.mount_size(); i++) {
const char* src = (njc.mount(i).has_src()) ? njc.mount(i).src().c_str() : NULL;
const char* src_env = (njc.mount(i).has_prefix_src_env()) ? njc.mount(i).prefix_src_env().c_str() : NULL;
const char* dst = (njc.mount(i).has_dst()) ? njc.mount(i).dst().c_str() : NULL;
const char* dst_env = (njc.mount(i).has_prefix_dst_env()) ? njc.mount(i).prefix_dst_env().c_str() : NULL;
const char* fstype = (njc.mount(i).has_fstype()) ? njc.mount(i).fstype().c_str() : NULL;
const char* options = (njc.mount(i).has_options()) ? njc.mount(i).options().c_str() : NULL;
nsjconf->mount_proc = njc.mount_proc();
for (ssize_t i = 0; i < njc.mount_size(); i++) {
const char* src = (njc.mount(i).has_src()) ? njc.mount(i).src().c_str() : NULL;
const char* src_env = (njc.mount(i).has_prefix_src_env()) ? njc.mount(i).prefix_src_env().c_str() : NULL;
const char* dst = (njc.mount(i).has_dst()) ? njc.mount(i).dst().c_str() : NULL;
const char* dst_env = (njc.mount(i).has_prefix_dst_env()) ? njc.mount(i).prefix_dst_env().c_str() : NULL;
const char* fstype = (njc.mount(i).has_fstype()) ? njc.mount(i).fstype().c_str() : NULL;
const char* options = (njc.mount(i).has_options()) ? njc.mount(i).options().c_str() : NULL;
uintptr_t flags = (njc.mount(i).rw() == false) ? MS_RDONLY : 0;
flags |= njc.mount(i).is_bind() ? (MS_BIND | MS_REC) : 0;
bool mandatory = njc.mount(i).mandatory();
uintptr_t flags = (njc.mount(i).rw() == false) ? MS_RDONLY : 0;
flags |= njc.mount(i).is_bind() ? (MS_BIND | MS_REC) : 0;
bool mandatory = njc.mount(i).mandatory();
isDir_t isDir = NS_DIR_MAYBE;
if (njc.mount(i).has_is_dir()) {
isDir = njc.mount(i).is_dir() ? NS_DIR_YES : NS_DIR_NO;
}
isDir_t isDir = NS_DIR_MAYBE;
if (njc.mount(i).has_is_dir()) {
isDir = njc.mount(i).is_dir() ? NS_DIR_YES : NS_DIR_NO;
}
const char* src_content = NULL;
size_t src_content_len = 0;
if (njc.mount(i).has_src_content()) {
src_content = njc.mount(i).src_content().data();
src_content_len = njc.mount(i).src_content().size();
}
const char* src_content = NULL;
size_t src_content_len = 0;
if (njc.mount(i).has_src_content()) {
src_content = njc.mount(i).src_content().data();
src_content_len = njc.mount(i).src_content().size();
}
if (mountAddMountPtTail(nsjconf, src, dst, fstype, options, flags, isDir,
mandatory, src_env, dst_env, src_content,
src_content_len, njc.mount(i).is_symlink())
== false) {
LOG_E("Couldn't add mountpoint for src:'%s' dst:'%s'", src, dst);
return false;
}
}
if (mountAddMountPtTail(nsjconf, src, dst, fstype, options, flags, isDir,
mandatory, src_env, dst_env, src_content,
src_content_len, njc.mount(i).is_symlink())
== false) {
LOG_E("Couldn't add mountpoint for src:'%s' dst:'%s'", src, dst);
return false;
}
}
if (njc.has_seccomp_policy_file()) {
if ((nsjconf->kafel_file = fopen(njc.seccomp_policy_file().c_str(), "rb")) == NULL) {
PLOG_W("Couldn't open file with seccomp policy '%s'",
njc.seccomp_policy_file().c_str());
return false;
}
}
if (njc.has_seccomp_policy_file()) {
if ((nsjconf->kafel_file = fopen(njc.seccomp_policy_file().c_str(), "rb")) == NULL) {
PLOG_W("Couldn't open file with seccomp policy '%s'",
njc.seccomp_policy_file().c_str());
return false;
}
}
std::string kafel_string;
for (ssize_t i = 0; i < njc.seccomp_string().size(); i++) {
kafel_string += njc.seccomp_string(i);
}
nsjconf->kafel_string = njc.seccomp_string().size() > 0
? utilStrDup(kafel_string.c_str())
: NULL;
std::string kafel_string;
for (ssize_t i = 0; i < njc.seccomp_string().size(); i++) {
kafel_string += njc.seccomp_string(i);
}
nsjconf->kafel_string = njc.seccomp_string().size() > 0
? utilStrDup(kafel_string.c_str())
: NULL;
nsjconf->cgroup_mem_max = njc.cgroup_mem_max();
nsjconf->cgroup_mem_mount = njc.cgroup_mem_mount().c_str();
nsjconf->cgroup_mem_parent = njc.cgroup_mem_parent().c_str();
nsjconf->cgroup_pids_max = njc.cgroup_pids_max();
nsjconf->cgroup_pids_mount = njc.cgroup_pids_mount().c_str();
nsjconf->cgroup_pids_parent = njc.cgroup_pids_parent().c_str();
nsjconf->cgroup_mem_max = njc.cgroup_mem_max();
nsjconf->cgroup_mem_mount = njc.cgroup_mem_mount().c_str();
nsjconf->cgroup_mem_parent = njc.cgroup_mem_parent().c_str();
nsjconf->cgroup_pids_max = njc.cgroup_pids_max();
nsjconf->cgroup_pids_mount = njc.cgroup_pids_mount().c_str();
nsjconf->cgroup_pids_parent = njc.cgroup_pids_parent().c_str();
nsjconf->iface_no_lo = njc.iface_no_lo();
nsjconf->iface_vs = DUP_IF_SET(njc, macvlan_iface);
nsjconf->iface_vs_ip = njc.macvlan_vs_ip().c_str();
nsjconf->iface_vs_nm = njc.macvlan_vs_nm().c_str();
nsjconf->iface_vs_gw = njc.macvlan_vs_gw().c_str();
nsjconf->iface_no_lo = njc.iface_no_lo();
nsjconf->iface_vs = DUP_IF_SET(njc, macvlan_iface);
nsjconf->iface_vs_ip = njc.macvlan_vs_ip().c_str();
nsjconf->iface_vs_nm = njc.macvlan_vs_nm().c_str();
nsjconf->iface_vs_gw = njc.macvlan_vs_gw().c_str();
if (njc.has_exec_bin()) {
static std::vector<const char*> argv;
if (njc.exec_bin().has_arg0()) {
argv.push_back(njc.exec_bin().arg0().c_str());
} else {
argv.push_back(njc.exec_bin().path().c_str());
}
for (ssize_t i = 0; i < njc.exec_bin().arg().size(); i++) {
argv.push_back(njc.exec_bin().arg(i).c_str());
}
argv.push_back(nullptr);
nsjconf->exec_file = DUP_IF_SET(njc.exec_bin(), path);
nsjconf->argv = argv.data();
}
if (njc.has_exec_bin()) {
static std::vector<const char*> argv;
if (njc.exec_bin().has_arg0()) {
argv.push_back(njc.exec_bin().arg0().c_str());
} else {
argv.push_back(njc.exec_bin().path().c_str());
}
for (ssize_t i = 0; i < njc.exec_bin().arg().size(); i++) {
argv.push_back(njc.exec_bin().arg(i).c_str());
}
argv.push_back(nullptr);
nsjconf->exec_file = DUP_IF_SET(njc.exec_bin(), path);
nsjconf->argv = argv.data();
}
return true;
return true;
}
static void LogHandler(google::protobuf::LogLevel level, const char* filename, int line, const std::string& message)
{
LOG_W("config.cc: '%s'", message.c_str());
LOG_W("config.cc: '%s'", message.c_str());
}
extern "C" bool configParse(struct nsjconf_t* nsjconf, const char* file)
{
LOG_I("Parsing configuration from '%s'", file);
LOG_I("Parsing configuration from '%s'", file);
int fd = open(file, O_RDONLY);
if (fd == -1) {
PLOG_W("Couldn't open config file '%s'", file);
return false;
}
int fd = open(file, O_RDONLY);
if (fd == -1) {
PLOG_W("Couldn't open config file '%s'", file);
return false;
}
SetLogHandler(LogHandler);
google::protobuf::io::FileInputStream input(fd);
input.SetCloseOnDelete(true);
SetLogHandler(LogHandler);
google::protobuf::io::FileInputStream input(fd);
input.SetCloseOnDelete(true);
/* Use static so we can get c_str() pointers, and copy them into the nsjconf struct */
static nsjail::NsJailConfig nsc;
/* Use static so we can get c_str() pointers, and copy them into the nsjconf struct */
static nsjail::NsJailConfig nsc;
auto parser = google::protobuf::TextFormat::Parser();
if (!parser.Parse(&input, &nsc)) {
LOG_W("Couldn't parse file '%s' from Text into ProtoBuf", file);
return false;
}
if (!configParseInternal(nsjconf, nsc)) {
LOG_W("Couldn't parse the ProtoBuf");
return false;
}
LOG_D("Parsed config:\n'%s'", nsc.DebugString().c_str());
auto parser = google::protobuf::TextFormat::Parser();
if (!parser.Parse(&input, &nsc)) {
LOG_W("Couldn't parse file '%s' from Text into ProtoBuf", file);
return false;
}
if (!configParseInternal(nsjconf, nsc)) {
LOG_W("Couldn't parse the ProtoBuf");
return false;
}
LOG_D("Parsed config:\n'%s'", nsc.DebugString().c_str());
return true;
return true;
}

View File

@ -27,9 +27,9 @@ extern "C" {
#endif
#include "common.h"
bool configParse(struct nsjconf_t *nsjconf, const char *file);
bool configParse(struct nsjconf_t* nsjconf, const char* file);
#ifdef __cplusplus
} // extern "C"
} // extern "C"
#endif
#endif /* NS_CONFIG_H */
#endif /* NS_CONFIG_H */

View File

@ -47,22 +47,22 @@
#include "util.h"
#include "uts.h"
static bool containUserNs(struct nsjconf_t *nsjconf)
static bool containUserNs(struct nsjconf_t* nsjconf)
{
return userInitNsFromChild(nsjconf);
}
static bool containInitPidNs(struct nsjconf_t *nsjconf)
static bool containInitPidNs(struct nsjconf_t* nsjconf)
{
return pidInitNs(nsjconf);
}
static bool containInitNetNs(struct nsjconf_t *nsjconf)
static bool containInitNetNs(struct nsjconf_t* nsjconf)
{
return netInitNsFromChild(nsjconf);
}
static bool containInitUtsNs(struct nsjconf_t *nsjconf)
static bool containInitUtsNs(struct nsjconf_t* nsjconf)
{
return utsInitNs(nsjconf);
}
@ -72,7 +72,7 @@ static bool containInitCgroupNs(void)
return cgroupInitNs();
}
static bool containDropPrivs(struct nsjconf_t *nsjconf)
static bool containDropPrivs(struct nsjconf_t* nsjconf)
{
#ifndef PR_SET_NO_NEW_PRIVS
#define PR_SET_NO_NEW_PRIVS 38
@ -91,7 +91,7 @@ static bool containDropPrivs(struct nsjconf_t *nsjconf)
return true;
}
static bool containPrepareEnv(struct nsjconf_t *nsjconf)
static bool containPrepareEnv(struct nsjconf_t* nsjconf)
{
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0) == -1) {
PLOG_E("prctl(PR_SET_PDEATHSIG, SIGKILL)");
@ -111,17 +111,17 @@ static bool containPrepareEnv(struct nsjconf_t *nsjconf)
return true;
}
static bool containInitMountNs(struct nsjconf_t *nsjconf)
static bool containInitMountNs(struct nsjconf_t* nsjconf)
{
return mountInitNs(nsjconf);
}
static bool containCPU(struct nsjconf_t *nsjconf)
static bool containCPU(struct nsjconf_t* nsjconf)
{
return cpuInit(nsjconf);
}
static bool containSetLimits(struct nsjconf_t *nsjconf)
static bool containSetLimits(struct nsjconf_t* nsjconf)
{
struct rlimit64 rl;
rl.rlim_cur = rl.rlim_max = nsjconf->rl_as;
@ -162,10 +162,11 @@ static bool containSetLimits(struct nsjconf_t *nsjconf)
return true;
}
static bool containPassFd(struct nsjconf_t *nsjconf, int fd)
static bool containPassFd(struct nsjconf_t* nsjconf, int fd)
{
struct ints_t *p;
TAILQ_FOREACH(p, &nsjconf->open_fds, pointers) {
struct ints_t* p;
TAILQ_FOREACH(p, &nsjconf->open_fds, pointers)
{
if (p->val == fd) {
return true;
}
@ -173,7 +174,7 @@ static bool containPassFd(struct nsjconf_t *nsjconf, int fd)
return false;
}
static bool containMakeFdsCOENaive(struct nsjconf_t *nsjconf)
static bool containMakeFdsCOENaive(struct nsjconf_t* nsjconf)
{
/*
* Don't use getrlimit(RLIMIT_NOFILE) here, as it can return an artifically small value
@ -201,14 +202,14 @@ static bool containMakeFdsCOENaive(struct nsjconf_t *nsjconf)
return true;
}
static bool containMakeFdsCOEProc(struct nsjconf_t *nsjconf)
static bool containMakeFdsCOEProc(struct nsjconf_t* nsjconf)
{
int dirfd = open("/proc/self/fd", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
if (dirfd == -1) {
PLOG_D("open('/proc/self/fd', O_DIRECTORY|O_RDONLY)");
return false;
}
DIR *dir = fdopendir(dirfd);
DIR* dir = fdopendir(dirfd);
if (dir == NULL) {
PLOG_W("fdopendir(fd=%d)", dirfd);
close(dirfd);
@ -217,7 +218,7 @@ static bool containMakeFdsCOEProc(struct nsjconf_t *nsjconf)
/* Make all fds above stderr close-on-exec */
for (;;) {
errno = 0;
struct dirent *entry = readdir(dir);
struct dirent* entry = readdir(dir);
if (entry == NULL && errno != 0) {
PLOG_D("readdir('/proc/self/fd')");
closedir(dir);
@ -263,7 +264,7 @@ static bool containMakeFdsCOEProc(struct nsjconf_t *nsjconf)
return true;
}
static bool containMakeFdsCOE(struct nsjconf_t *nsjconf)
static bool containMakeFdsCOE(struct nsjconf_t* nsjconf)
{
if (containMakeFdsCOEProc(nsjconf) == true) {
return true;
@ -275,7 +276,7 @@ static bool containMakeFdsCOE(struct nsjconf_t *nsjconf)
return false;
}
bool containSetupFD(struct nsjconf_t * nsjconf, int fd_in, int fd_out, int fd_err)
bool containSetupFD(struct nsjconf_t* nsjconf, int fd_in, int fd_out, int fd_err)
{
if (nsjconf->mode != MODE_LISTEN_TCP) {
if (nsjconf->is_silent == false) {
@ -302,7 +303,7 @@ bool containSetupFD(struct nsjconf_t * nsjconf, int fd_in, int fd_out, int fd_er
return true;
}
bool containContain(struct nsjconf_t * nsjconf)
bool containContain(struct nsjconf_t* nsjconf)
{
if (containUserNs(nsjconf) == false) {
return false;

View File

@ -26,7 +26,7 @@
#include "common.h"
bool containSetupFD(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int fd_err);
bool containContain(struct nsjconf_t *nsjconf);
bool containSetupFD(struct nsjconf_t* nsjconf, int fd_in, int fd_out, int fd_err);
bool containContain(struct nsjconf_t* nsjconf);
#endif /* NS_CONTAIN_H */
#endif /* NS_CONTAIN_H */

19
cpu.c
View File

@ -28,12 +28,11 @@
#include "log.h"
#include "util.h"
static void cpuSetRandomCpu(cpu_set_t * mask, size_t mask_size, size_t cpu_num)
static void cpuSetRandomCpu(cpu_set_t* mask, size_t mask_size, size_t cpu_num)
{
if ((size_t) CPU_COUNT_S(mask_size, mask) >= cpu_num) {
LOG_F
("Number of CPUs in the mask '%d' is bigger than number of available CPUs '%zu'",
CPU_COUNT(mask), cpu_num);
if ((size_t)CPU_COUNT_S(mask_size, mask) >= cpu_num) {
LOG_F("Number of CPUs in the mask '%d' is bigger than number of available CPUs '%zu'",
CPU_COUNT(mask), cpu_num);
}
for (;;) {
@ -46,18 +45,18 @@ static void cpuSetRandomCpu(cpu_set_t * mask, size_t mask_size, size_t cpu_num)
}
}
bool cpuInit(struct nsjconf_t *nsjconf)
bool cpuInit(struct nsjconf_t* nsjconf)
{
if (nsjconf->num_cpus < 0) {
PLOG_W("sysconf(_SC_NPROCESSORS_ONLN) returned %ld", nsjconf->num_cpus);
return false;
}
if (nsjconf->max_cpus > (size_t) nsjconf->num_cpus) {
if (nsjconf->max_cpus > (size_t)nsjconf->num_cpus) {
LOG_W("Requested number of CPUs:%zu is bigger than CPUs online:%ld",
nsjconf->max_cpus, nsjconf->num_cpus);
nsjconf->max_cpus, nsjconf->num_cpus);
return true;
}
if (nsjconf->max_cpus == (size_t) nsjconf->num_cpus) {
if (nsjconf->max_cpus == (size_t)nsjconf->num_cpus) {
LOG_D("All CPUs requested (%zu of %ld)", nsjconf->max_cpus, nsjconf->num_cpus);
return true;
}
@ -66,7 +65,7 @@ bool cpuInit(struct nsjconf_t *nsjconf)
return true;
}
cpu_set_t *mask = CPU_ALLOC(nsjconf->num_cpus);
cpu_set_t* mask = CPU_ALLOC(nsjconf->num_cpus);
if (mask == NULL) {
PLOG_W("Failure allocating cpu_set_t for %ld CPUs", nsjconf->num_cpus);
return false;

4
cpu.h
View File

@ -27,6 +27,6 @@
#include "common.h"
bool cpuInit(struct nsjconf_t *nsjconf);
bool cpuInit(struct nsjconf_t* nsjconf);
#endif /* NS_CPU_H */
#endif /* NS_CPU_H */

25
log.c
View File

@ -44,7 +44,7 @@ static enum llevel_t log_level = INFO;
* Log to stderr by default. Use a dup()d fd, because in the future we'll associate the
* connection socket with fd (0, 1, 2).
*/
bool logInitLogFile(struct nsjconf_t *nsjconf)
bool logInitLogFile(struct nsjconf_t* nsjconf)
{
/* Close previous log_fd */
if (log_fd > STDERR_FILENO) {
@ -60,8 +60,7 @@ bool logInitLogFile(struct nsjconf_t *nsjconf)
if (nsjconf->logfile == NULL) {
log_fd = fcntl(log_fd, F_DUPFD_CLOEXEC, 0);
} else {
if (TEMP_FAILURE_RETRY
(log_fd = open(nsjconf->logfile, O_CREAT | O_RDWR | O_APPEND, 0640)) == -1) {
if (TEMP_FAILURE_RETRY(log_fd = open(nsjconf->logfile, O_CREAT | O_RDWR | O_APPEND, 0640)) == -1) {
log_fd = STDERR_FILENO;
PLOG_E("Couldn't open logfile open('%s')", nsjconf->logfile);
return false;
@ -71,7 +70,7 @@ bool logInitLogFile(struct nsjconf_t *nsjconf)
return true;
}
void logLog(enum llevel_t ll, const char *fn, int ln, bool perr, const char *fmt, ...)
void logLog(enum llevel_t ll, const char* fn, int ln, bool perr, const char* fmt, ...)
{
if (ll < log_level) {
return;
@ -82,19 +81,19 @@ void logLog(enum llevel_t ll, const char *fn, int ln, bool perr, const char *fmt
snprintf(strerr, sizeof(strerr), "%s", strerror(errno));
}
struct ll_t {
const char *const descr;
const char *const prefix;
const char* const descr;
const char* const prefix;
const bool print_funcline;
const bool print_time;
};
static struct ll_t const logLevels[] = {
{"D", "\033[0;4m", true, true},
{"I", "\033[1m", false, true},
{"W", "\033[0;33m", true, true},
{"E", "\033[1;31m", true, true},
{"F", "\033[7;35m", true, true},
{"HR", "\033[0m", false, false},
{"HB", "\033[1m", false, false},
{ "D", "\033[0;4m", true, true },
{ "I", "\033[1m", false, true },
{ "W", "\033[0;33m", true, true },
{ "E", "\033[1;31m", true, true },
{ "F", "\033[7;35m", true, true },
{ "HR", "\033[0m", false, false },
{ "HB", "\033[1m", false, false },
};
time_t ltstamp = time(NULL);

8
log.h
View File

@ -42,9 +42,9 @@
#define PLOG_E(...) logLog(ERROR, __func__, __LINE__, true, __VA_ARGS__);
#define PLOG_F(...) logLog(FATAL, __func__, __LINE__, true, __VA_ARGS__);
bool logInitLogFile(struct nsjconf_t *nsjconf);
void logLog(enum llevel_t ll, const char *fn, int ln, bool perr, const char *fmt, ...)
__attribute__ ((format(printf, 5, 6)));
bool logInitLogFile(struct nsjconf_t* nsjconf);
void logLog(enum llevel_t ll, const char* fn, int ln, bool perr, const char* fmt, ...)
__attribute__((format(printf, 5, 6)));
void logStop(int sig);
#endif /* NS_LOG_H */
#endif /* NS_LOG_H */

138
mount.c
View File

@ -41,20 +41,20 @@
#include "util.h"
#define VALSTR_STRUCT(x) \
{ \
x, #x \
}
{ \
x, #x \
}
#if !defined(MS_LAZYTIME)
#define MS_LAZYTIME (1 << 25)
#endif /* if !defined(MS_LAZYTIME) */
#endif /* if !defined(MS_LAZYTIME) */
const char *mountFlagsToStr(uintptr_t flags)
const char* mountFlagsToStr(uintptr_t flags)
{
static __thread char mountFlagsStr[1024];
mountFlagsStr[0] = '\0';
// clang-format off
// clang-format off
static struct {
const uintptr_t flag;
const char* const name;
@ -84,12 +84,12 @@ const char *mountFlagsToStr(uintptr_t flags)
VALSTR_STRUCT(MS_STRICTATIME),
VALSTR_STRUCT(MS_LAZYTIME),
};
// clang-format on
// clang-format on
for (size_t i = 0; i < ARRAYSIZE(mountFlags); i++) {
if (flags & mountFlags[i].flag) {
utilSSnPrintf(mountFlagsStr, sizeof(mountFlagsStr), "%s|",
mountFlags[i].name);
mountFlags[i].name);
}
}
@ -101,7 +101,7 @@ const char *mountFlagsToStr(uintptr_t flags)
return mountFlagsStr;
}
static bool mountIsDir(const char *path)
static bool mountIsDir(const char* path)
{
/*
* If the source dir is NULL, we assume it's a dir (for /proc and tmpfs)
@ -120,7 +120,7 @@ static bool mountIsDir(const char *path)
return false;
}
static bool mountMount(struct mounts_t *mpt, const char *newroot, const char *tmpdir)
static bool mountMount(struct mounts_t* mpt, const char* newroot, const char* tmpdir)
{
char dst[PATH_MAX];
snprintf(dst, sizeof(dst), "%s/%s", newroot, mpt->dst);
@ -168,7 +168,7 @@ static bool mountMount(struct mounts_t *mpt, const char *newroot, const char *tm
return false;
} else {
PLOG_W("symlink('%s', '%s'), but it's not mandatory, continuing",
srcpath, dst);
srcpath, dst);
}
}
return true;
@ -177,10 +177,8 @@ static bool mountMount(struct mounts_t *mpt, const char *newroot, const char *tm
if (mpt->src_content) {
static uint64_t df_counter = 0;
snprintf(srcpath, sizeof(srcpath), "%s/dynamic_file.%" PRIu64, tmpdir,
++df_counter);
int fd =
TEMP_FAILURE_RETRY(open
(srcpath, O_CREAT | O_EXCL | O_CLOEXEC | O_WRONLY, 0644));
++df_counter);
int fd = TEMP_FAILURE_RETRY(open(srcpath, O_CREAT | O_EXCL | O_CLOEXEC | O_WRONLY, 0644));
if (fd < 0) {
PLOG_W("open(srcpath, O_CREAT|O_EXCL|O_CLOEXEC|O_WRONLY, 0644) failed");
return false;
@ -202,10 +200,11 @@ static bool mountMount(struct mounts_t *mpt, const char *newroot, const char *tm
if (errno == EACCES) {
PLOG_W("mount('%s') src:'%s' dst:'%s' failed. "
"Try fixing this problem by applying 'chmod o+x' to the '%s' directory and "
"its ancestors", mountDescribeMountPt(mpt), srcpath, dst, srcpath);
"its ancestors",
mountDescribeMountPt(mpt), srcpath, dst, srcpath);
} else {
PLOG_W("mount('%s') src:'%s' dst:'%s' failed", mountDescribeMountPt(mpt),
srcpath, dst);
srcpath, dst);
}
} else {
mpt->mounted = true;
@ -217,7 +216,7 @@ static bool mountMount(struct mounts_t *mpt, const char *newroot, const char *tm
return true;
}
static bool mountRemountRO(struct mounts_t *mpt)
static bool mountRemountRO(struct mounts_t* mpt)
{
if (!mpt->mounted) {
return true;
@ -243,7 +242,7 @@ static bool mountRemountRO(struct mounts_t *mpt)
unsigned long new_flags = MS_REMOUNT | MS_BIND | MS_RDONLY | vfs.f_flag;
LOG_D("Re-mounting R/O '%s' (old_flags:%s, new_flags:%s)", mpt->dst,
mountFlagsToStr(vfs.f_flag), mountFlagsToStr(new_flags));
mountFlagsToStr(vfs.f_flag), mountFlagsToStr(new_flags));
if (mount(mpt->dst, mpt->dst, NULL, new_flags, 0) == -1) {
PLOG_W("mount('%s', flags:%s)", mpt->dst, mountFlagsToStr(new_flags));
@ -253,7 +252,7 @@ static bool mountRemountRO(struct mounts_t *mpt)
return true;
}
static bool mountMkdirAndTest(const char *dir)
static bool mountMkdirAndTest(const char* dir)
{
if (mkdir(dir, 0755) == -1 && errno != EEXIST) {
PLOG_W("Couldn't create '%s' directory", dir);
@ -267,7 +266,7 @@ static bool mountMkdirAndTest(const char *dir)
return true;
}
static bool mountGetDir(char *dir, const char *name)
static bool mountGetDir(char* dir, const char* name)
{
snprintf(dir, PATH_MAX, "/dev/shm/nsjail.%s", name);
if (mountMkdirAndTest(dir)) {
@ -277,7 +276,7 @@ static bool mountGetDir(char *dir, const char *name)
if (mountMkdirAndTest(dir)) {
return true;
}
const char *tmp = getenv("TMPDIR");
const char* tmp = getenv("TMPDIR");
if (tmp) {
snprintf(dir, PATH_MAX, "%s/nsjail.%s", name, tmp);
if (mountMkdirAndTest(dir)) {
@ -293,7 +292,7 @@ static bool mountGetDir(char *dir, const char *name)
return false;
}
static bool mountInitNsInternal(struct nsjconf_t *nsjconf)
static bool mountInitNsInternal(struct nsjconf_t* nsjconf)
{
/*
* If CLONE_NEWNS is not used, we would be changing the global mount namespace, so simply
@ -301,8 +300,7 @@ static bool mountInitNsInternal(struct nsjconf_t *nsjconf)
*/
if (nsjconf->clone_newns == false) {
if (nsjconf->chroot == NULL) {
PLOG_E
("--chroot was not specified, and it's required when not using CLONE_NEWNS");
PLOG_E("--chroot was not specified, and it's required when not using CLONE_NEWNS");
return false;
}
if (chroot(nsjconf->chroot) == -1) {
@ -347,8 +345,9 @@ static bool mountInitNsInternal(struct nsjconf_t *nsjconf)
return false;
}
struct mounts_t *p;
TAILQ_FOREACH(p, &nsjconf->mountpts, pointers) {
struct mounts_t* p;
TAILQ_FOREACH(p, &nsjconf->mountpts, pointers)
{
if (mountMount(p, destdir, tmpdir) == false && p->mandatory) {
return false;
}
@ -379,7 +378,8 @@ static bool mountInitNsInternal(struct nsjconf_t *nsjconf)
return false;
}
TAILQ_FOREACH(p, &nsjconf->mountpts, pointers) {
TAILQ_FOREACH(p, &nsjconf->mountpts, pointers)
{
if (mountRemountRO(p) == false && p->mandatory) {
return false;
}
@ -392,7 +392,7 @@ static bool mountInitNsInternal(struct nsjconf_t *nsjconf)
* With mode MODE_STANDALONE_EXECVE it's required to mount /proc inside a new process,
* as the current process is still in the original PID namespace (man pid_namespaces)
*/
bool mountInitNs(struct nsjconf_t * nsjconf)
bool mountInitNs(struct nsjconf_t* nsjconf)
{
if (nsjconf->mode != MODE_STANDALONE_EXECVE) {
return mountInitNsInternal(nsjconf);
@ -408,27 +408,28 @@ bool mountInitNs(struct nsjconf_t * nsjconf)
}
int status;
while (wait4(pid, &status, 0, NULL) != pid) ;
while (wait4(pid, &status, 0, NULL) != pid)
;
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
return true;
}
return false;
}
static bool mountAddMountPt(struct nsjconf_t *nsjconf, bool head, const char *src, const char *dst,
const char *fstype, const char *options, uintptr_t flags, isDir_t isDir,
bool mandatory, const char *src_env, const char *dst_env,
const char *src_content, size_t src_content_len, bool is_symlink)
static bool mountAddMountPt(struct nsjconf_t* nsjconf, bool head, const char* src, const char* dst,
const char* fstype, const char* options, uintptr_t flags, isDir_t isDir,
bool mandatory, const char* src_env, const char* dst_env,
const char* src_content, size_t src_content_len, bool is_symlink)
{
struct mounts_t *p = utilCalloc(sizeof(struct mounts_t));
struct mounts_t* p = utilCalloc(sizeof(struct mounts_t));
if (src_env) {
const char *e = getenv(src_env);
const char* e = getenv(src_env);
if (e == NULL) {
LOG_W("No such envvar:'%s'", src_env);
return false;
}
if (asprintf((char **)&p->src, "%s%s", e, src ? src : "") == -1) {
if (asprintf((char**)&p->src, "%s%s", e, src ? src : "") == -1) {
PLOG_W("asprintf() failed");
return false;
}
@ -437,12 +438,12 @@ static bool mountAddMountPt(struct nsjconf_t *nsjconf, bool head, const char *sr
}
if (dst_env) {
const char *e = getenv(dst_env);
const char* e = getenv(dst_env);
if (e == NULL) {
LOG_W("No such envvar:'%s'", dst_env);
return false;
}
if (asprintf((char **)&p->dst, "%s%s", e, dst ? dst : "") == -1) {
if (asprintf((char**)&p->dst, "%s%s", e, dst ? dst : "") == -1) {
PLOG_W("asprintf() failed");
return false;
}
@ -465,24 +466,23 @@ static bool mountAddMountPt(struct nsjconf_t *nsjconf, bool head, const char *sr
case NS_DIR_NO:
p->isDir = false;
break;
case NS_DIR_MAYBE:{
if (src_content) {
p->isDir = false;
} else if (p->src == NULL) {
p->isDir = true;
} else if (p->flags & MS_BIND) {
p->isDir = mountIsDir(p->src);
} else {
p->isDir = true;
}
case NS_DIR_MAYBE: {
if (src_content) {
p->isDir = false;
} else if (p->src == NULL) {
p->isDir = true;
} else if (p->flags & MS_BIND) {
p->isDir = mountIsDir(p->src);
} else {
p->isDir = true;
}
break;
} break;
default:
LOG_F("Unknown isDir value: %d", isDir);
break;
}
p->src_content = utilMemDup((const uint8_t *)src_content, src_content_len);
p->src_content = utilMemDup((const uint8_t*)src_content, src_content_len);
p->src_content_len = src_content_len;
if (head) {
@ -494,42 +494,42 @@ static bool mountAddMountPt(struct nsjconf_t *nsjconf, bool head, const char *sr
return true;
}
bool mountAddMountPtHead(struct nsjconf_t * nsjconf, const char *src, const char *dst,
const char *fstype, const char *options, uintptr_t flags, isDir_t isDir,
bool mandatory, const char *src_env, const char *dst_env,
const char *src_content, size_t src_content_len, bool is_symlink)
bool mountAddMountPtHead(struct nsjconf_t* nsjconf, const char* src, const char* dst,
const char* fstype, const char* options, uintptr_t flags, isDir_t isDir,
bool mandatory, const char* src_env, const char* dst_env,
const char* src_content, size_t src_content_len, bool is_symlink)
{
return mountAddMountPt(nsjconf, /* head= */ true, src, dst, fstype, options, flags, isDir,
mandatory, src_env, dst_env, src_content, src_content_len,
is_symlink);
mandatory, src_env, dst_env, src_content, src_content_len,
is_symlink);
}
bool mountAddMountPtTail(struct nsjconf_t * nsjconf, const char *src, const char *dst,
const char *fstype, const char *options, uintptr_t flags, isDir_t isDir,
bool mandatory, const char *src_env, const char *dst_env,
const char *src_content, size_t src_content_len, bool is_symlink)
bool mountAddMountPtTail(struct nsjconf_t* nsjconf, const char* src, const char* dst,
const char* fstype, const char* options, uintptr_t flags, isDir_t isDir,
bool mandatory, const char* src_env, const char* dst_env,
const char* src_content, size_t src_content_len, bool is_symlink)
{
return mountAddMountPt(nsjconf, /* head= */ false, src, dst, fstype, options, flags, isDir,
mandatory, src_env, dst_env, src_content, src_content_len,
is_symlink);
mandatory, src_env, dst_env, src_content, src_content_len,
is_symlink);
}
const char *mountDescribeMountPt(struct mounts_t *mpt)
const char* mountDescribeMountPt(struct mounts_t* mpt)
{
static __thread char mount_pt_descr[4096];
snprintf(mount_pt_descr, sizeof(mount_pt_descr),
"src:'%s' dst:'%s' type:'%s' flags:%s options:'%s' isDir:%s",
mpt->src ? mpt->src : "[NULL]", mpt->dst, mpt->fs_type ? mpt->fs_type : "[NULL]",
mountFlagsToStr(mpt->flags), mpt->options ? mpt->options : "[NULL]",
mpt->isDir ? "true" : "false");
"src:'%s' dst:'%s' type:'%s' flags:%s options:'%s' isDir:%s",
mpt->src ? mpt->src : "[NULL]", mpt->dst, mpt->fs_type ? mpt->fs_type : "[NULL]",
mountFlagsToStr(mpt->flags), mpt->options ? mpt->options : "[NULL]",
mpt->isDir ? "true" : "false");
if (mpt->mandatory == false) {
utilSSnPrintf(mount_pt_descr, sizeof(mount_pt_descr), " mandatory:false");
}
if (mpt->src_content) {
utilSSnPrintf(mount_pt_descr, sizeof(mount_pt_descr), " src_content_len:%zu",
mpt->src_content_len);
mpt->src_content_len);
}
if (mpt->isSymlink) {
utilSSnPrintf(mount_pt_descr, sizeof(mount_pt_descr), " symlink:true");

24
mount.h
View File

@ -32,16 +32,16 @@ typedef enum {
NS_DIR_MAYBE,
} isDir_t;
const char *mountFlagsToStr(uintptr_t flags);
bool mountInitNs(struct nsjconf_t *nsjconf);
bool mountAddMountPtHead(struct nsjconf_t *nsjconf, const char *src, const char *dst,
const char *fstype, const char *options, uintptr_t flags, isDir_t isDir,
bool mandatory, const char *src_env, const char *dst_env,
const char *src_content, size_t src_content_len, bool is_symlink);
bool mountAddMountPtTail(struct nsjconf_t *nsjconf, const char *src, const char *dst,
const char *fstype, const char *options, uintptr_t flags, isDir_t isDir,
bool mandatory, const char *src_env, const char *dst_env,
const char *src_content, size_t src_content_len, bool is_symlink);
const char *mountDescribeMountPt(struct mounts_t *mpt);
const char* mountFlagsToStr(uintptr_t flags);
bool mountInitNs(struct nsjconf_t* nsjconf);
bool mountAddMountPtHead(struct nsjconf_t* nsjconf, const char* src, const char* dst,
const char* fstype, const char* options, uintptr_t flags, isDir_t isDir,
bool mandatory, const char* src_env, const char* dst_env,
const char* src_content, size_t src_content_len, bool is_symlink);
bool mountAddMountPtTail(struct nsjconf_t* nsjconf, const char* src, const char* dst,
const char* fstype, const char* options, uintptr_t flags, isDir_t isDir,
bool mandatory, const char* src_env, const char* dst_env,
const char* src_content, size_t src_content_len, bool is_symlink);
const char* mountDescribeMountPt(struct mounts_t* mpt);
#endif /* NS_MOUNT_H */
#endif /* NS_MOUNT_H */

76
net.c
View File

@ -45,12 +45,12 @@
#define IFACE_NAME "vs"
extern char **environ;
extern char** environ;
#if defined(NSJAIL_NL3_WITH_MACVLAN)
#include <netlink/route/link.h>
#include <netlink/route/link/macvlan.h>
bool netInitNsFromParent(struct nsjconf_t *nsjconf, int pid)
bool netInitNsFromParent(struct nsjconf_t* nsjconf, int pid)
{
if (nsjconf->clone_newnet == false) {
return true;
@ -61,7 +61,7 @@ bool netInitNsFromParent(struct nsjconf_t *nsjconf, int pid)
LOG_D("Putting iface:'%s' into namespace of PID:%d (with libnl3)", nsjconf->iface_vs, pid);
struct nl_sock *sk = nl_socket_alloc();
struct nl_sock* sk = nl_socket_alloc();
if (sk == NULL) {
LOG_E("Could not allocate socket with nl_socket_alloc()");
return false;
@ -74,14 +74,14 @@ bool netInitNsFromParent(struct nsjconf_t *nsjconf, int pid)
return false;
}
struct rtnl_link *rmv = rtnl_link_macvlan_alloc();
struct rtnl_link* rmv = rtnl_link_macvlan_alloc();
if (rmv == NULL) {
LOG_E("rtnl_link_macvlan_alloc(): %s", nl_geterror(err));
nl_socket_free(sk);
return false;
}
struct nl_cache *link_cache;
struct nl_cache* link_cache;
if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) {
LOG_E("rtnl_link_alloc_cache(): %s", nl_geterror(err));
rtnl_link_put(rmv);
@ -104,7 +104,7 @@ bool netInitNsFromParent(struct nsjconf_t *nsjconf, int pid)
if ((err = rtnl_link_add(sk, rmv, NLM_F_CREATE)) < 0) {
LOG_E("rtnl_link_add(name:'%s' link:'%s'): %s", IFACE_NAME, nsjconf->iface_vs,
nl_geterror(err));
nl_geterror(err));
nl_cache_free(link_cache);
rtnl_link_put(rmv);
nl_socket_free(sk);
@ -116,9 +116,9 @@ bool netInitNsFromParent(struct nsjconf_t *nsjconf, int pid)
nl_socket_free(sk);
return true;
}
#else // defined(NSJAIL_NL3_WITH_MACVLAN)
#else // defined(NSJAIL_NL3_WITH_MACVLAN)
bool netInitNsFromParent(struct nsjconf_t *nsjconf, int pid)
bool netInitNsFromParent(struct nsjconf_t* nsjconf, int pid)
{
if (nsjconf->clone_newnet == false) {
return true;
@ -128,13 +128,13 @@ bool netInitNsFromParent(struct nsjconf_t *nsjconf, int pid)
}
LOG_D("Putting iface:'%s' into namespace of PID:%d (with /sbin/ip)", nsjconf->iface_vs,
pid);
pid);
char pid_str[256];
snprintf(pid_str, sizeof(pid_str), "%d", pid);
const char *argv[] = {
"/sbin/ip", "link", "add", "link", (char *)nsjconf->iface_vs, "name", IFACE_NAME,
const char* argv[] = {
"/sbin/ip", "link", "add", "link", (char*)nsjconf->iface_vs, "name", IFACE_NAME,
"netns", pid_str, "type", "macvlan", "mode", "bridge", NULL
};
if (subprocSystem(argv, environ) != 0) {
@ -144,7 +144,7 @@ bool netInitNsFromParent(struct nsjconf_t *nsjconf, int pid)
return true;
}
#endif // defined(NSJAIL_NL3_WITH_MACVLAN)
#endif // defined(NSJAIL_NL3_WITH_MACVLAN)
static bool netIsSocket(int fd)
{
@ -157,7 +157,7 @@ static bool netIsSocket(int fd)
return true;
}
bool netLimitConns(struct nsjconf_t * nsjconf, int connsock)
bool netLimitConns(struct nsjconf_t* nsjconf, int connsock)
{
/* 0 means 'unlimited' */
if (nsjconf->max_conns_per_ip == 0) {
@ -166,13 +166,14 @@ bool netLimitConns(struct nsjconf_t * nsjconf, int connsock)
struct sockaddr_in6 addr;
char cs_addr[64];
netConnToText(connsock, true /* remote */ , cs_addr, sizeof(cs_addr), &addr);
netConnToText(connsock, true /* remote */, cs_addr, sizeof(cs_addr), &addr);
unsigned int cnt = 0;
struct pids_t *p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
struct pids_t* p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers)
{
if (memcmp(addr.sin6_addr.s6_addr, p->remote_addr.sin6_addr.s6_addr,
sizeof(*p->remote_addr.sin6_addr.s6_addr))
sizeof(*p->remote_addr.sin6_addr.s6_addr))
== 0) {
cnt++;
}
@ -180,19 +181,18 @@ bool netLimitConns(struct nsjconf_t * nsjconf, int connsock)
if (cnt >= nsjconf->max_conns_per_ip) {
LOG_W("Rejecting connection from '%s', max_conns_per_ip limit reached: %u", cs_addr,
nsjconf->max_conns_per_ip);
nsjconf->max_conns_per_ip);
return false;
}
return true;
}
int netGetRecvSocket(const char *bindhost, int port)
int netGetRecvSocket(const char* bindhost, int port)
{
if (port < 1 || port > 65535) {
LOG_F
("TCP port %d out of bounds (0 <= port <= 65535), specify one with --port <port>",
port);
LOG_F("TCP port %d out of bounds (0 <= port <= 65535), specify one with --port <port>",
port);
}
char bindaddr[128];
@ -206,7 +206,7 @@ int netGetRecvSocket(const char *bindhost, int port)
struct in6_addr in6a;
if (inet_pton(AF_INET6, bindaddr, &in6a) != 1) {
PLOG_E("Couldn't convert '%s' (orig:'%s') into AF_INET6 address", bindaddr,
bindhost);
bindhost);
return -1;
}
@ -227,7 +227,7 @@ int netGetRecvSocket(const char *bindhost, int port)
.sin6_addr = in6a,
.sin6_scope_id = 0,
};
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
close(sockfd);
PLOG_E("bind(host:[%s (orig:'%s')], port:%d)", bindaddr, bindhost, port);
return -1;
@ -239,7 +239,7 @@ int netGetRecvSocket(const char *bindhost, int port)
}
char ss_addr[64];
netConnToText(sockfd, false /* remote */ , ss_addr, sizeof(ss_addr), NULL);
netConnToText(sockfd, false /* remote */, ss_addr, sizeof(ss_addr), NULL);
LOG_I("Listening on %s", ss_addr);
return sockfd;
@ -249,7 +249,7 @@ int netAcceptConn(int listenfd)
{
struct sockaddr_in6 cli_addr;
socklen_t socklen = sizeof(cli_addr);
int connfd = accept(listenfd, (struct sockaddr *)&cli_addr, &socklen);
int connfd = accept(listenfd, (struct sockaddr*)&cli_addr, &socklen);
if (connfd == -1) {
if (errno != EINTR) {
PLOG_E("accept(%d)", listenfd);
@ -258,14 +258,14 @@ int netAcceptConn(int listenfd)
}
char cs_addr[64], ss_addr[64];
netConnToText(connfd, true /* remote */ , cs_addr, sizeof(cs_addr), NULL);
netConnToText(connfd, false /* remote */ , ss_addr, sizeof(ss_addr), NULL);
netConnToText(connfd, true /* remote */, cs_addr, sizeof(cs_addr), NULL);
netConnToText(connfd, false /* remote */, ss_addr, sizeof(ss_addr), NULL);
LOG_I("New connection from: %s on: %s", cs_addr, ss_addr);
return connfd;
}
void netConnToText(int fd, bool remote, char *buf, size_t s, struct sockaddr_in6 *addr_or_null)
void netConnToText(int fd, bool remote, char* buf, size_t s, struct sockaddr_in6* addr_or_null)
{
if (netIsSocket(fd) == false) {
snprintf(buf, s, "[STANDALONE_MODE]");
@ -275,13 +275,13 @@ void netConnToText(int fd, bool remote, char *buf, size_t s, struct sockaddr_in6
struct sockaddr_in6 addr;
socklen_t addrlen = sizeof(addr);
if (remote) {
if (getpeername(fd, (struct sockaddr *)&addr, &addrlen) == -1) {
if (getpeername(fd, (struct sockaddr*)&addr, &addrlen) == -1) {
PLOG_W("getpeername(%d)", fd);
snprintf(buf, s, "[unknown]");
return;
}
} else {
if (getsockname(fd, (struct sockaddr *)&addr, &addrlen) == -1) {
if (getsockname(fd, (struct sockaddr*)&addr, &addrlen) == -1) {
PLOG_W("getsockname(%d)", fd);
snprintf(buf, s, "[unknown]");
return;
@ -302,7 +302,7 @@ void netConnToText(int fd, bool remote, char *buf, size_t s, struct sockaddr_in6
return;
}
static bool netIfaceUp(const char *ifacename)
static bool netIfaceUp(const char* ifacename)
{
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (sock == -1) {
@ -332,7 +332,7 @@ static bool netIfaceUp(const char *ifacename)
return true;
}
static bool netConfigureVs(struct nsjconf_t *nsjconf)
static bool netConfigureVs(struct nsjconf_t* nsjconf)
{
struct ifreq ifr;
memset(&ifr, '\0', sizeof(ifr));
@ -356,7 +356,7 @@ static bool netConfigureVs(struct nsjconf_t *nsjconf)
return true;
}
struct sockaddr_in *sa = (struct sockaddr_in *)(&ifr.ifr_addr);
struct sockaddr_in* sa = (struct sockaddr_in*)(&ifr.ifr_addr);
sa->sin_family = AF_INET;
sa->sin_addr = addr;
if (ioctl(sock, SIOCSIFADDR, &ifr) == -1) {
@ -397,9 +397,9 @@ static bool netConfigureVs(struct nsjconf_t *nsjconf)
struct rtentry rt;
memset(&rt, '\0', sizeof(rt));
struct sockaddr_in *sdest = (struct sockaddr_in *)(&rt.rt_dst);
struct sockaddr_in *smask = (struct sockaddr_in *)(&rt.rt_genmask);
struct sockaddr_in *sgate = (struct sockaddr_in *)(&rt.rt_gateway);
struct sockaddr_in* sdest = (struct sockaddr_in*)(&rt.rt_dst);
struct sockaddr_in* smask = (struct sockaddr_in*)(&rt.rt_genmask);
struct sockaddr_in* sgate = (struct sockaddr_in*)(&rt.rt_gateway);
sdest->sin_family = AF_INET;
sdest->sin_addr.s_addr = INADDR_ANY;
smask->sin_family = AF_INET;
@ -420,7 +420,7 @@ static bool netConfigureVs(struct nsjconf_t *nsjconf)
return true;
}
bool netInitNsFromChild(struct nsjconf_t * nsjconf)
bool netInitNsFromChild(struct nsjconf_t* nsjconf)
{
if (nsjconf->clone_newnet == false) {
return true;

12
net.h
View File

@ -27,11 +27,11 @@
#include "common.h"
bool netLimitConns(struct nsjconf_t *nsjconf, int connsock);
int netGetRecvSocket(const char *bindhost, int port);
bool netLimitConns(struct nsjconf_t* nsjconf, int connsock);
int netGetRecvSocket(const char* bindhost, int port);
int netAcceptConn(int listenfd);
void netConnToText(int fd, bool remote, char *buf, size_t s, struct sockaddr_in6 *addr_or_null);
bool netInitNsFromParent(struct nsjconf_t *nsjconf, int pid);
bool netInitNsFromChild(struct nsjconf_t *nsjconf);
void netConnToText(int fd, bool remote, char* buf, size_t s, struct sockaddr_in6* addr_or_null);
bool netInitNsFromParent(struct nsjconf_t* nsjconf, int pid);
bool netInitNsFromChild(struct nsjconf_t* nsjconf);
#endif /* _NET_H */
#endif /* _NET_H */

View File

@ -94,15 +94,15 @@ static bool nsjailSetSigHandlers(void)
return true;
}
static bool nsjailSetTimer(struct nsjconf_t *nsjconf)
static bool nsjailSetTimer(struct nsjconf_t* nsjconf)
{
if (nsjconf->mode == MODE_STANDALONE_EXECVE) {
return true;
}
struct itimerval it = {
.it_value = {.tv_sec = 1,.tv_usec = 0},
.it_interval = {.tv_sec = 1,.tv_usec = 0},
.it_value = {.tv_sec = 1, .tv_usec = 0 },
.it_interval = {.tv_sec = 1, .tv_usec = 0 },
};
if (setitimer(ITIMER_REAL, &it, NULL) == -1) {
PLOG_E("setitimer(ITIMER_REAL)");
@ -111,7 +111,7 @@ static bool nsjailSetTimer(struct nsjconf_t *nsjconf)
return true;
}
static void nsjailListenMode(struct nsjconf_t *nsjconf)
static void nsjailListenMode(struct nsjconf_t* nsjconf)
{
int listenfd = netGetRecvSocket(nsjconf->bindhost, nsjconf->port);
if (listenfd == -1) {
@ -137,7 +137,7 @@ static void nsjailListenMode(struct nsjconf_t *nsjconf)
}
}
static int nsjailStandaloneMode(struct nsjconf_t *nsjconf)
static int nsjailStandaloneMode(struct nsjconf_t* nsjconf)
{
subprocRunChild(nsjconf, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO);
for (;;) {
@ -165,7 +165,7 @@ static int nsjailStandaloneMode(struct nsjconf_t *nsjconf)
// not reached
}
int main(int argc, char *argv[])
int main(int argc, char* argv[])
{
struct nsjconf_t nsjconf;
if (!cmdlineParse(argc, argv, &nsjconf)) {
@ -196,4 +196,4 @@ int main(int argc, char *argv[])
/*
* To satisfy requirement for BlocksRuntime in clang -fblocks
*/
void *_NSConcreteStackBlock[32] = { 0 };
void* _NSConcreteStackBlock[32] = { 0 };

View File

@ -25,4 +25,4 @@
#include "common.h"
#endif /* _NSJAIL_H */
#endif /* _NSJAIL_H */

2
pid.c
View File

@ -31,7 +31,7 @@
#include "log.h"
#include "subproc.h"
bool pidInitNs(struct nsjconf_t *nsjconf)
bool pidInitNs(struct nsjconf_t* nsjconf)
{
if (nsjconf->mode != MODE_STANDALONE_EXECVE) {
return true;

4
pid.h
View File

@ -26,6 +26,6 @@
#include "common.h"
bool pidInitNs(struct nsjconf_t *nsjconf);
bool pidInitNs(struct nsjconf_t* nsjconf);
#endif /* NS_PID_H */
#endif /* NS_PID_H */

View File

@ -29,11 +29,11 @@
#include "kafel.h"
#include "log.h"
#ifndef PR_SET_NO_NEW_PRIVS /* in prctl.h since Linux 3.5 */
#ifndef PR_SET_NO_NEW_PRIVS /* in prctl.h since Linux 3.5 */
#define PR_SET_NO_NEW_PRIVS 38
#endif /* PR_SET_NO_NEW_PRIVS */
#endif /* PR_SET_NO_NEW_PRIVS */
static bool sandboxPrepareAndCommit(struct nsjconf_t *nsjconf)
static bool sandboxPrepareAndCommit(struct nsjconf_t* nsjconf)
{
if (nsjconf->kafel_file == NULL && nsjconf->kafel_string == NULL) {
return true;
@ -66,7 +66,7 @@ static bool sandboxPrepareAndCommit(struct nsjconf_t *nsjconf)
return true;
}
bool sandboxApply(struct nsjconf_t * nsjconf)
bool sandboxApply(struct nsjconf_t* nsjconf)
{
return sandboxPrepareAndCommit(nsjconf);
}

View File

@ -26,6 +26,6 @@
#include "common.h"
bool sandboxApply(struct nsjconf_t *nsjconf);
bool sandboxApply(struct nsjconf_t* nsjconf);
#endif /* NS_SANDBOX_H */
#endif /* NS_SANDBOX_H */

152
subproc.c
View File

@ -53,20 +53,20 @@
static const char subprocDoneChar = 'D';
#define VALSTR_STRUCT(x) \
{ \
x, #x \
}
{ \
x, #x \
}
#if !defined(CLONE_NEWCGROUP)
#define CLONE_NEWCGROUP 0x02000000
#endif /* !defined(CLONE_NEWCGROUP) */
#endif /* !defined(CLONE_NEWCGROUP) */
static const char *subprocCloneFlagsToStr(uintptr_t flags)
static const char* subprocCloneFlagsToStr(uintptr_t flags)
{
static __thread char cloneFlagName[1024];
cloneFlagName[0] = '\0';
// clang-format off
// clang-format off
static struct {
const uintptr_t flag;
const char* const name;
@ -95,12 +95,12 @@ static const char *subprocCloneFlagsToStr(uintptr_t flags)
VALSTR_STRUCT(CLONE_NEWNET),
VALSTR_STRUCT(CLONE_IO),
};
// clang-format on
// clang-format on
for (size_t i = 0; i < ARRAYSIZE(cloneFlags); i++) {
if (flags & cloneFlags[i].flag) {
utilSSnPrintf(cloneFlagName, sizeof(cloneFlagName), "%s|",
cloneFlags[i].name);
cloneFlags[i].name);
}
}
@ -110,13 +110,13 @@ static const char *subprocCloneFlagsToStr(uintptr_t flags)
}
if (flags & ~(knownFlagMask)) {
utilSSnPrintf(cloneFlagName, sizeof(cloneFlagName), "%#tx|",
flags & ~(knownFlagMask));
flags & ~(knownFlagMask));
}
utilSSnPrintf(cloneFlagName, sizeof(cloneFlagName), "%s", utilSigName(flags & CSIGNAL));
return cloneFlagName;
}
static int subprocNewProc(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int fd_err, int pipefd)
static int subprocNewProc(struct nsjconf_t* nsjconf, int fd_in, int fd_out, int fd_err, int pipefd)
{
if (containSetupFD(nsjconf, fd_in, fd_out, fd_err) == false) {
exit(0xff);
@ -146,13 +146,14 @@ static int subprocNewProc(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int
if (nsjconf->keep_env == false) {
clearenv();
}
struct charptr_t *p;
TAILQ_FOREACH(p, &nsjconf->envs, pointers) {
putenv((char *)p->val);
struct charptr_t* p;
TAILQ_FOREACH(p, &nsjconf->envs, pointers)
{
putenv((char*)p->val);
}
char cs_addr[64];
netConnToText(fd_in, true /* remote */ , cs_addr, sizeof(cs_addr), NULL);
netConnToText(fd_in, true /* remote */, cs_addr, sizeof(cs_addr), NULL);
LOG_I("Executing '%s' for '%s'", nsjconf->exec_file, cs_addr);
for (size_t i = 0; nsjconf->argv[i]; i++) {
@ -163,20 +164,20 @@ static int subprocNewProc(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int
if (sandboxApply(nsjconf) == false) {
exit(0xff);
}
execv(nsjconf->exec_file, (char *const *)&nsjconf->argv[0]);
execv(nsjconf->exec_file, (char* const*)&nsjconf->argv[0]);
PLOG_E("execve('%s') failed", nsjconf->exec_file);
_exit(0xff);
}
static void subprocAdd(struct nsjconf_t *nsjconf, pid_t pid, int sock)
static void subprocAdd(struct nsjconf_t* nsjconf, pid_t pid, int sock)
{
struct pids_t *p = utilMalloc(sizeof(struct pids_t));
struct pids_t* p = utilMalloc(sizeof(struct pids_t));
p->pid = pid;
p->start = time(NULL);
netConnToText(sock, true /* remote */ , p->remote_txt, sizeof(p->remote_txt),
&p->remote_addr);
netConnToText(sock, true /* remote */, p->remote_txt, sizeof(p->remote_txt),
&p->remote_addr);
char fname[PATH_MAX];
snprintf(fname, sizeof(fname), "/proc/%d/syscall", (int)pid);
@ -185,16 +186,17 @@ static void subprocAdd(struct nsjconf_t *nsjconf, pid_t pid, int sock)
TAILQ_INSERT_HEAD(&nsjconf->pids, p, pointers);
LOG_D("Added pid '%d' with start time '%u' to the queue for IP: '%s'", pid,
(unsigned int)p->start, p->remote_txt);
(unsigned int)p->start, p->remote_txt);
}
static void subprocRemove(struct nsjconf_t *nsjconf, pid_t pid)
static void subprocRemove(struct nsjconf_t* nsjconf, pid_t pid)
{
struct pids_t *p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
struct pids_t* p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers)
{
if (p->pid == pid) {
LOG_D("Removing pid '%d' from the queue (IP:'%s', start time:'%s')", p->pid,
p->remote_txt, utilTimeToStr(p->start));
p->remote_txt, utilTimeToStr(p->start));
close(p->pid_syscall_fd);
TAILQ_REMOVE(&nsjconf->pids, p, pointers);
free(p);
@ -204,33 +206,36 @@ static void subprocRemove(struct nsjconf_t *nsjconf, pid_t pid)
LOG_W("PID: %d not found (?)", pid);
}
int subprocCount(struct nsjconf_t *nsjconf)
int subprocCount(struct nsjconf_t* nsjconf)
{
int cnt = 0;
struct pids_t *p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
struct pids_t* p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers)
{
cnt++;
}
return cnt;
}
void subprocDisplay(struct nsjconf_t *nsjconf)
void subprocDisplay(struct nsjconf_t* nsjconf)
{
LOG_I("Total number of spawned namespaces: %d", subprocCount(nsjconf));
time_t now = time(NULL);
struct pids_t *p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
struct pids_t* p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers)
{
time_t diff = now - p->start;
time_t left = nsjconf->tlimit ? nsjconf->tlimit - diff : 0;
LOG_I("PID: %d, Remote host: %s, Run time: %ld sec. (time left: %ld sec.)", p->pid,
p->remote_txt, (long)diff, (long)left);
p->remote_txt, (long)diff, (long)left);
}
}
static struct pids_t *subprocGetPidElem(struct nsjconf_t *nsjconf, pid_t pid)
static struct pids_t* subprocGetPidElem(struct nsjconf_t* nsjconf, pid_t pid)
{
struct pids_t *p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
struct pids_t* p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers)
{
if (p->pid == pid) {
return p;
}
@ -238,14 +243,14 @@ static struct pids_t *subprocGetPidElem(struct nsjconf_t *nsjconf, pid_t pid)
return NULL;
}
static void subprocSeccompViolation(struct nsjconf_t *nsjconf, siginfo_t * si)
static void subprocSeccompViolation(struct nsjconf_t* nsjconf, siginfo_t* si)
{
LOG_W("PID: %d commited a syscall/seccomp violation and exited with SIGSYS", si->si_pid);
struct pids_t *p = subprocGetPidElem(nsjconf, si->si_pid);
struct pids_t* p = subprocGetPidElem(nsjconf, si->si_pid);
if (p == NULL) {
LOG_W("PID: %d, Syscall number: %d, Seccomp reason: %d", (int)si->si_pid,
si->si_syscall, si->si_errno);
si->si_syscall, si->si_errno);
LOG_E("Couldn't find pid element in the subproc list for PID: %d", (int)si->si_pid);
return;
}
@ -254,31 +259,29 @@ static void subprocSeccompViolation(struct nsjconf_t *nsjconf, siginfo_t * si)
ssize_t rdsize = utilReadFromFd(p->pid_syscall_fd, buf, sizeof(buf) - 1);
if (rdsize < 1) {
LOG_W("PID: %d, Syscall number: %d, Seccomp reason: %d", (int)si->si_pid,
si->si_syscall, si->si_errno);
si->si_syscall, si->si_errno);
return;
}
buf[rdsize - 1] = '\0';
uintptr_t arg1, arg2, arg3, arg4, arg5, arg6, sp, pc;
ptrdiff_t sc;
int ret =
sscanf(buf, "%td %tx %tx %tx %tx %tx %tx %tx %tx", &sc, &arg1, &arg2, &arg3, &arg4,
&arg5, &arg6, &sp, &pc);
int ret = sscanf(buf, "%td %tx %tx %tx %tx %tx %tx %tx %tx", &sc, &arg1, &arg2, &arg3, &arg4,
&arg5, &arg6, &sp, &pc);
if (ret == 9) {
LOG_W
("PID: %d, Syscall number: %td, Arguments: %#tx, %#tx, %#tx, %#tx, %#tx, %#tx, SP: %#tx, PC: %#tx, si_syscall: %d, si_errno: %#x",
(int)si->si_pid, sc, arg1, arg2, arg3, arg4, arg5, arg6, sp, pc,
si->si_syscall, si->si_errno);
LOG_W("PID: %d, Syscall number: %td, Arguments: %#tx, %#tx, %#tx, %#tx, %#tx, %#tx, SP: %#tx, PC: %#tx, si_syscall: %d, si_errno: %#x",
(int)si->si_pid, sc, arg1, arg2, arg3, arg4, arg5, arg6, sp, pc,
si->si_syscall, si->si_errno);
} else if (ret == 3) {
LOG_W("PID: %d, Syscall number: %d, Seccomp reason: %d, SP: %#tx, PC: %#tx",
(int)si->si_pid, si->si_syscall, si->si_errno, arg1, arg2);
(int)si->si_pid, si->si_syscall, si->si_errno, arg1, arg2);
} else {
LOG_W("PID: %d, Syscall number: %d, Seccomp reason: %d, Syscall string '%s'",
(int)si->si_pid, si->si_syscall, si->si_errno, buf);
(int)si->si_pid, si->si_syscall, si->si_errno, buf);
}
}
int subprocReap(struct nsjconf_t *nsjconf)
int subprocReap(struct nsjconf_t* nsjconf)
{
int status;
int rv = 0;
@ -299,16 +302,16 @@ int subprocReap(struct nsjconf_t *nsjconf)
if (wait4(si.si_pid, &status, WNOHANG, NULL) == si.si_pid) {
cgroupFinishFromParent(nsjconf, si.si_pid);
const char *remote_txt = "[UNKNOWN]";
struct pids_t *elem = subprocGetPidElem(nsjconf, si.si_pid);
const char* remote_txt = "[UNKNOWN]";
struct pids_t* elem = subprocGetPidElem(nsjconf, si.si_pid);
if (elem) {
remote_txt = elem->remote_txt;
}
if (WIFEXITED(status)) {
LOG_I("PID: %d (%s) exited with status: %d, (PIDs left: %d)",
si.si_pid, remote_txt, WEXITSTATUS(status),
subprocCount(nsjconf) - 1);
si.si_pid, remote_txt, WEXITSTATUS(status),
subprocCount(nsjconf) - 1);
subprocRemove(nsjconf, si.si_pid);
rv = WEXITSTATUS(status) % 100;
if (rv == 0 && WEXITSTATUS(status) != 0) {
@ -316,10 +319,9 @@ int subprocReap(struct nsjconf_t *nsjconf)
}
}
if (WIFSIGNALED(status)) {
LOG_I
("PID: %d (%s) terminated with signal: %s (%d), (PIDs left: %d)",
si.si_pid, remote_txt, utilSigName(WTERMSIG(status)),
WTERMSIG(status), subprocCount(nsjconf) - 1);
LOG_I("PID: %d (%s) terminated with signal: %s (%d), (PIDs left: %d)",
si.si_pid, remote_txt, utilSigName(WTERMSIG(status)),
WTERMSIG(status), subprocCount(nsjconf) - 1);
subprocRemove(nsjconf, si.si_pid);
rv = 100 + WTERMSIG(status);
}
@ -327,8 +329,9 @@ int subprocReap(struct nsjconf_t *nsjconf)
}
time_t now = time(NULL);
struct pids_t *p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
struct pids_t* p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers)
{
if (nsjconf->tlimit == 0) {
continue;
}
@ -336,7 +339,7 @@ int subprocReap(struct nsjconf_t *nsjconf)
time_t diff = now - p->start;
if (diff >= nsjconf->tlimit) {
LOG_I("PID: %d run time >= time limit (%ld >= %ld) (%s). Killing it", pid,
(long)diff, (long)nsjconf->tlimit, p->remote_txt);
(long)diff, (long)nsjconf->tlimit, p->remote_txt);
/*
* Probably a kernel bug - some processes cannot be killed with KILL if
* they're namespaced, and in a stopped state
@ -350,15 +353,16 @@ int subprocReap(struct nsjconf_t *nsjconf)
return rv;
}
void subprocKillAll(struct nsjconf_t *nsjconf)
void subprocKillAll(struct nsjconf_t* nsjconf)
{
struct pids_t *p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
struct pids_t* p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers)
{
kill(p->pid, SIGKILL);
}
}
static bool subprocInitParent(struct nsjconf_t *nsjconf, pid_t pid, int pipefd)
static bool subprocInitParent(struct nsjconf_t* nsjconf, pid_t pid, int pipefd)
{
if (netInitNsFromParent(nsjconf, pid) == false) {
LOG_E("Couldn't create and put MACVTAP interface into NS of PID '%d'", pid);
@ -372,8 +376,7 @@ static bool subprocInitParent(struct nsjconf_t *nsjconf, pid_t pid, int pipefd)
LOG_E("Couldn't initialize user namespaces for pid %d", pid);
return false;
}
if (utilWriteToFd(pipefd, &subprocDoneChar, sizeof(subprocDoneChar)) !=
sizeof(subprocDoneChar)) {
if (utilWriteToFd(pipefd, &subprocDoneChar, sizeof(subprocDoneChar)) != sizeof(subprocDoneChar)) {
LOG_E("Couldn't signal the new process via a socketpair");
return false;
}
@ -381,11 +384,11 @@ static bool subprocInitParent(struct nsjconf_t *nsjconf, pid_t pid, int pipefd)
}
/* Will be used inside the child process only, so it's save to have it in BSS */
static uint8_t subprocCloneStack[128 * 1024]; /* 128 KiB */
static uint8_t subprocCloneStack[128 * 1024]; /* 128 KiB */
/* Cannot be on the stack, as the child's stack pointer will change after clone() */
static __thread jmp_buf env;
static int subprocCloneFunc(void *arg __attribute__ ((unused)))
static int subprocCloneFunc(void* arg __attribute__((unused)))
{
longjmp(env, 1);
return 0;
@ -409,7 +412,7 @@ pid_t subprocClone(uintptr_t flags)
* Avoid the problem of the stack growing up/down under different CPU architectures, by using
* middle of the static stack buffer (which is temporary, and used only inside of subprocCloneFunc
*/
void *stack = &subprocCloneStack[sizeof(subprocCloneStack) / 2];
void* stack = &subprocCloneStack[sizeof(subprocCloneStack) / 2];
/* Parent */
return clone(subprocCloneFunc, stack, flags, NULL, NULL, NULL);
}
@ -417,7 +420,7 @@ pid_t subprocClone(uintptr_t flags)
return 0;
}
void subprocRunChild(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int fd_err)
void subprocRunChild(struct nsjconf_t* nsjconf, int fd_in, int fd_out, int fd_err)
{
if (netLimitConns(nsjconf, fd_in) == false) {
return;
@ -461,7 +464,8 @@ void subprocRunChild(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int fd_er
PLOG_E("clone(flags=%s) failed. You probably need root privileges if your system "
"doesn't support CLONE_NEWUSER. Alternatively, you might want to recompile your "
"kernel with support for namespaces or check the setting of the "
"kernel.unprivileged_userns_clone sysctl", subprocCloneFlagsToStr(flags));
"kernel.unprivileged_userns_clone sysctl",
subprocCloneFlagsToStr(flags));
close(parent_fd);
return;
}
@ -474,10 +478,10 @@ void subprocRunChild(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int fd_er
close(parent_fd);
char cs_addr[64];
netConnToText(fd_in, true /* remote */ , cs_addr, sizeof(cs_addr), NULL);
netConnToText(fd_in, true /* remote */, cs_addr, sizeof(cs_addr), NULL);
}
int subprocSystem(const char **argv, char **env)
int subprocSystem(const char** argv, char** env)
{
bool exec_failed = false;
@ -497,7 +501,7 @@ int subprocSystem(const char **argv, char **env)
if (pid == 0) {
close(sv[0]);
execve(argv[0], (char *const *)argv, (char *const *)env);
execve(argv[0], (char* const*)argv, (char* const*)env);
PLOG_W("execve('%s')", argv[0]);
utilWriteToFd(sv[1], "A", 1);
exit(0);
@ -535,7 +539,7 @@ int subprocSystem(const char **argv, char **env)
if (WIFSIGNALED(status)) {
int exit_signal = WTERMSIG(status);
LOG_W("PID %d killed by signal: %d (%s)", pid, exit_signal,
utilSigName(exit_signal));
utilSigName(exit_signal));
return 2;
}
LOG_W("Unknown exit status: %d", status);

View File

@ -27,15 +27,15 @@
#include <inttypes.h>
#include <unistd.h>
void subprocRunChild(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int fd_err);
int subprocCount(struct nsjconf_t *nsjconf);
void subprocDisplay(struct nsjconf_t *nsjconf);
void subprocKillAll(struct nsjconf_t *nsjconf);
int subprocSystem(const char **argv, char **env);
void subprocRunChild(struct nsjconf_t* nsjconf, int fd_in, int fd_out, int fd_err);
int subprocCount(struct nsjconf_t* nsjconf);
void subprocDisplay(struct nsjconf_t* nsjconf);
void subprocKillAll(struct nsjconf_t* nsjconf);
int subprocSystem(const char** argv, char** env);
pid_t subprocClone(uintptr_t flags);
void subprocCloneFlags(struct nsjconf_t *nsjconf);
void subprocCloneFlags(struct nsjconf_t* nsjconf);
/* Returns the exit code of the first failing subprocess, or 0 if none fail */
int subprocReap(struct nsjconf_t *nsjconf);
int subprocReap(struct nsjconf_t* nsjconf);
#endif /* NS_PROC_H */
#endif /* NS_PROC_H */

83
user.c
View File

@ -52,7 +52,7 @@ static bool userSetGroups(pid_t pid)
char fname[PATH_MAX];
snprintf(fname, sizeof(fname), "/proc/%d/setgroups", pid);
const char *denystr = "deny";
const char* denystr = "deny";
if (utilWriteBufToFile(fname, denystr, strlen(denystr), O_WRONLY) == false) {
LOG_E("utilWriteBufToFile('%s', '%s') failed", fname, denystr);
return false;
@ -60,20 +60,21 @@ static bool userSetGroups(pid_t pid)
return true;
}
static bool userUidMapSelf(struct nsjconf_t *nsjconf, pid_t pid)
static bool userUidMapSelf(struct nsjconf_t* nsjconf, pid_t pid)
{
char fname[PATH_MAX];
snprintf(fname, sizeof(fname), "/proc/%d/uid_map", pid);
char map[4096] = {[0] = '\0' };
struct idmap_t *p;
TAILQ_FOREACH(p, &nsjconf->uids, pointers) {
struct idmap_t* p;
TAILQ_FOREACH(p, &nsjconf->uids, pointers)
{
if (p->is_newidmap) {
continue;
}
utilSSnPrintf(map, sizeof(map), "%lu %lu %zu\n", (unsigned long)p->inside_id,
(unsigned long)p->outside_id, p->count);
(unsigned long)p->outside_id, p->count);
}
if (strlen(map) == 0) {
@ -89,20 +90,21 @@ static bool userUidMapSelf(struct nsjconf_t *nsjconf, pid_t pid)
return true;
}
static bool userGidMapSelf(struct nsjconf_t *nsjconf, pid_t pid)
static bool userGidMapSelf(struct nsjconf_t* nsjconf, pid_t pid)
{
char fname[PATH_MAX];
snprintf(fname, sizeof(fname), "/proc/%d/gid_map", pid);
char map[4096] = {[0] = '\0' };
struct idmap_t *p;
TAILQ_FOREACH(p, &nsjconf->gids, pointers) {
struct idmap_t* p;
TAILQ_FOREACH(p, &nsjconf->gids, pointers)
{
if (p->is_newidmap) {
continue;
}
utilSSnPrintf(map, sizeof(map), "%lu %lu %zu\n", (unsigned long)p->inside_id,
(unsigned long)p->outside_id, p->count);
(unsigned long)p->outside_id, p->count);
}
if (strlen(map) == 0) {
@ -119,11 +121,11 @@ 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)
static bool userGidMapExternal(struct nsjconf_t* nsjconf, pid_t pid UNUSED)
{
static size_t idx = 0;
const char *argv[1024];
const char* argv[1024];
char parms[1024][256];
argv[idx++] = "/usr/bin/newgidmap";
@ -132,9 +134,10 @@ static bool userGidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
argv[idx] = parms[idx];
idx++;
struct idmap_t *p;
struct idmap_t* p;
bool use = false;
TAILQ_FOREACH(p, &nsjconf->gids, pointers) {
TAILQ_FOREACH(p, &nsjconf->gids, pointers)
{
if (p->is_newidmap == false) {
continue;
}
@ -172,11 +175,11 @@ 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)
static bool userUidMapExternal(struct nsjconf_t* nsjconf, pid_t pid UNUSED)
{
static size_t idx = 0;
const char *argv[1024];
const char* argv[1024];
char parms[1024][256];
argv[idx++] = "/usr/bin/newuidmap";
@ -186,8 +189,9 @@ static bool userUidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
idx++;
bool use = false;
struct idmap_t *p;
TAILQ_FOREACH(p, &nsjconf->uids, pointers) {
struct idmap_t* p;
TAILQ_FOREACH(p, &nsjconf->uids, pointers)
{
if (p->is_newidmap == false) {
continue;
}
@ -224,7 +228,7 @@ static bool userUidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
return true;
}
static bool userUidGidMap(struct nsjconf_t *nsjconf, pid_t pid)
static bool userUidGidMap(struct nsjconf_t* nsjconf, pid_t pid)
{
if (!userGidMapSelf(nsjconf, pid)) {
return false;
@ -241,7 +245,7 @@ static bool userUidGidMap(struct nsjconf_t *nsjconf, pid_t pid)
return true;
}
bool userInitNsFromParent(struct nsjconf_t * nsjconf, pid_t pid)
bool userInitNsFromParent(struct nsjconf_t* nsjconf, pid_t pid)
{
if (userSetGroups(pid) == false) {
return false;
@ -255,13 +259,13 @@ bool userInitNsFromParent(struct nsjconf_t * nsjconf, pid_t pid)
return true;
}
bool userInitNsFromChild(struct nsjconf_t * nsjconf)
bool userInitNsFromChild(struct nsjconf_t* nsjconf)
{
/*
* Best effort because of /proc/self/setgroups
*/
LOG_D("setgroups(0, NULL)");
gid_t *group_list = NULL;
gid_t* group_list = NULL;
if (setgroups(0, group_list) == -1) {
PLOG_D("setgroups(NULL) failed");
}
@ -270,24 +274,23 @@ bool userInitNsFromChild(struct nsjconf_t * nsjconf)
* Make sure all capabilities are retained after the subsequent setuid/setgid, as they will be
* needed for privileged operations: mounts, uts change etc.
*/
if (prctl(PR_SET_SECUREBITS, SECBIT_KEEP_CAPS | SECBIT_NO_SETUID_FIXUP, 0UL, 0UL, 0UL) ==
-1) {
if (prctl(PR_SET_SECUREBITS, SECBIT_KEEP_CAPS | SECBIT_NO_SETUID_FIXUP, 0UL, 0UL, 0UL) == -1) {
PLOG_E("prctl(PR_SET_SECUREBITS, SECBIT_KEEP_CAPS | SECBIT_NO_SETUID_FIXUP)");
return false;
}
LOG_D("setresgid(%d, %d, %d)", TAILQ_FIRST(&nsjconf->gids)->inside_id,
TAILQ_FIRST(&nsjconf->gids)->inside_id, TAILQ_FIRST(&nsjconf->gids)->inside_id);
TAILQ_FIRST(&nsjconf->gids)->inside_id, TAILQ_FIRST(&nsjconf->gids)->inside_id);
if (syscall(__NR_setresgid, TAILQ_FIRST(&nsjconf->gids)->inside_id,
TAILQ_FIRST(&nsjconf->gids)->inside_id, TAILQ_FIRST(&nsjconf->gids)->inside_id)
TAILQ_FIRST(&nsjconf->gids)->inside_id, TAILQ_FIRST(&nsjconf->gids)->inside_id)
== -1) {
PLOG_E("setresgid(%u)", TAILQ_FIRST(&nsjconf->gids)->inside_id);
return false;
}
LOG_D("setresuid(%d, %d, %d)", TAILQ_FIRST(&nsjconf->uids)->inside_id,
TAILQ_FIRST(&nsjconf->uids)->inside_id, TAILQ_FIRST(&nsjconf->uids)->inside_id);
TAILQ_FIRST(&nsjconf->uids)->inside_id, TAILQ_FIRST(&nsjconf->uids)->inside_id);
if (syscall(__NR_setresuid, TAILQ_FIRST(&nsjconf->uids)->inside_id,
TAILQ_FIRST(&nsjconf->uids)->inside_id, TAILQ_FIRST(&nsjconf->uids)->inside_id)
TAILQ_FIRST(&nsjconf->uids)->inside_id, TAILQ_FIRST(&nsjconf->uids)->inside_id)
== -1) {
PLOG_E("setresuid(%u)", TAILQ_FIRST(&nsjconf->uids)->inside_id);
return false;
@ -296,67 +299,67 @@ bool userInitNsFromChild(struct nsjconf_t * nsjconf)
return true;
}
static uid_t cmdParseUid(const char *id)
static uid_t cmdParseUid(const char* id)
{
if (id == NULL || strlen(id) == 0) {
return getuid();
}
struct passwd *pw = getpwnam(id);
struct passwd* pw = getpwnam(id);
if (pw != NULL) {
return pw->pw_uid;
}
if (utilIsANumber(id)) {
return (uid_t) strtoull(id, NULL, 0);
return (uid_t)strtoull(id, NULL, 0);
}
return -1;
}
static gid_t cmdParseGid(const char *id)
static gid_t cmdParseGid(const char* id)
{
if (id == NULL || strlen(id) == 0) {
return getgid();
}
struct group *gr = getgrnam(id);
struct group* gr = getgrnam(id);
if (gr != NULL) {
return gr->gr_gid;
}
if (utilIsANumber(id)) {
return (gid_t) strtoull(id, NULL, 0);
return (gid_t)strtoull(id, NULL, 0);
}
return -1;
}
bool userParseId(struct nsjconf_t * nsjconf, const char *i_id, const char *o_id, size_t cnt,
bool is_gid, bool is_newidmap)
bool userParseId(struct nsjconf_t* nsjconf, const char* i_id, const char* o_id, size_t cnt,
bool is_gid, bool is_newidmap)
{
uid_t inside_id;
uid_t outside_id;
if (is_gid) {
inside_id = cmdParseGid(i_id);
if (inside_id == (uid_t) - 1) {
if (inside_id == (uid_t)-1) {
LOG_W("Cannot parse '%s' as GID", i_id);
return false;
}
outside_id = cmdParseGid(o_id);
if (inside_id == (uid_t) - 1) {
if (inside_id == (uid_t)-1) {
LOG_W("Cannot parse '%s' as GID", o_id);
return false;
}
} else {
inside_id = cmdParseUid(i_id);
if (inside_id == (uid_t) - 1) {
if (inside_id == (uid_t)-1) {
LOG_W("Cannot parse '%s' as UID", i_id);
return false;
}
outside_id = cmdParseUid(o_id);
if (inside_id == (uid_t) - 1) {
if (inside_id == (uid_t)-1) {
LOG_W("Cannot parse '%s' as UID", o_id);
return false;
}
}
struct idmap_t *p = utilMalloc(sizeof(struct idmap_t));
struct idmap_t* p = utilMalloc(sizeof(struct idmap_t));
p->inside_id = inside_id;
p->outside_id = outside_id;
p->count = cnt;

10
user.h
View File

@ -26,10 +26,10 @@
#include "common.h"
bool userInitNsFromParent(struct nsjconf_t *nsjconf, pid_t pid);
bool userInitNsFromChild(struct nsjconf_t *nsjconf);
bool userInitNsFromParent(struct nsjconf_t* nsjconf, pid_t pid);
bool userInitNsFromChild(struct nsjconf_t* nsjconf);
bool userParseId(struct nsjconf_t *nsjconf, const char *i_id, const char *o_id, size_t cnt,
bool is_gid, bool is_newidmap);
bool userParseId(struct nsjconf_t* nsjconf, const char* i_id, const char* o_id, size_t cnt,
bool is_gid, bool is_newidmap);
#endif /* NS_USER_H */
#endif /* NS_USER_H */

58
util.c
View File

@ -39,47 +39,47 @@
#include "log.h"
void *utilMalloc(size_t sz)
void* utilMalloc(size_t sz)
{
void *ret = malloc(sz);
void* ret = malloc(sz);
if (ret == NULL) {
LOG_F("malloc(sz=%zu) failed", sz);
}
return ret;
}
void *utilCalloc(size_t sz)
void* utilCalloc(size_t sz)
{
void *r = utilMalloc(sz);
void* r = utilMalloc(sz);
memset(r, '\0', sz);
return r;
}
char *utilStrDup(const char *str)
char* utilStrDup(const char* str)
{
if (str == NULL) {
return NULL;
}
char *ret = strdup(str);
char* ret = strdup(str);
if (ret == NULL) {
LOG_E("Cannot allocate memory for strdup(sz=%zu)", strlen(str));
}
return ret;
}
uint8_t *utilMemDup(const uint8_t * src, size_t len)
uint8_t* utilMemDup(const uint8_t* src, size_t len)
{
if (src == NULL) {
return NULL;
}
uint8_t *ret = utilMalloc(len);
uint8_t* ret = utilMalloc(len);
memcpy(ret, src, len);
return ret;
}
ssize_t utilReadFromFd(int fd, void *buf, size_t len)
ssize_t utilReadFromFd(int fd, void* buf, size_t len)
{
uint8_t *charbuf = (uint8_t *) buf;
uint8_t* charbuf = (uint8_t*)buf;
size_t readSz = 0;
while (readSz < len) {
@ -95,7 +95,7 @@ ssize_t utilReadFromFd(int fd, void *buf, size_t len)
return readSz;
}
ssize_t utilReadFromFile(const char *fname, void *buf, size_t len)
ssize_t utilReadFromFile(const char* fname, void* buf, size_t len)
{
int fd;
TEMP_FAILURE_RETRY(fd = open(fname, O_RDONLY | O_CLOEXEC));
@ -108,9 +108,9 @@ ssize_t utilReadFromFile(const char *fname, void *buf, size_t len)
return ret;
}
ssize_t utilWriteToFd(int fd, const void *buf, size_t len)
ssize_t utilWriteToFd(int fd, const void* buf, size_t len)
{
const uint8_t *charbuf = (const uint8_t *)buf;
const uint8_t* charbuf = (const uint8_t*)buf;
size_t writtenSz = 0;
while (writtenSz < len) {
@ -126,7 +126,7 @@ ssize_t utilWriteToFd(int fd, const void *buf, size_t len)
return true;
}
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)
{
int fd;
TEMP_FAILURE_RETRY(fd = open(filename, open_flags, 0644));
@ -148,7 +148,7 @@ bool utilWriteBufToFile(const char *filename, const void *buf, size_t len, int o
return true;
}
bool utilCreateDirRecursively(const char *dir)
bool utilCreateDirRecursively(const char* dir)
{
if (dir[0] != '/') {
LOG_W("The directory path must start with '/': '%s' provided", dir);
@ -163,13 +163,13 @@ bool utilCreateDirRecursively(const char *dir)
char path[PATH_MAX];
snprintf(path, sizeof(path), "%s", dir);
char *curr = path;
char* curr = path;
for (;;) {
while (*curr == '/') {
curr++;
}
char *next = strchr(curr, '/');
char* next = strchr(curr, '/');
if (next == NULL) {
close(prev_dir_fd);
return true;
@ -194,7 +194,7 @@ 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, ...)
{
char buf1[size];
char buf2[size];
@ -209,7 +209,7 @@ int utilSSnPrintf(char *str, size_t size, const char *format, ...)
return snprintf(str, size, "%s%s", buf1, buf2);
}
bool utilIsANumber(const char *s)
bool utilIsANumber(const char* s)
{
for (int i = 0; s[i]; s++) {
if (!isdigit(s[i]) && s[i] != 'x') {
@ -232,16 +232,16 @@ static void utilRndInitThread(void)
if (syscall(__NR_getrandom, &rndX, sizeof(rndX), 0) == sizeof(rndX)) {
return;
}
#endif /* defined(__NR_getrandom) */
#endif /* defined(__NR_getrandom) */
int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
if (fd == -1) {
PLOG_D("Couldn't open /dev/urandom for reading. Using gettimeofday fall-back");
struct timeval tv;
gettimeofday(&tv, NULL);
rndX = tv.tv_usec + ((uint64_t) tv.tv_sec << 32);
rndX = tv.tv_usec + ((uint64_t)tv.tv_sec << 32);
return;
}
if (utilReadFromFd(fd, (uint8_t *) & rndX, sizeof(rndX)) != sizeof(rndX)) {
if (utilReadFromFd(fd, (uint8_t*)&rndX, sizeof(rndX)) != sizeof(rndX)) {
PLOG_F("Couldn't read '%zu' bytes from /dev/urandom", sizeof(rndX));
close(fd);
}
@ -256,15 +256,15 @@ uint64_t utilRnd64(void)
}
#define VALSTR_STRUCT(x) \
{ \
x, #x \
}
const char *utilSigName(int signo)
{ \
x, #x \
}
const char* utilSigName(int signo)
{
static __thread char sigstr[32];
sigstr[0] = '\0';
// clang-format off
// clang-format off
static struct {
const int signo;
const char* const name;
@ -299,7 +299,7 @@ const char *utilSigName(int signo)
VALSTR_STRUCT(SIGUSR2),
VALSTR_STRUCT(SIGWINCH),
};
// clang-format on
// clang-format on
for (size_t i = 0; i < ARRAYSIZE(sigNames); i++) {
if (signo == sigNames[i].signo) {
@ -317,7 +317,7 @@ const char *utilSigName(int signo)
}
static __thread char timestr[64];
const char *utilTimeToStr(time_t t)
const char* utilTimeToStr(time_t t)
{
struct tm utctime;
localtime_r(&t, &utctime);

28
util.h
View File

@ -28,19 +28,19 @@
#include "common.h"
void *utilMalloc(size_t sz);
void *utilCalloc(size_t sz);
char *utilStrDup(const char *str);
uint8_t *utilMemDup(const uint8_t * src, size_t len);
ssize_t utilReadFromFd(int fd, void *buf, size_t len);
ssize_t utilReadFromFile(const char *fname, 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 utilCreateDirRecursively(const char *dir);
int utilSSnPrintf(char *str, size_t size, const char *format, ...);
bool utilIsANumber(const char *s);
void* utilMalloc(size_t sz);
void* utilCalloc(size_t sz);
char* utilStrDup(const char* str);
uint8_t* utilMemDup(const uint8_t* src, size_t len);
ssize_t utilReadFromFd(int fd, void* buf, size_t len);
ssize_t utilReadFromFile(const char* fname, 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 utilCreateDirRecursively(const char* dir);
int utilSSnPrintf(char* str, size_t size, const char* format, ...);
bool utilIsANumber(const char* s);
uint64_t utilRnd64(void);
const char *utilSigName(int signo);
const char *utilTimeToStr(time_t t);
const char* utilSigName(int signo);
const char* utilTimeToStr(time_t t);
#endif /* NS_UTIL_H */
#endif /* NS_UTIL_H */

2
uts.c
View File

@ -26,7 +26,7 @@
#include "log.h"
bool utsInitNs(struct nsjconf_t * nsjconf)
bool utsInitNs(struct nsjconf_t* nsjconf)
{
if (nsjconf->clone_newuts == false) {
return true;

4
uts.h
View File

@ -27,6 +27,6 @@
#include "common.h"
bool utsInitNs(struct nsjconf_t *nsjconf);
bool utsInitNs(struct nsjconf_t* nsjconf);
#endif /* NS_UTS_H */
#endif /* NS_UTS_H */