makedepend -Y -Ykafel/include -- -- $(SRCS_C) $(SRCS_CXX) $(SRCS_PB_CXX)
indent:
- clang-format -style="{BasedOnStyle: webkit, IndentWidth: 8, UseTab: Always, IndentCaseLabels: false, ColumnLimit: 100}" -i -sort-includes *.c *.h $(SRCS_CXX)
+ clang-format -style="{BasedOnStyle: google, IndentWidth: 8, UseTab: Always, IndentCaseLabels: false, ColumnLimit: 100, AlignAfterOpenBracket: false}" -i -sort-includes *.c *.h $(SRCS_CXX)
# DO NOT DELETE THIS LINE -- make depend depends on it.
const int val;
const char* const name;
} const capNames[] = {
- NS_VALSTR_STRUCT(CAP_CHOWN),
- NS_VALSTR_STRUCT(CAP_DAC_OVERRIDE),
- NS_VALSTR_STRUCT(CAP_DAC_READ_SEARCH),
- NS_VALSTR_STRUCT(CAP_FOWNER),
- NS_VALSTR_STRUCT(CAP_FSETID),
- NS_VALSTR_STRUCT(CAP_KILL),
- NS_VALSTR_STRUCT(CAP_SETGID),
- NS_VALSTR_STRUCT(CAP_SETUID),
- NS_VALSTR_STRUCT(CAP_SETPCAP),
- NS_VALSTR_STRUCT(CAP_LINUX_IMMUTABLE),
- NS_VALSTR_STRUCT(CAP_NET_BIND_SERVICE),
- NS_VALSTR_STRUCT(CAP_NET_BROADCAST),
- NS_VALSTR_STRUCT(CAP_NET_ADMIN),
- NS_VALSTR_STRUCT(CAP_NET_RAW),
- NS_VALSTR_STRUCT(CAP_IPC_LOCK),
- NS_VALSTR_STRUCT(CAP_IPC_OWNER),
- NS_VALSTR_STRUCT(CAP_SYS_MODULE),
- NS_VALSTR_STRUCT(CAP_SYS_RAWIO),
- NS_VALSTR_STRUCT(CAP_SYS_CHROOT),
- NS_VALSTR_STRUCT(CAP_SYS_PTRACE),
- NS_VALSTR_STRUCT(CAP_SYS_PACCT),
- NS_VALSTR_STRUCT(CAP_SYS_ADMIN),
- NS_VALSTR_STRUCT(CAP_SYS_BOOT),
- NS_VALSTR_STRUCT(CAP_SYS_NICE),
- NS_VALSTR_STRUCT(CAP_SYS_RESOURCE),
- NS_VALSTR_STRUCT(CAP_SYS_TIME),
- NS_VALSTR_STRUCT(CAP_SYS_TTY_CONFIG),
- NS_VALSTR_STRUCT(CAP_MKNOD),
- NS_VALSTR_STRUCT(CAP_LEASE),
- NS_VALSTR_STRUCT(CAP_AUDIT_WRITE),
- NS_VALSTR_STRUCT(CAP_AUDIT_CONTROL),
- NS_VALSTR_STRUCT(CAP_SETFCAP),
- NS_VALSTR_STRUCT(CAP_MAC_OVERRIDE),
- NS_VALSTR_STRUCT(CAP_MAC_ADMIN),
- NS_VALSTR_STRUCT(CAP_SYSLOG),
- NS_VALSTR_STRUCT(CAP_WAKE_ALARM),
- NS_VALSTR_STRUCT(CAP_BLOCK_SUSPEND),
+ NS_VALSTR_STRUCT(CAP_CHOWN),
+ NS_VALSTR_STRUCT(CAP_DAC_OVERRIDE),
+ NS_VALSTR_STRUCT(CAP_DAC_READ_SEARCH),
+ NS_VALSTR_STRUCT(CAP_FOWNER),
+ NS_VALSTR_STRUCT(CAP_FSETID),
+ NS_VALSTR_STRUCT(CAP_KILL),
+ NS_VALSTR_STRUCT(CAP_SETGID),
+ NS_VALSTR_STRUCT(CAP_SETUID),
+ NS_VALSTR_STRUCT(CAP_SETPCAP),
+ NS_VALSTR_STRUCT(CAP_LINUX_IMMUTABLE),
+ NS_VALSTR_STRUCT(CAP_NET_BIND_SERVICE),
+ NS_VALSTR_STRUCT(CAP_NET_BROADCAST),
+ NS_VALSTR_STRUCT(CAP_NET_ADMIN),
+ NS_VALSTR_STRUCT(CAP_NET_RAW),
+ NS_VALSTR_STRUCT(CAP_IPC_LOCK),
+ NS_VALSTR_STRUCT(CAP_IPC_OWNER),
+ NS_VALSTR_STRUCT(CAP_SYS_MODULE),
+ NS_VALSTR_STRUCT(CAP_SYS_RAWIO),
+ NS_VALSTR_STRUCT(CAP_SYS_CHROOT),
+ NS_VALSTR_STRUCT(CAP_SYS_PTRACE),
+ NS_VALSTR_STRUCT(CAP_SYS_PACCT),
+ NS_VALSTR_STRUCT(CAP_SYS_ADMIN),
+ NS_VALSTR_STRUCT(CAP_SYS_BOOT),
+ NS_VALSTR_STRUCT(CAP_SYS_NICE),
+ NS_VALSTR_STRUCT(CAP_SYS_RESOURCE),
+ NS_VALSTR_STRUCT(CAP_SYS_TIME),
+ NS_VALSTR_STRUCT(CAP_SYS_TTY_CONFIG),
+ NS_VALSTR_STRUCT(CAP_MKNOD),
+ NS_VALSTR_STRUCT(CAP_LEASE),
+ NS_VALSTR_STRUCT(CAP_AUDIT_WRITE),
+ NS_VALSTR_STRUCT(CAP_AUDIT_CONTROL),
+ NS_VALSTR_STRUCT(CAP_SETFCAP),
+ NS_VALSTR_STRUCT(CAP_MAC_OVERRIDE),
+ NS_VALSTR_STRUCT(CAP_MAC_ADMIN),
+ NS_VALSTR_STRUCT(CAP_SYSLOG),
+ NS_VALSTR_STRUCT(CAP_WAKE_ALARM),
+ NS_VALSTR_STRUCT(CAP_BLOCK_SUSPEND),
#if defined(CAP_AUDIT_READ)
- NS_VALSTR_STRUCT(CAP_AUDIT_READ),
+ NS_VALSTR_STRUCT(CAP_AUDIT_READ),
#endif /* defined(CAP_AUDIT_READ) */
};
-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) {
return capNames[i].val;
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++) {
if (val == capNames[i].val) {
return capsStr;
}
-static cap_user_data_t capsGet()
-{
+static cap_user_data_t capsGet() {
static __thread struct __user_cap_data_struct cap_data[_LINUX_CAPABILITY_U32S_3];
const struct __user_cap_header_struct cap_hdr = {
- .version = _LINUX_CAPABILITY_VERSION_3,
- .pid = 0,
+ .version = _LINUX_CAPABILITY_VERSION_3,
+ .pid = 0,
};
if (syscall(__NR_capget, &cap_hdr, &cap_data) == -1) {
PLOG_W("capget() failed");
return cap_data;
}
-static bool capsSet(const cap_user_data_t cap_data)
-{
+static bool capsSet(const cap_user_data_t cap_data) {
const struct __user_cap_header_struct cap_hdr = {
- .version = _LINUX_CAPABILITY_VERSION_3,
- .pid = 0,
+ .version = _LINUX_CAPABILITY_VERSION_3,
+ .pid = 0,
};
if (syscall(__NR_capset, &cap_hdr, cap_data) == -1) {
PLOG_W("capset() failed");
return true;
}
-static void capsClearInheritable(cap_user_data_t cap_data)
-{
+static void capsClearInheritable(cap_user_data_t cap_data) {
for (size_t i = 0; i < _LINUX_CAPABILITY_U32S_3; i++) {
cap_data[i].inheritable = 0U;
}
}
-static bool capsGetPermitted(cap_user_data_t cap_data, unsigned int cap)
-{
+static bool capsGetPermitted(cap_user_data_t cap_data, unsigned int cap) {
size_t off_byte = cap / (sizeof(cap_data->permitted) * 8);
size_t off_bit = cap % (sizeof(cap_data->permitted) * 8);
return cap_data[off_byte].permitted & (1U << off_bit);
}
-static bool capsGetEffective(cap_user_data_t cap_data, unsigned int cap)
-{
+static bool capsGetEffective(cap_user_data_t cap_data, unsigned int cap) {
size_t off_byte = cap / (sizeof(cap_data->effective) * 8);
size_t off_bit = cap % (sizeof(cap_data->effective) * 8);
return cap_data[off_byte].effective & (1U << off_bit);
}
-static bool capsGetInheritable(cap_user_data_t cap_data, unsigned int cap)
-{
+static bool capsGetInheritable(cap_user_data_t cap_data, unsigned int cap) {
size_t off_byte = cap / (sizeof(cap_data->inheritable) * 8);
size_t off_bit = cap % (sizeof(cap_data->inheritable) * 8);
return cap_data[off_byte].inheritable & (1U << off_bit);
}
-static void capsSetInheritable(cap_user_data_t cap_data, unsigned int cap)
-{
+static void capsSetInheritable(cap_user_data_t cap_data, unsigned int cap) {
size_t off_byte = cap / (sizeof(cap_data->inheritable) * 8);
size_t off_bit = cap % (sizeof(cap_data->inheritable) * 8);
cap_data[off_byte].inheritable |= (1U << off_bit);
#define PR_CAP_AMBIENT_RAISE 2
#define PR_CAP_AMBIENT_CLEAR_ALL 4
#endif /* !defined(PR_CAP_AMBIENT) */
-static bool CapsInitNsKeepCaps(cap_user_data_t cap_data)
-{
+static bool CapsInitNsKeepCaps(cap_user_data_t cap_data) {
char dbgmsg[4096];
/* Copy all permitted caps to the inheritable set */
continue;
}
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, (unsigned long)capNames[i].val, 0UL,
- 0UL)
- == -1) {
+ 0UL) == -1) {
PLOG_W("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, %s)", capNames[i].name);
} else {
utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
return true;
}
-bool capsInitNs(struct nsjconf_t* nsjconf)
-{
+bool capsInitNs(struct nsjconf_t* nsjconf) {
char dbgmsg[4096];
struct ints_t* p;
/* 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));
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;
}
/* 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));
} else {
#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) {
return true;
}
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 == 0U) {
return true;
}
return true;
}
-static bool cgroupInitNsFromParentNetCls(struct nsjconf_t* nsjconf, pid_t pid)
-{
+static bool cgroupInitNsFromParentNetCls(struct nsjconf_t* nsjconf, pid_t pid) {
if (nsjconf->cgroup_net_cls_classid == 0U) {
return true;
}
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;
}
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) {
return;
}
return;
}
-void cgroupFinishFromParentPids(struct nsjconf_t* nsjconf, pid_t pid)
-{
+void cgroupFinishFromParentPids(struct nsjconf_t* nsjconf, pid_t pid) {
if (nsjconf->cgroup_pids_max == 0U) {
return;
}
return;
}
-void cgroupFinishFromParentNetCls(struct nsjconf_t* nsjconf, pid_t pid)
-{
+void cgroupFinishFromParentNetCls(struct nsjconf_t* nsjconf, pid_t pid) {
if (nsjconf->cgroup_net_cls_classid == 0U) {
return;
}
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);
cgroupFinishFromParentNetCls(nsjconf, pid);
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" : "");
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:");
for (size_t i = 0; i < ARRAYSIZE(custom_opts); i++) {
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:
LOG_I("Mode: LISTEN_TCP");
break;
}
- LOG_I("Jail parameters: hostname:'%s', chroot:'%s', process:'%s', "
- "bind:[%s]:%d, "
- "max_conns_per_ip:%u, time_limit:%ld, personality:%#lx, daemonize:%s, "
- "clone_newnet:%s, clone_newuser:%s, clone_newns:%s, clone_newpid:%s, "
- "clone_newipc:%s, clonew_newuts:%s, clone_newcgroup:%s, keep_caps:%s, "
- "tmpfs_size:%zu, disable_no_new_privs:%s, max_cpus:%zu",
+ LOG_I(
+ "Jail parameters: hostname:'%s', chroot:'%s', process:'%s', "
+ "bind:[%s]:%d, "
+ "max_conns_per_ip:%u, time_limit:%ld, personality:%#lx, daemonize:%s, "
+ "clone_newnet:%s, clone_newuser:%s, clone_newns:%s, clone_newpid:%s, "
+ "clone_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),
{
struct mounts_t* p;
- TAILQ_FOREACH(p, &nsjconf->mountpts, pointers)
- {
+ TAILQ_FOREACH(p, &nsjconf->mountpts, pointers) {
LOG_I("%s: %s", p->isSymlink ? "Symlink" : "Mount point",
mountDescribeMountPt(p));
}
}
{
struct idmap_t* p;
- TAILQ_FOREACH(p, &nsjconf->uids, pointers)
- {
+ 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");
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");
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");
}
}
}
}
-uint64_t cmdlineParseRLimit(int res, const char* optarg, unsigned long mul)
-{
+uint64_t cmdlineParseRLimit(int res, const char* optarg, unsigned long mul) {
if (strcasecmp(optarg, "inf") == 0) {
return RLIM64_INFINITY;
}
return cur.rlim_max;
}
if (utilIsANumber(optarg) == false) {
- LOG_F("RLIMIT %d needs a numeric or 'max'/'hard'/'def'/'soft'/'inf' value ('%s' "
- "provided)",
+ LOG_F(
+ "RLIMIT %d needs a numeric or 'max'/'hard'/'def'/'soft'/'inf' value ('%s' "
+ "provided)",
res, optarg);
}
uint64_t val = strtoull(optarg, NULL, 0) * 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;
}
}
}
-bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf)
-{
+bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf) {
(*nsjconf) = (const struct nsjconf_t){
- .exec_file = NULL,
- .use_execveat = false,
- .exec_fd = -1,
- .argv = NULL,
- .hostname = "NSJAIL",
- .cwd = "/",
- .chroot = NULL,
- .port = 0,
- .bindhost = "::",
- .log_fd = STDERR_FILENO,
- .logfile = NULL,
- .loglevel = INFO,
- .daemonize = false,
- .tlimit = 0,
- .max_cpus = 0,
- .keep_caps = false,
- .disable_no_new_privs = false,
- .rl_as = 512 * (1024 * 1024),
- .rl_core = 0,
- .rl_cpu = 600,
- .rl_fsize = 1 * (1024 * 1024),
- .rl_nofile = 32,
- .rl_nproc = cmdlineParseRLimit(RLIMIT_NPROC, "soft", 1),
- .rl_stack = cmdlineParseRLimit(RLIMIT_STACK, "soft", 1),
- .personality = 0,
- .clone_newnet = true,
- .clone_newuser = true,
- .clone_newns = true,
- .clone_newpid = true,
- .clone_newipc = true,
- .clone_newuts = true,
- .clone_newcgroup = false,
- .mode = MODE_STANDALONE_ONCE,
- .is_root_rw = false,
- .is_silent = false,
- .skip_setsid = false,
- .max_conns_per_ip = 0,
- .tmpfs_size = 4 * (1024 * 1024),
- .mount_proc = true,
- .proc_path = "/proc",
- .is_proc_rw = false,
- .cgroup_mem_mount = "/sys/fs/cgroup/memory",
- .cgroup_mem_parent = "NSJAIL",
- .cgroup_mem_max = (size_t)0,
- .cgroup_pids_mount = "/sys/fs/cgroup/pids",
- .cgroup_pids_parent = "NSJAIL",
- .cgroup_pids_max = (unsigned int)0,
- .cgroup_net_cls_mount = "/sys/fs/cgroup/net_cls",
- .cgroup_net_cls_parent = "NSJAIL",
- .cgroup_net_cls_classid = (unsigned int)0,
- .iface_no_lo = false,
- .iface_vs = NULL,
- .iface_vs_ip = "0.0.0.0",
- .iface_vs_nm = "255.255.255.0",
- .iface_vs_gw = "0.0.0.0",
- .kafel_file = NULL,
- .kafel_string = NULL,
- .orig_uid = getuid(),
- .num_cpus = sysconf(_SC_NPROCESSORS_ONLN),
+ .exec_file = NULL,
+ .use_execveat = false,
+ .exec_fd = -1,
+ .argv = NULL,
+ .hostname = "NSJAIL",
+ .cwd = "/",
+ .chroot = NULL,
+ .port = 0,
+ .bindhost = "::",
+ .log_fd = STDERR_FILENO,
+ .logfile = NULL,
+ .loglevel = INFO,
+ .daemonize = false,
+ .tlimit = 0,
+ .max_cpus = 0,
+ .keep_caps = false,
+ .disable_no_new_privs = false,
+ .rl_as = 512 * (1024 * 1024),
+ .rl_core = 0,
+ .rl_cpu = 600,
+ .rl_fsize = 1 * (1024 * 1024),
+ .rl_nofile = 32,
+ .rl_nproc = cmdlineParseRLimit(RLIMIT_NPROC, "soft", 1),
+ .rl_stack = cmdlineParseRLimit(RLIMIT_STACK, "soft", 1),
+ .personality = 0,
+ .clone_newnet = true,
+ .clone_newuser = true,
+ .clone_newns = true,
+ .clone_newpid = true,
+ .clone_newipc = true,
+ .clone_newuts = true,
+ .clone_newcgroup = false,
+ .mode = MODE_STANDALONE_ONCE,
+ .is_root_rw = false,
+ .is_silent = false,
+ .skip_setsid = false,
+ .max_conns_per_ip = 0,
+ .tmpfs_size = 4 * (1024 * 1024),
+ .mount_proc = true,
+ .proc_path = "/proc",
+ .is_proc_rw = false,
+ .cgroup_mem_mount = "/sys/fs/cgroup/memory",
+ .cgroup_mem_parent = "NSJAIL",
+ .cgroup_mem_max = (size_t)0,
+ .cgroup_pids_mount = "/sys/fs/cgroup/pids",
+ .cgroup_pids_parent = "NSJAIL",
+ .cgroup_pids_max = (unsigned int)0,
+ .cgroup_net_cls_mount = "/sys/fs/cgroup/net_cls",
+ .cgroup_net_cls_parent = "NSJAIL",
+ .cgroup_net_cls_classid = (unsigned int)0,
+ .iface_no_lo = false,
+ .iface_vs = NULL,
+ .iface_vs_ip = "0.0.0.0",
+ .iface_vs_nm = "255.255.255.0",
+ .iface_vs_gw = "0.0.0.0",
+ .kafel_file = NULL,
+ .kafel_string = NULL,
+ .orig_uid = getuid(),
+ .num_cpus = sysconf(_SC_NPROCESSORS_ONLN),
};
TAILQ_INIT(&nsjconf->pids);
opts[ARRAYSIZE(custom_opts) + i] = deprecated_opts[i].opt;
}
// Last, NULL option as a terminator.
- struct option terminator = { NULL, 0, NULL, 0 };
+ struct option terminator = {NULL, 0, NULL, 0};
memcpy(&opts[options_length - 1].name, &terminator, sizeof(terminator));
int opt_index = 0;
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);
+ 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) {
+ false /* is_newidmap */) == false) {
return false;
}
} break;
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);
+ 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) {
+ false /* is_newidmap */) == false) {
return false;
}
} break;
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);
+ 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) {
+ true /* is_newidmap */) == false) {
return false;
}
} break;
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);
+ 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) {
+ true /* is_newidmap */) == false) {
return false;
}
} break;
if (nsjconf->use_execveat) {
#if !defined(__NR_execveat)
- LOG_E("Your nsjail is compiled without support for the execveat() syscall, yet you "
- "specified the --execute_fd flag");
+ LOG_E(
+ "Your nsjail is compiled without support for the execveat() syscall, yet you "
+ "specified the --execute_fd flag");
return false;
#endif /* !defined(__NR_execveat) */
- if ((nsjconf->exec_fd = open(nsjconf->exec_file, O_RDONLY | O_PATH | O_CLOEXEC))
- == -1) {
+ if ((nsjconf->exec_fd = open(nsjconf->exec_file, O_RDONLY | O_PATH | O_CLOEXEC)) ==
+ -1) {
PLOG_W("Couldn't open '%s' file", nsjconf->exec_file);
return false;
}
(*dfunc) ();
}
-#define defer \
- void (^_STRMERGE(__defer_f_, __COUNTER__))(void) \
- __attribute__((cleanup(__clang_cleanup_func))) __attribute__((unused)) \
- = ^
+#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)); \
+#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
-#define NS_VALSTR_STRUCT(x) \
- { \
- x, #x \
- }
+#define NS_VALSTR_STRUCT(x) \
+ { x, #x }
#endif /* NS_COMMON_H */
#include "util.h"
}
-#include <fstream>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/text_format.h>
+#include <fstream>
#include <string>
#include <vector>
#define DUP_IF_SET(njc, val) (njc.has_##val() ? njc.val().c_str() : NULL)
static __rlim64_t configRLimit(
- int res, const nsjail::RLimit& rl, const uint64_t val, unsigned long mul = 1UL)
-{
+ int res, const nsjail::RLimit& rl, const uint64_t val, unsigned long mul = 1UL) {
if (rl == nsjail::RLimit::VALUE) {
return (val * mul);
}
abort();
}
-static bool configParseInternal(struct nsjconf_t* nsjconf, const nsjail::NsJailConfig& njc)
-{
+static bool configParseInternal(struct nsjconf_t* nsjconf, const nsjail::NsJailConfig& njc) {
switch (njc.mode()) {
case nsjail::Mode::LISTEN:
nsjconf->mode = MODE_LISTEN_TCP;
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)));
+ 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)));
+ 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;
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)));
+ 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->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_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_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);
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) {
+ 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) {
+ true /* is_gid */, njc.gidmap(i).use_newidmap()) == false) {
return false;
}
}
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;
+ ? 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;
+ ? 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 | MS_PRIVATE) : 0;
}
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) {
+ 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) {
+ 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;
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->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();
}
static void LogHandler(
- google::protobuf::LogLevel level, const char* filename, int line, const std::string& message)
-{
+ google::protobuf::LogLevel level, const char* filename, int line, const std::string& message) {
LOG_W("config.cc: '%s'", message.c_str());
}
-extern "C" bool configParse(struct nsjconf_t* nsjconf, const char* file)
-{
+extern "C" bool configParse(struct nsjconf_t* nsjconf, const char* file) {
LOG_I("Parsing configuration from '%s'", file);
int fd = open(file, O_RDONLY);
bool configParse(struct nsjconf_t* nsjconf, const char* file);
#ifdef __cplusplus
-} // extern "C"
+} // extern "C"
#endif
#endif /* NS_CONFIG_H */
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
#endif
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)");
return false;
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;
if (setrlimit64(RLIMIT_AS, &rl) == -1) {
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)
- {
+ TAILQ_FOREACH(p, &nsjconf->open_fds, pointers) {
if (p->val == fd) {
return true;
}
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
* (e.g. 32), which could be smaller than a maximum assigned number to file-descriptors
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 true;
}
-static bool containMakeFdsCOE(struct nsjconf_t* nsjconf)
-{
+static bool containMakeFdsCOE(struct nsjconf_t* nsjconf) {
if (containMakeFdsCOEProc(nsjconf)) {
return true;
}
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) {
return true;
return true;
}
-bool containContain(struct nsjconf_t* nsjconf)
-{
+bool containContain(struct nsjconf_t* nsjconf) {
if (containUserNs(nsjconf) == false) {
return false;
}
#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'",
}
}
-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;
* 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) {
close(log_fd);
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) {
+ 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;
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;
}
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);
#define MS_LAZYTIME (1 << 25)
#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';
const uintptr_t flag;
const char* const name;
} const mountFlags[] = {
- NS_VALSTR_STRUCT(MS_RDONLY),
- NS_VALSTR_STRUCT(MS_NOSUID),
- NS_VALSTR_STRUCT(MS_NODEV),
- NS_VALSTR_STRUCT(MS_NOEXEC),
- NS_VALSTR_STRUCT(MS_SYNCHRONOUS),
- NS_VALSTR_STRUCT(MS_REMOUNT),
- NS_VALSTR_STRUCT(MS_MANDLOCK),
- NS_VALSTR_STRUCT(MS_DIRSYNC),
- NS_VALSTR_STRUCT(MS_NOATIME),
- NS_VALSTR_STRUCT(MS_NODIRATIME),
- NS_VALSTR_STRUCT(MS_BIND),
- NS_VALSTR_STRUCT(MS_MOVE),
- NS_VALSTR_STRUCT(MS_REC),
- NS_VALSTR_STRUCT(MS_SILENT),
- NS_VALSTR_STRUCT(MS_POSIXACL),
- NS_VALSTR_STRUCT(MS_UNBINDABLE),
- NS_VALSTR_STRUCT(MS_PRIVATE),
- NS_VALSTR_STRUCT(MS_SLAVE),
- NS_VALSTR_STRUCT(MS_SHARED),
- NS_VALSTR_STRUCT(MS_RELATIME),
- NS_VALSTR_STRUCT(MS_KERNMOUNT),
- NS_VALSTR_STRUCT(MS_I_VERSION),
- NS_VALSTR_STRUCT(MS_STRICTATIME),
- NS_VALSTR_STRUCT(MS_LAZYTIME),
+ NS_VALSTR_STRUCT(MS_RDONLY),
+ NS_VALSTR_STRUCT(MS_NOSUID),
+ NS_VALSTR_STRUCT(MS_NODEV),
+ NS_VALSTR_STRUCT(MS_NOEXEC),
+ NS_VALSTR_STRUCT(MS_SYNCHRONOUS),
+ NS_VALSTR_STRUCT(MS_REMOUNT),
+ NS_VALSTR_STRUCT(MS_MANDLOCK),
+ NS_VALSTR_STRUCT(MS_DIRSYNC),
+ NS_VALSTR_STRUCT(MS_NOATIME),
+ NS_VALSTR_STRUCT(MS_NODIRATIME),
+ NS_VALSTR_STRUCT(MS_BIND),
+ NS_VALSTR_STRUCT(MS_MOVE),
+ NS_VALSTR_STRUCT(MS_REC),
+ NS_VALSTR_STRUCT(MS_SILENT),
+ NS_VALSTR_STRUCT(MS_POSIXACL),
+ NS_VALSTR_STRUCT(MS_UNBINDABLE),
+ NS_VALSTR_STRUCT(MS_PRIVATE),
+ NS_VALSTR_STRUCT(MS_SLAVE),
+ NS_VALSTR_STRUCT(MS_SHARED),
+ NS_VALSTR_STRUCT(MS_RELATIME),
+ NS_VALSTR_STRUCT(MS_KERNMOUNT),
+ NS_VALSTR_STRUCT(MS_I_VERSION),
+ NS_VALSTR_STRUCT(MS_STRICTATIME),
+ NS_VALSTR_STRUCT(MS_LAZYTIME),
};
for (size_t i = 0; i < ARRAYSIZE(mountFlags); i++) {
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)
*/
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);
unsigned long flags = mpt->flags & ~(MS_RDONLY);
if (mount(srcpath, dst, mpt->fs_type, flags, mpt->options) == -1) {
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",
+ 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);
} else {
PLOG_W("mount('%s') src:'%s' dst:'%s' failed", mountDescribeMountPt(mpt),
return true;
}
-static bool mountRemountRO(struct mounts_t* mpt)
-{
+static bool mountRemountRO(struct mounts_t* mpt) {
if (!mpt->mounted) {
return true;
}
return true;
}
-static bool mountMkdirAndTest(const char* dir)
-{
+static bool mountMkdirAndTest(const char* dir) {
if (mkdir(dir, 0755) == -1 && errno != EEXIST) {
PLOG_D("Couldn't create '%s' directory", dir);
return false;
return true;
}
-static bool mountGetDir(struct nsjconf_t* nsjconf, char* dir, const char* name)
-{
+static bool mountGetDir(struct nsjconf_t* nsjconf, char* dir, const char* name) {
snprintf(dir, PATH_MAX, "/run/user/%u/nsjail.%s", nsjconf->orig_uid, name);
if (mountMkdirAndTest(dir)) {
return true;
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
* use --chroot in this case
*/
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) {
}
struct mounts_t* p;
- TAILQ_FOREACH(p, &nsjconf->mountpts, pointers)
- {
+ TAILQ_FOREACH(p, &nsjconf->mountpts, pointers) {
if (mountMount(p, destdir, tmpdir) == false && p->mandatory) {
return false;
}
return false;
}
- TAILQ_FOREACH(p, &nsjconf->mountpts, pointers)
- {
+ TAILQ_FOREACH(p, &nsjconf->mountpts, pointers) {
if (mountRemountRO(p) == false && p->mandatory) {
return false;
}
* 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);
}
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)
-{
+ bool is_symlink) {
struct mounts_t* p = utilCalloc(sizeof(struct mounts_t));
if (src_env) {
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 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);
}
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 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);
}
-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),
#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;
}
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;
}
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, "netns", pid_str, "type", "macvlan", "mode", "bridge", NULL };
+ 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) {
LOG_E("Couldn't create MACVTAP interface for '%s'", nsjconf->iface_vs);
return false;
return true;
}
-#endif // defined(NSJAIL_NL3_WITH_MACVLAN)
+#endif // defined(NSJAIL_NL3_WITH_MACVLAN)
-static bool netIsSocket(int fd)
-{
+static bool netIsSocket(int fd) {
int optval;
socklen_t optlen = sizeof(optval);
int ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, &optval, &optlen);
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) {
return true;
unsigned int cnt = 0;
struct pids_t* p;
- TAILQ_FOREACH(p, &nsjconf->pids, pointers)
- {
+ 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))
- == 0) {
+ sizeof(*p->remote_addr.sin6_addr.s6_addr)) == 0) {
cnt++;
}
}
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>",
+ LOG_F(
+ "TCP port %d out of bounds (0 <= port <= 65535), specify one with --port "
+ "<port>",
port);
}
return -1;
}
struct sockaddr_in6 addr = {
- .sin6_family = AF_INET6,
- .sin6_port = htons(port),
- .sin6_flowinfo = 0,
- .sin6_addr = in6a,
- .sin6_scope_id = 0,
+ .sin6_family = AF_INET6,
+ .sin6_port = htons(port),
+ .sin6_flowinfo = 0,
+ .sin6_addr = in6a,
+ .sin6_scope_id = 0,
};
if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
close(sockfd);
return sockfd;
}
-int netAcceptConn(int listenfd)
-{
+int netAcceptConn(int listenfd) {
struct sockaddr_in6 cli_addr;
socklen_t socklen = sizeof(cli_addr);
int connfd = accept(listenfd, (struct sockaddr*)&cli_addr, &socklen);
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]");
return;
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) {
PLOG_E("socket(AF_INET, SOCK_STREAM, IPPROTO_IP)");
return true;
}
-static bool netConfigureVs(struct nsjconf_t* nsjconf)
-{
+static bool netConfigureVs(struct nsjconf_t* nsjconf) {
struct ifreq ifr;
memset(&ifr, '\0', sizeof(ifr));
snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", IFACE_NAME);
return true;
}
-bool netInitNsFromChild(struct nsjconf_t* nsjconf)
-{
+bool netInitNsFromChild(struct nsjconf_t* nsjconf) {
if (nsjconf->clone_newnet == false) {
return true;
}
static __thread int nsjailSigFatal = 0;
static __thread bool nsjailShowProc = false;
-static void nsjailSig(int sig)
-{
+static void nsjailSig(int sig) {
if (sig == SIGALRM) {
return;
}
nsjailSigFatal = sig;
}
-static bool nsjailSetSigHandler(int sig)
-{
+static bool nsjailSetSigHandler(int sig) {
LOG_D("Setting sighandler for signal %s (%d)", utilSigName(sig), sig);
sigset_t smask;
sigemptyset(&smask);
struct sigaction sa = {
- .sa_handler = nsjailSig,
- .sa_mask = smask,
- .sa_flags = 0,
- .sa_restorer = NULL,
+ .sa_handler = nsjailSig,
+ .sa_mask = smask,
+ .sa_flags = 0,
+ .sa_restorer = NULL,
};
if (sigaction(sig, &sa, NULL) == -1) {
PLOG_E("sigaction(%d)", sig);
return true;
}
-static bool nsjailSetSigHandlers(void)
-{
+static bool nsjailSetSigHandlers(void) {
for (size_t i = 0; i < ARRAYSIZE(nssigs); i++) {
if (!nsjailSetSigHandler(nssigs[i])) {
return false;
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 = {
+ .it_value =
+ {
.tv_sec = 1,
.tv_usec = 0,
},
- .it_interval = {
+ .it_interval =
+ {
.tv_sec = 1,
.tv_usec = 0,
},
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) {
return;
}
}
-static int nsjailStandaloneMode(struct nsjconf_t* nsjconf)
-{
+static int nsjailStandaloneMode(struct nsjconf_t* nsjconf) {
subprocRunChild(nsjconf, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO);
for (;;) {
int child_status = subprocReap(nsjconf);
// not reached
}
-int main(int argc, char* argv[])
-{
+int main(int argc, char* argv[]) {
struct nsjconf_t nsjconf;
if (!cmdlineParse(argc, argv, &nsjconf)) {
LOG_F("Couldn't parse cmdline options");
/*
* To satisfy requirement for BlocksRuntime in clang -fblocks
*/
-void* _NSConcreteStackBlock[32] = { 0 };
+void* _NSConcreteStackBlock[32] = {0};
#include <time.h>
static const int nssigs[] = {
- SIGINT,
- SIGQUIT,
- SIGUSR1,
- SIGALRM,
- SIGCHLD,
- SIGTERM,
+ SIGINT,
+ SIGQUIT,
+ SIGUSR1,
+ SIGALRM,
+ SIGCHLD,
+ SIGTERM,
};
struct pids_t {
#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;
}
/* Act sort-a like a init by reaping zombie processes */
struct sigaction sa = {
- .sa_handler = SIG_DFL,
- .sa_flags = SA_NOCLDWAIT | SA_NOCLDSTOP,
- .sa_restorer = NULL,
+ .sa_handler = SIG_DFL,
+ .sa_flags = SA_NOCLDWAIT | SA_NOCLDSTOP,
+ .sa_restorer = NULL,
};
sigemptyset(&sa.sa_mask);
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
#define PR_SET_NO_NEW_PRIVS 38
#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;
}
#define CLONE_NEWCGROUP 0x02000000
#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';
const uintptr_t flag;
const char* const name;
} const cloneFlags[] = {
- NS_VALSTR_STRUCT(CLONE_VM),
- NS_VALSTR_STRUCT(CLONE_FS),
- NS_VALSTR_STRUCT(CLONE_FILES),
- NS_VALSTR_STRUCT(CLONE_SIGHAND),
- NS_VALSTR_STRUCT(CLONE_PTRACE),
- NS_VALSTR_STRUCT(CLONE_VFORK),
- NS_VALSTR_STRUCT(CLONE_PARENT),
- NS_VALSTR_STRUCT(CLONE_THREAD),
- NS_VALSTR_STRUCT(CLONE_NEWNS),
- NS_VALSTR_STRUCT(CLONE_SYSVSEM),
- NS_VALSTR_STRUCT(CLONE_SETTLS),
- NS_VALSTR_STRUCT(CLONE_PARENT_SETTID),
- NS_VALSTR_STRUCT(CLONE_CHILD_CLEARTID),
- NS_VALSTR_STRUCT(CLONE_DETACHED),
- NS_VALSTR_STRUCT(CLONE_UNTRACED),
- NS_VALSTR_STRUCT(CLONE_CHILD_SETTID),
- NS_VALSTR_STRUCT(CLONE_NEWCGROUP),
- NS_VALSTR_STRUCT(CLONE_NEWUTS),
- NS_VALSTR_STRUCT(CLONE_NEWIPC),
- NS_VALSTR_STRUCT(CLONE_NEWUSER),
- NS_VALSTR_STRUCT(CLONE_NEWPID),
- NS_VALSTR_STRUCT(CLONE_NEWNET),
- NS_VALSTR_STRUCT(CLONE_IO),
+ NS_VALSTR_STRUCT(CLONE_VM),
+ NS_VALSTR_STRUCT(CLONE_FS),
+ NS_VALSTR_STRUCT(CLONE_FILES),
+ NS_VALSTR_STRUCT(CLONE_SIGHAND),
+ NS_VALSTR_STRUCT(CLONE_PTRACE),
+ NS_VALSTR_STRUCT(CLONE_VFORK),
+ NS_VALSTR_STRUCT(CLONE_PARENT),
+ NS_VALSTR_STRUCT(CLONE_THREAD),
+ NS_VALSTR_STRUCT(CLONE_NEWNS),
+ NS_VALSTR_STRUCT(CLONE_SYSVSEM),
+ NS_VALSTR_STRUCT(CLONE_SETTLS),
+ NS_VALSTR_STRUCT(CLONE_PARENT_SETTID),
+ NS_VALSTR_STRUCT(CLONE_CHILD_CLEARTID),
+ NS_VALSTR_STRUCT(CLONE_DETACHED),
+ NS_VALSTR_STRUCT(CLONE_UNTRACED),
+ NS_VALSTR_STRUCT(CLONE_CHILD_SETTID),
+ NS_VALSTR_STRUCT(CLONE_NEWCGROUP),
+ NS_VALSTR_STRUCT(CLONE_NEWUTS),
+ NS_VALSTR_STRUCT(CLONE_NEWIPC),
+ NS_VALSTR_STRUCT(CLONE_NEWUSER),
+ NS_VALSTR_STRUCT(CLONE_NEWPID),
+ NS_VALSTR_STRUCT(CLONE_NEWNET),
+ NS_VALSTR_STRUCT(CLONE_IO),
};
for (size_t i = 0; i < ARRAYSIZE(cloneFlags); i++) {
}
/* Reset the execution environment for the new process */
-static bool subprocReset(void)
-{
+static bool subprocReset(void) {
/* Set all previously changed signals to their default behavior */
for (size_t i = 0; i < ARRAYSIZE(nssigs); i++) {
if (signal(nssigs[i], SIG_DFL) == SIG_ERR) {
return true;
}
-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);
}
#if defined(__NR_execveat)
syscall(__NR_execveat, (uintptr_t)nsjconf->exec_fd, "",
(char* const*)&nsjconf->argv[0], environ, (uintptr_t)AT_EMPTY_PATH);
-#else /* defined(__NR_execveat) */
+#else /* defined(__NR_execveat) */
LOG_F("Your system doesn't support execveat() syscall");
#endif /* defined(__NR_execveat) */
} else {
_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));
p->pid = pid;
p->start = time(NULL);
(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)
- {
+ 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));
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) { 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)
- {
+ 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,
}
}
-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)
- {
+ TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
if (p->pid == pid) {
return p;
}
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);
}
}
-int subprocReap(struct nsjconf_t* nsjconf)
-{
+int subprocReap(struct nsjconf_t* nsjconf) {
int status;
int rv = 0;
siginfo_t si;
time_t now = time(NULL);
struct pids_t* p;
- TAILQ_FOREACH(p, &nsjconf->pids, pointers)
- {
+ TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
if (nsjconf->tlimit == 0) {
continue;
}
return rv;
}
-void subprocKillAll(struct nsjconf_t* nsjconf)
-{
+void subprocKillAll(struct nsjconf_t* nsjconf) {
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);
return false;
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;
}
/* 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;
}
* update the internal PID/TID caches, what can lead to invalid values being returned by getpid()
* or incorrect PID/TIDs used in raise()/abort() functions
*/
-pid_t subprocClone(uintptr_t flags)
-{
+pid_t subprocClone(uintptr_t flags) {
if (flags & CLONE_VM) {
LOG_E("Cannot use clone(flags & CLONE_VM)");
return -1;
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;
}
}
close(child_fd);
if (pid == -1) {
- 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",
+ 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));
close(parent_fd);
return;
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;
int sv[2];
#include "subproc.h"
#include "util.h"
-static bool userSetResGid(gid_t gid)
-{
+static bool userSetResGid(gid_t gid) {
LOG_D("setresgid(%d)", gid);
#if defined(__NR_setresgid32)
if (syscall(__NR_setresgid32, (uintptr_t)gid, (uintptr_t)gid, (uintptr_t)gid) == -1) {
PLOG_W("setresgid32(%d)", (int)gid);
return false;
}
-#else /* defined(__NR_setresgid32) */
+#else /* defined(__NR_setresgid32) */
if (syscall(__NR_setresgid, (uintptr_t)gid, (uintptr_t)gid, (uintptr_t)gid) == -1) {
PLOG_W("setresgid(%d)", gid);
return false;
return true;
}
-static bool userSetResUid(uid_t uid)
-{
+static bool userSetResUid(uid_t uid) {
LOG_D("setresuid(%d)", uid);
#if defined(__NR_setresuid32)
if (syscall(__NR_setresuid32, (uintptr_t)uid, (uintptr_t)uid, (uintptr_t)uid) == -1) {
PLOG_W("setresuid32(%d)", (int)uid);
return false;
}
-#else /* defined(__NR_setresuid32) */
+#else /* defined(__NR_setresuid32) */
if (syscall(__NR_setresuid, (uintptr_t)uid, (uintptr_t)uid, (uintptr_t)uid) == -1) {
PLOG_W("setresuid(%d)", uid);
return false;
return true;
}
-static bool userSetGroups(pid_t pid)
-{
+static bool userSetGroups(pid_t pid) {
/*
* No need to write 'deny' to /proc/pid/setgroups if our euid==0, as writing to
* uid_map/gid_map will succeed anyway
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' };
+ char map[4096] = {[0] = '\0'};
struct idmap_t* p;
- TAILQ_FOREACH(p, &nsjconf->uids, pointers)
- {
+ TAILQ_FOREACH(p, &nsjconf->uids, pointers) {
if (p->is_newidmap) {
continue;
}
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' };
+ char map[4096] = {[0] = '\0'};
struct idmap_t* p;
- TAILQ_FOREACH(p, &nsjconf->gids, pointers)
- {
+ TAILQ_FOREACH(p, &nsjconf->gids, pointers) {
if (p->is_newidmap) {
continue;
}
}
/* 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) {
size_t idx = 0;
const char* argv[1024];
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;
}
}
/* 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) {
size_t idx = 0;
const char* argv[1024];
bool use = false;
struct idmap_t* p;
- TAILQ_FOREACH(p, &nsjconf->uids, pointers)
- {
+ TAILQ_FOREACH(p, &nsjconf->uids, pointers) {
if (p->is_newidmap == false) {
continue;
}
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;
}
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;
}
return true;
}
-bool userInitNsFromChild(struct nsjconf_t* nsjconf)
-{
+bool userInitNsFromChild(struct nsjconf_t* nsjconf) {
/*
* Best effort because of /proc/self/setgroups
*/
* 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;
}
return true;
}
-static uid_t cmdParseUid(const char* id)
-{
+static uid_t cmdParseUid(const char* id) {
if (id == NULL || strlen(id) == 0) {
return getuid();
}
return -1;
}
-static gid_t cmdParseGid(const char* id)
-{
+static gid_t cmdParseGid(const char* id) {
if (id == NULL || strlen(id) == 0) {
return getgid();
}
}
bool userParseId(struct nsjconf_t* nsjconf, const char* i_id, const char* o_id, size_t cnt,
- bool is_gid, bool is_newidmap)
-{
+ bool is_gid, bool is_newidmap) {
uid_t inside_id;
uid_t outside_id;
#include "common.h"
#include "log.h"
-void* utilMalloc(size_t sz)
-{
+void* utilMalloc(size_t 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);
memset(r, '\0', sz);
return r;
}
-char* utilStrDup(const char* str)
-{
+char* utilStrDup(const char* str) {
if (str == NULL) {
return NULL;
}
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;
}
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;
size_t readSz = 0;
while (readSz < len) {
ssize_t sz = read(fd, &charbuf[readSz], len - readSz);
- if (sz < 0 && errno == EINTR)
- continue;
+ if (sz < 0 && errno == EINTR) continue;
- if (sz <= 0)
- break;
+ if (sz <= 0) break;
readSz += sz;
}
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));
if (fd == -1) {
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;
size_t writtenSz = 0;
while (writtenSz < len) {
ssize_t sz = write(fd, &charbuf[writtenSz], len - writtenSz);
- if (sz < 0 && errno == EINTR)
- continue;
+ if (sz < 0 && errno == EINTR) continue;
- if (sz < 0)
- return false;
+ if (sz < 0) return false;
writtenSz += sz;
}
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));
if (fd == -1) {
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);
return false;
}
}
-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];
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') {
return false;
static const uint64_t a = 6364136223846793005ULL;
static const uint64_t c = 1442695040888963407ULL;
-static void utilRndInitThread(void)
-{
+static void utilRndInitThread(void) {
#if defined(__NR_getrandom)
if (syscall(__NR_getrandom, &rndX, sizeof(rndX), 0) == sizeof(rndX)) {
return;
close(fd);
}
-uint64_t utilRnd64(void)
-{
+uint64_t utilRnd64(void) {
pthread_once(&rndThreadOnce, utilRndInitThread);
rndX = a * rndX + c;
return rndX;
}
-const char* utilSigName(int signo)
-{
+const char* utilSigName(int signo) {
static __thread char sigstr[32];
sigstr[0] = '\0';
const int signo;
const char* const name;
} const sigNames[] = {
- NS_VALSTR_STRUCT(SIGINT),
- NS_VALSTR_STRUCT(SIGILL),
- NS_VALSTR_STRUCT(SIGABRT),
- NS_VALSTR_STRUCT(SIGFPE),
- NS_VALSTR_STRUCT(SIGSEGV),
- NS_VALSTR_STRUCT(SIGTERM),
- NS_VALSTR_STRUCT(SIGHUP),
- NS_VALSTR_STRUCT(SIGQUIT),
- NS_VALSTR_STRUCT(SIGTRAP),
- NS_VALSTR_STRUCT(SIGKILL),
- NS_VALSTR_STRUCT(SIGBUS),
- NS_VALSTR_STRUCT(SIGSYS),
- NS_VALSTR_STRUCT(SIGPIPE),
- NS_VALSTR_STRUCT(SIGALRM),
- NS_VALSTR_STRUCT(SIGURG),
- NS_VALSTR_STRUCT(SIGSTOP),
- NS_VALSTR_STRUCT(SIGTSTP),
- NS_VALSTR_STRUCT(SIGCONT),
- NS_VALSTR_STRUCT(SIGCHLD),
- NS_VALSTR_STRUCT(SIGTTIN),
- NS_VALSTR_STRUCT(SIGTTOU),
- NS_VALSTR_STRUCT(SIGPOLL),
- NS_VALSTR_STRUCT(SIGXCPU),
- NS_VALSTR_STRUCT(SIGXFSZ),
- NS_VALSTR_STRUCT(SIGVTALRM),
- NS_VALSTR_STRUCT(SIGPROF),
- NS_VALSTR_STRUCT(SIGUSR1),
- NS_VALSTR_STRUCT(SIGUSR2),
- NS_VALSTR_STRUCT(SIGWINCH),
+ NS_VALSTR_STRUCT(SIGINT),
+ NS_VALSTR_STRUCT(SIGILL),
+ NS_VALSTR_STRUCT(SIGABRT),
+ NS_VALSTR_STRUCT(SIGFPE),
+ NS_VALSTR_STRUCT(SIGSEGV),
+ NS_VALSTR_STRUCT(SIGTERM),
+ NS_VALSTR_STRUCT(SIGHUP),
+ NS_VALSTR_STRUCT(SIGQUIT),
+ NS_VALSTR_STRUCT(SIGTRAP),
+ NS_VALSTR_STRUCT(SIGKILL),
+ NS_VALSTR_STRUCT(SIGBUS),
+ NS_VALSTR_STRUCT(SIGSYS),
+ NS_VALSTR_STRUCT(SIGPIPE),
+ NS_VALSTR_STRUCT(SIGALRM),
+ NS_VALSTR_STRUCT(SIGURG),
+ NS_VALSTR_STRUCT(SIGSTOP),
+ NS_VALSTR_STRUCT(SIGTSTP),
+ NS_VALSTR_STRUCT(SIGCONT),
+ NS_VALSTR_STRUCT(SIGCHLD),
+ NS_VALSTR_STRUCT(SIGTTIN),
+ NS_VALSTR_STRUCT(SIGTTOU),
+ NS_VALSTR_STRUCT(SIGPOLL),
+ NS_VALSTR_STRUCT(SIGXCPU),
+ NS_VALSTR_STRUCT(SIGXFSZ),
+ NS_VALSTR_STRUCT(SIGVTALRM),
+ NS_VALSTR_STRUCT(SIGPROF),
+ NS_VALSTR_STRUCT(SIGUSR1),
+ NS_VALSTR_STRUCT(SIGUSR2),
+ NS_VALSTR_STRUCT(SIGWINCH),
};
for (size_t i = 0; i < ARRAYSIZE(sigNames); i++) {
}
static __thread char timestr[64];
-const char* utilTimeToStr(time_t t)
-{
+const char* utilTimeToStr(time_t t) {
struct tm utctime;
localtime_r(&t, &utctime);
if (strftime(timestr, sizeof(timestr) - 1, "%FT%T%z", &utctime) == 0) {
#include "log.h"
-bool utsInitNs(struct nsjconf_t* nsjconf)
-{
+bool utsInitNs(struct nsjconf_t* nsjconf) {
if (nsjconf->clone_newuts == false) {
return true;
}