make indent
This commit is contained in:
parent
414e999787
commit
74b43346bd
2
Makefile
2
Makefile
@ -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
36
caps.c
@ -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
6
caps.h
@ -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 */
|
||||
|
35
cgroup.c
35
cgroup.c
@ -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);
|
||||
|
6
cgroup.h
6
cgroup.h
@ -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
335
cmdline.c
@ -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]);
|
||||
|
@ -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
106
common.h
@ -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
464
config.cc
@ -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;
|
||||
}
|
||||
|
6
config.h
6
config.h
@ -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 */
|
||||
|
39
contain.c
39
contain.c
@ -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;
|
||||
|
@ -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
19
cpu.c
@ -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
4
cpu.h
@ -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
25
log.c
@ -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
8
log.h
@ -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
138
mount.c
@ -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
24
mount.h
@ -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
76
net.c
@ -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
12
net.h
@ -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 */
|
||||
|
14
nsjail.c
14
nsjail.c
@ -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 };
|
||||
|
2
nsjail.h
2
nsjail.h
@ -25,4 +25,4 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#endif /* _NSJAIL_H */
|
||||
#endif /* _NSJAIL_H */
|
||||
|
2
pid.c
2
pid.c
@ -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
4
pid.h
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
152
subproc.c
@ -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);
|
||||
|
16
subproc.h
16
subproc.h
@ -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
83
user.c
@ -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
10
user.h
@ -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
58
util.c
@ -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
28
util.h
@ -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
2
uts.c
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user