BIN = nsjail
LIBS = kafel/libkafel.a
-SRCS_C = log.c util.c
-SRCS_CXX = caps.cc cgroup.cc cmdline.cc config.cc contain.cc cpu.cc mnt.cc net.cc nsjail.cc pid.cc sandbox.cc subproc.cc uts.cc user.cc
+SRCS_C = log.c
+SRCS_CXX = caps.cc cgroup.cc cmdline.cc config.cc contain.cc cpu.cc mnt.cc net.cc nsjail.cc pid.cc sandbox.cc subproc.cc uts.cc user.cc util.cc
SRCS_PROTO = config.proto
SRCS_PB_CXX = $(SRCS_PROTO:.proto=.pb.cc)
SRCS_PB_H = $(SRCS_PROTO:.proto=.pb.h)
# DO NOT DELETE THIS LINE -- make depend depends on it.
log.o: log.h nsjail.h
-util.o: util.h nsjail.h common.h log.h
-caps.o: caps.h nsjail.h common.h log.h util.h
+caps.o: caps.h nsjail.h log.h common.h util.h
cgroup.o: cgroup.h nsjail.h log.h util.h
-cmdline.o: cmdline.h nsjail.h log.h util.h caps.h common.h config.h mnt.h
-cmdline.o: sandbox.h user.h
-config.o: log.h nsjail.h util.h caps.h cmdline.h common.h config.h mnt.h
-config.o: user.h
+cmdline.o: cmdline.h nsjail.h log.h caps.h common.h config.h mnt.h sandbox.h
+cmdline.o: user.h util.h
+config.o: log.h nsjail.h caps.h cmdline.h common.h config.h mnt.h user.h
+config.o: util.h
contain.o: contain.h nsjail.h log.h caps.h cgroup.h cpu.h mnt.h net.h pid.h
contain.o: user.h uts.h
cpu.o: cpu.h nsjail.h log.h util.h
-mnt.o: mnt.h nsjail.h log.h util.h common.h subproc.h
+mnt.o: mnt.h nsjail.h log.h common.h subproc.h util.h
net.o: net.h nsjail.h log.h subproc.h
nsjail.o: nsjail.h cmdline.h common.h log.h net.h subproc.h util.h
pid.o: pid.h nsjail.h log.h subproc.h
sandbox.o: sandbox.h nsjail.h kafel/include/kafel.h log.h
-subproc.o: subproc.h nsjail.h cgroup.h contain.h net.h sandbox.h user.h
-subproc.o: common.h log.h util.h
+subproc.o: subproc.h nsjail.h cgroup.h common.h contain.h net.h sandbox.h
+subproc.o: user.h util.h log.h
uts.o: uts.h nsjail.h log.h
-user.o: user.h nsjail.h common.h log.h util.h subproc.h
+user.o: user.h nsjail.h log.h common.h subproc.h util.h
+util.o: util.h nsjail.h common.h log.h
#include <unistd.h>
extern "C" {
-#include "common.h"
#include "log.h"
-#include "util.h"
}
+#include "common.h"
+#include "util.h"
+
namespace caps {
static struct {
dbgmsg[0] = '\0';
for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
if (getPermitted(cap_data, capNames[i].val)) {
- utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
+ util::sSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
setInheritable(cap_data, capNames[i].val);
}
}
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);
+ util::sSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
}
}
LOG_D("Added the following capabilities to the ambient set:%s", dbgmsg);
LOG_W("Capability %s is not permitted in the namespace", valToStr(p->val));
return false;
}
- utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", valToStr(p->val));
+ util::sSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", valToStr(p->val));
setInheritable(cap_data, p->val);
}
LOG_D("Adding the following capabilities to the inheritable set:%s", dbgmsg);
if (getInheritable(cap_data, capNames[i].val)) {
continue;
}
- utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
+ util::sSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
if (prctl(PR_CAPBSET_DROP, (unsigned long)capNames[i].val, 0UL, 0UL, 0UL) ==
-1) {
PLOG_W("prctl(PR_CAPBSET_DROP, %s)", capNames[i].name);
-1) {
PLOG_W("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, %s)", valToStr(p->val));
} else {
- utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", valToStr(p->val));
+ util::sSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", valToStr(p->val));
}
}
LOG_D("Added the following capabilities to the ambient set:%s", dbgmsg);
extern "C" {
#include "log.h"
-#include "util.h"
}
+#include "util.h"
+
namespace cgroup {
static bool initNsFromParentMem(struct nsjconf_t* nsjconf, pid_t pid) {
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);
LOG_D("Setting '%s' to '%s'", fname, mem_max_str);
- if (!utilWriteBufToFile(fname, mem_max_str, strlen(mem_max_str), O_WRONLY | O_CLOEXEC)) {
+ if (!util::writeBufToFile(fname, mem_max_str, strlen(mem_max_str), O_WRONLY | O_CLOEXEC)) {
LOG_E("Could not update memory cgroup max limit");
return false;
}
*/
snprintf(fname, sizeof(fname), "%s/memory.oom_control", mem_cgroup_path);
LOG_D("Writting '0' '%s'", fname);
- if (!utilWriteBufToFile(fname, "0", strlen("0"), O_WRONLY | O_CLOEXEC)) {
+ if (!util::writeBufToFile(fname, "0", strlen("0"), O_WRONLY | O_CLOEXEC)) {
LOG_E("Could not update memory cgroup oom control");
return false;
}
snprintf(pid_str, sizeof(pid_str), "%d", (int)pid);
snprintf(fname, sizeof(fname), "%s/tasks", mem_cgroup_path);
LOG_D("Adding PID='%s' to '%s'", pid_str, fname);
- if (!utilWriteBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY | O_CLOEXEC)) {
+ if (!util::writeBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY | O_CLOEXEC)) {
LOG_E("Could not update memory cgroup task list");
return false;
}
snprintf(pids_max_str, sizeof(pids_max_str), "%u", 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 | O_CLOEXEC)) {
+ if (!util::writeBufToFile(
+ fname, pids_max_str, strlen(pids_max_str), O_WRONLY | O_CLOEXEC)) {
LOG_E("Could not update pids cgroup max limit");
return false;
}
snprintf(pid_str, sizeof(pid_str), "%d", (int)pid);
snprintf(fname, sizeof(fname), "%s/tasks", pids_cgroup_path);
LOG_D("Adding PID='%s' to '%s'", pid_str, fname);
- if (!utilWriteBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY | O_CLOEXEC)) {
+ if (!util::writeBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY | O_CLOEXEC)) {
LOG_E("Could not update pids cgroup task list");
return false;
}
nsjconf->cgroup_net_cls_classid);
snprintf(fname, sizeof(fname), "%s/net_cls.classid", net_cls_cgroup_path);
LOG_D("Setting '%s' to '%s'", fname, net_cls_classid_str);
- if (!utilWriteBufToFile(
+ if (!util::writeBufToFile(
fname, net_cls_classid_str, strlen(net_cls_classid_str), O_WRONLY | O_CLOEXEC)) {
LOG_E("Could not update net_cls cgroup classid");
return false;
snprintf(pid_str, sizeof(pid_str), "%d", (int)pid);
snprintf(fname, sizeof(fname), "%s/tasks", net_cls_cgroup_path);
LOG_D("Adding PID='%s' to '%s'", pid_str, fname);
- if (!utilWriteBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY | O_CLOEXEC)) {
+ if (!util::writeBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY | O_CLOEXEC)) {
LOG_E("Could not update net_cls cgroup task list");
return false;
}
nsjconf->cgroup_cpu_ms_per_sec * 1000U);
snprintf(fname, sizeof(fname), "%s/cpu.cfs_quota_us", cpu_cgroup_path);
LOG_D("Setting '%s' to '%s'", fname, cpu_ms_per_sec_str);
- if (!utilWriteBufToFile(
+ if (!util::writeBufToFile(
fname, cpu_ms_per_sec_str, strlen(cpu_ms_per_sec_str), O_WRONLY | O_CLOEXEC)) {
LOG_E("Could not update cpu quota");
return false;
const char cpu_period_us[] = "1000000";
snprintf(fname, sizeof(fname), "%s/cpu.cfs_period_us", cpu_cgroup_path);
LOG_D("Setting '%s' to '%s'", fname, cpu_period_us);
- if (!utilWriteBufToFile(
+ if (!util::writeBufToFile(
fname, cpu_period_us, strlen(cpu_period_us), O_WRONLY | O_CLOEXEC)) {
LOG_E("Could not update cpu period");
return false;
snprintf(pid_str, sizeof(pid_str), "%d", (int)pid);
snprintf(fname, sizeof(fname), "%s/tasks", cpu_cgroup_path);
LOG_D("Adding PID='%s' to '%s'", pid_str, fname);
- if (!utilWriteBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY | O_CLOEXEC)) {
+ if (!util::writeBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY | O_CLOEXEC)) {
LOG_E("Could not update cpu cgroup task list");
return false;
}
extern "C" {
#include "log.h"
-#include "util.h"
}
#include "caps.h"
#include "mnt.h"
#include "sandbox.h"
#include "user.h"
+#include "util.h"
namespace cmdline {
if (strcasecmp(optarg, "max") == 0 || strcasecmp(optarg, "hard") == 0) {
return cur.rlim_max;
}
- if (utilIsANumber(optarg) == false) {
+ if (util::isANumber(optarg) == false) {
LOG_F(
"RLIMIT %d needs a numeric or 'max'/'hard'/'def'/'soft'/'inf' value ('%s' "
"provided)",
static char cmdlineTmpfsSz[PATH_MAX] = "size=4194304";
struct ints_t* f;
- f = reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
+ f = reinterpret_cast<struct ints_t*>(util::memAlloc(sizeof(struct ints_t)));
f->val = STDIN_FILENO;
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
- f = reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
+ f = reinterpret_cast<struct ints_t*>(util::memAlloc(sizeof(struct ints_t)));
f->val = STDOUT_FILENO;
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
- f = reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
+ f = reinterpret_cast<struct ints_t*>(util::memAlloc(sizeof(struct ints_t)));
f->val = STDERR_FILENO;
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
break;
case 0x0505: {
struct ints_t* f;
- f = reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
+ f = reinterpret_cast<struct ints_t*>(util::memAlloc(sizeof(struct ints_t)));
f->val = (int)strtol(optarg, NULL, 0);
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
} break;
break;
case 0x0509: {
struct ints_t* f =
- reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
+ reinterpret_cast<struct ints_t*>(util::memAlloc(sizeof(struct ints_t)));
f->val = caps::nameToVal(optarg);
if (f->val == -1) {
return nullptr;
break;
case 'E': {
struct charptr_t* p = reinterpret_cast<struct charptr_t*>(
- utilMalloc(sizeof(struct charptr_t)));
+ util::memAlloc(sizeof(struct charptr_t)));
p->val = optarg;
TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers);
} break;
if (TAILQ_EMPTY(&nsjconf->uids)) {
struct idmap_t* p =
- reinterpret_cast<struct idmap_t*>(utilMalloc(sizeof(struct idmap_t)));
+ reinterpret_cast<struct idmap_t*>(util::memAlloc(sizeof(struct idmap_t)));
p->inside_id = getuid();
p->outside_id = getuid();
p->count = 1U;
}
if (TAILQ_EMPTY(&nsjconf->gids)) {
struct idmap_t* p =
- reinterpret_cast<struct idmap_t*>(utilMalloc(sizeof(struct idmap_t)));
+ reinterpret_cast<struct idmap_t*>(util::memAlloc(sizeof(struct idmap_t)));
p->inside_id = getgid();
p->outside_id = getgid();
p->count = 1U;
#include <sys/stat.h>
#include <sys/types.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/text_format.h>
+#include <fstream>
+#include <string>
+#include <vector>
+
extern "C" {
#include "log.h"
-#include "util.h"
}
-
#include "caps.h"
#include "cmdline.h"
#include "common.h"
#include "config.h"
+#include "config.pb.h"
#include "mnt.h"
#include "user.h"
-
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/text_format.h>
-#include <fstream>
-#include <string>
-#include <vector>
-
-#include "config.pb.h"
+#include "util.h"
#define DUP_IF_SET(njc, val) (njc.has_##val() ? njc.val().c_str() : NULL)
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)));
+ reinterpret_cast<charptr_t*>(util::memAlloc(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)));
+ reinterpret_cast<struct ints_t*>(util::memAlloc(sizeof(struct ints_t)));
f->val = caps::nameToVal(njc.cap(i).c_str());
if (f->val == -1) {
return false;
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)));
+ reinterpret_cast<struct ints_t*>(util::memAlloc(sizeof(struct ints_t)));
f->val = njc.pass_fd(i);
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
}
kafel_string += njc.seccomp_string(i);
}
nsjconf->kafel_string =
- njc.seccomp_string().size() > 0 ? utilStrDup(kafel_string.c_str()) : NULL;
+ njc.seccomp_string().size() > 0 ? util::strDup(kafel_string.c_str()) : NULL;
nsjconf->cgroup_mem_max = njc.cgroup_mem_max();
nsjconf->cgroup_mem_mount = njc.cgroup_mem_mount().c_str();
extern "C" {
#include "log.h"
-#include "util.h"
}
+#include "util.h"
+
namespace cpu {
static void setRandomCpu(cpu_set_t* mask, size_t mask_size, size_t cpu_num) {
}
for (;;) {
- uint64_t n = utilRnd64() % cpu_num;
+ uint64_t n = util::rnd64() % cpu_num;
if (!CPU_ISSET_S(n, mask_size, mask)) {
LOG_D("Setting allowed CPU#:%" PRIu64 " of [0-%zu]", n, cpu_num - 1);
CPU_SET_S(n, mask_size, mask);
extern "C" {
#include "log.h"
-#include "util.h"
}
#include "common.h"
#include "subproc.h"
+#include "util.h"
namespace mnt {
for (size_t i = 0; i < ARRAYSIZE(mountFlags); i++) {
if (flags & mountFlags[i].flag) {
- utilSSnPrintf(
+ util::sSnPrintf(
mountFlagsStr, sizeof(mountFlagsStr), "%s|", mountFlags[i].name);
}
}
for (size_t i = 0; i < ARRAYSIZE(mountFlags); i++) {
knownFlagMask |= mountFlags[i].flag;
}
- utilSSnPrintf(mountFlagsStr, sizeof(mountFlagsStr), "%#tx", flags & ~(knownFlagMask));
+ util::sSnPrintf(mountFlagsStr, sizeof(mountFlagsStr), "%#tx", flags & ~(knownFlagMask));
return mountFlagsStr;
}
}
if (mpt->isSymlink) {
- if (utilCreateDirRecursively(dst) == false) {
+ if (util::createDirRecursively(dst) == false) {
LOG_W("Couldn't create upper directories for '%s'", dst);
return false;
}
} else if (mpt->isDir) {
- if (utilCreateDirRecursively(dst) == false) {
+ if (util::createDirRecursively(dst) == false) {
LOG_W("Couldn't create upper directories for '%s'", dst);
return false;
}
PLOG_W("mkdir('%s')", dst);
}
} else {
- if (utilCreateDirRecursively(dst) == false) {
+ if (util::createDirRecursively(dst) == false) {
LOG_W("Couldn't create upper directories for '%s'", dst);
return false;
}
PLOG_W("open(srcpath, O_CREAT|O_EXCL|O_CLOEXEC|O_WRONLY, 0644) failed");
return false;
}
- if (utilWriteToFd(fd, mpt->src_content, mpt->src_content_len) == false) {
+ if (util::writeToFd(fd, mpt->src_content, mpt->src_content_len) == false) {
LOG_W("Writting %zu bytes to '%s' failed", mpt->src_content_len, srcpath);
close(fd);
return false;
if (mkdirAndTest(dir)) {
return true;
}
- snprintf(dir, PATH_MAX, "/tmp/nsjail.%s.%" PRIx64, name, utilRnd64());
+ snprintf(dir, PATH_MAX, "/tmp/nsjail.%s.%" PRIx64, name, util::rnd64());
if (mkdirAndTest(dir)) {
return true;
}
return initNsInternal(nsjconf);
}
- pid_t pid = subprocClone(CLONE_FS | SIGCHLD);
+ pid_t pid = subproc::cloneProc(CLONE_FS | SIGCHLD);
if (pid == -1) {
return false;
}
const char* src_env, const char* dst_env, const char* src_content, size_t src_content_len,
bool is_symlink) {
struct mounts_t* p =
- reinterpret_cast<struct mounts_t*>(utilCalloc(sizeof(struct mounts_t)));
+ reinterpret_cast<struct mounts_t*>(util::clearAlloc(sizeof(struct mounts_t)));
if (src_env) {
const char* e = getenv(src_env);
return false;
}
} else {
- p->src = utilStrDup(src);
+ p->src = util::strDup(src);
}
if (dst_env) {
return false;
}
} else {
- p->dst = utilStrDup(dst);
+ p->dst = util::strDup(dst);
}
- p->fs_type = utilStrDup(fstype);
- p->options = utilStrDup(options);
+ p->fs_type = util::strDup(fstype);
+ p->options = util::strDup(options);
p->flags = flags;
p->isDir = true;
p->isSymlink = is_symlink;
break;
}
- p->src_content = utilMemDup((const uint8_t*)src_content, src_content_len);
+ p->src_content = util::memDup((const uint8_t*)src_content, src_content_len);
p->src_content_len = src_content_len;
if (head) {
mpt->isDir ? "true" : "false");
if (mpt->mandatory == false) {
- utilSSnPrintf(mount_pt_descr, sizeof(mount_pt_descr), " mandatory:false");
+ util::sSnPrintf(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",
+ util::sSnPrintf(mount_pt_descr, sizeof(mount_pt_descr), " src_content_len:%zu",
mpt->src_content_len);
}
if (mpt->isSymlink) {
- utilSSnPrintf(mount_pt_descr, sizeof(mount_pt_descr), " symlink:true");
+ util::sSnPrintf(mount_pt_descr, sizeof(mount_pt_descr), " symlink:true");
}
return mount_pt_descr;
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) {
+ if (subproc::systemExe(argv, environ) != 0) {
LOG_E("Couldn't create MACVTAP interface for '%s'", nsjconf->iface_vs);
return false;
}
}
static bool nsjailSetSigHandler(int sig) {
- LOG_D("Setting sighandler for signal %s (%d)", utilSigName(sig), sig);
+ LOG_D("Setting sighandler for signal %s (%d)", util::sigName(sig), sig);
sigset_t smask;
sigemptyset(&smask);
* first clone/fork will work, and the rest will fail with ENOMEM (see 'man pid_namespaces'
* for details on this behavior)
*/
- pid_t pid = subprocClone(CLONE_FS);
+ pid_t pid = subproc::cloneProc(CLONE_FS);
if (pid == -1) {
PLOG_E("Couldn't create a dummy init process");
return false;
#include <unistd.h>
#include "cgroup.h"
+#include "common.h"
#include "contain.h"
#include "net.h"
#include "sandbox.h"
#include "user.h"
+#include "util.h"
extern "C" {
-#include "common.h"
#include "log.h"
-#include "util.h"
+} // extern "C"
+
+namespace subproc {
#if !defined(CLONE_NEWCGROUP)
#define CLONE_NEWCGROUP 0x02000000
#endif /* !defined(CLONE_NEWCGROUP) */
-static const char* subprocCloneFlagsToStr(uintptr_t flags) {
+static const char* cloneFlagsToStr(uintptr_t flags) {
static __thread char cloneFlagName[1024];
cloneFlagName[0] = '\0';
for (size_t i = 0; i < ARRAYSIZE(cloneFlags); i++) {
if (flags & cloneFlags[i].flag) {
- utilSSnPrintf(
+ util::sSnPrintf(
cloneFlagName, sizeof(cloneFlagName), "%s|", cloneFlags[i].name);
}
}
knownFlagMask |= cloneFlags[i].flag;
}
if (flags & ~(knownFlagMask)) {
- utilSSnPrintf(
+ util::sSnPrintf(
cloneFlagName, sizeof(cloneFlagName), "%#tx|", flags & ~(knownFlagMask));
}
- utilSSnPrintf(cloneFlagName, sizeof(cloneFlagName), "%s", utilSigName(flags & CSIGNAL));
+ util::sSnPrintf(cloneFlagName, sizeof(cloneFlagName), "%s", util::sigName(flags & CSIGNAL));
return cloneFlagName;
}
-} // extern "C"
-
/* Reset the execution environment for the new process */
static bool resetEnv(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) {
- PLOG_W("signal(%s, SIG_DFL)", utilSigName(nssigs[i]));
+ PLOG_W("signal(%s, SIG_DFL)", util::sigName(nssigs[i]));
return false;
}
}
return true;
}
-namespace subproc {
-
static const char kSubprocDoneChar = 'D';
static int subprocNewProc(
}
} else {
char doneChar;
- if (utilReadFromFd(pipefd, &doneChar, sizeof(doneChar)) != sizeof(doneChar)) {
+ if (util::readFromFd(pipefd, &doneChar, sizeof(doneChar)) != sizeof(doneChar)) {
_exit(0xff);
}
if (doneChar != kSubprocDoneChar) {
}
static void addProc(struct nsjconf_t* nsjconf, pid_t pid, int sock) {
- struct pids_t* p = reinterpret_cast<struct pids_t*>(utilMalloc(sizeof(struct pids_t)));
+ struct pids_t* p = reinterpret_cast<struct pids_t*>(util::memAlloc(sizeof(struct pids_t)));
p->pid = pid;
p->start = time(NULL);
net::connToText(
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, util::timeToStr(p->start));
close(p->pid_syscall_fd);
TAILQ_REMOVE(&nsjconf->pids, p, pointers);
free(p);
}
char buf[4096];
- ssize_t rdsize = utilReadFromFd(p->pid_syscall_fd, buf, sizeof(buf) - 1);
+ ssize_t rdsize = util::readFromFd(p->pid_syscall_fd, buf, sizeof(buf) - 1);
if (rdsize < 1) {
LOG_W("PID: %d, SiSyscall: %d, SiCode: %d, SiErrno: %d", (int)si->si_pid,
si->si_syscall, si->si_code, si->si_errno);
if (WIFSIGNALED(status)) {
LOG_I(
"PID: %d (%s) terminated with signal: %s (%d), (PIDs left: %d)",
- si.si_pid, remote_txt, utilSigName(WTERMSIG(status)),
+ si.si_pid, remote_txt, util::sigName(WTERMSIG(status)),
WTERMSIG(status), countProc(nsjconf) - 1);
removeProc(nsjconf, si.si_pid);
rv = 100 + WTERMSIG(status);
LOG_E("Couldn't initialize user namespaces for pid %d", pid);
return false;
}
- if (utilWriteToFd(pipefd, &kSubprocDoneChar, sizeof(kSubprocDoneChar)) !=
+ if (util::writeToFd(pipefd, &kSubprocDoneChar, sizeof(kSubprocDoneChar)) !=
sizeof(kSubprocDoneChar)) {
LOG_E("Couldn't signal the new process via a socketpair");
return false;
flags |= (nsjconf->clone_newcgroup ? CLONE_NEWCGROUP : 0);
if (nsjconf->mode == MODE_STANDALONE_EXECVE) {
- LOG_D("Entering namespace with flags:%s", subprocCloneFlagsToStr(flags));
+ LOG_D("Entering namespace with flags:%s", cloneFlagsToStr(flags));
if (unshare(flags) == -1) {
- PLOG_E("unshare(%s)", subprocCloneFlagsToStr(flags));
+ PLOG_E("unshare(%s)", cloneFlagsToStr(flags));
_exit(0xff);
}
subprocNewProc(nsjconf, fd_in, fd_out, fd_err, -1);
}
flags |= SIGCHLD;
- LOG_D("Creating new process with clone flags:%s", subprocCloneFlagsToStr(flags));
+ LOG_D("Creating new process with clone flags:%s", cloneFlagsToStr(flags));
int sv[2];
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) == -1) {
int child_fd = sv[0];
int parent_fd = sv[1];
- pid_t pid = subprocClone(flags);
+ pid_t pid = cloneProc(flags);
if (pid == 0) {
close(parent_fd);
subprocNewProc(nsjconf, fd_in, fd_out, fd_err, child_fd);
"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));
+ cloneFlagsToStr(flags));
close(parent_fd);
return;
}
net::connToText(fd_in, true /* remote */, cs_addr, sizeof(cs_addr), NULL);
}
-} // namespace subproc
-
/*
* Will be used inside the child process only, so it's safe to have it in BSS.
* Some CPU archs (e.g. aarch64) must have it aligned. Size: 128 KiB (/2)
*/
-static uint8_t subprocCloneStack[128 * 1024] __attribute__((aligned(__BIGGEST_ALIGNMENT__)));
+static uint8_t cloneStack[128 * 1024] __attribute__((aligned(__BIGGEST_ALIGNMENT__)));
/* 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 cloneFunc(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 cloneProc(uintptr_t flags) {
if (flags & CLONE_VM) {
LOG_E("Cannot use clone(flags & CLONE_VM)");
return -1;
}
if (setjmp(env) == 0) {
- LOG_D("Cloning process with flags:%s", subprocCloneFlagsToStr(flags));
+ LOG_D("Cloning process with flags:%s", cloneFlagsToStr(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 the subprocCloneFunc()
+ * inside of the cloneFunc()
*/
- void* stack = &subprocCloneStack[sizeof(subprocCloneStack) / 2];
+ void* stack = &cloneStack[sizeof(cloneStack) / 2];
/* Parent */
- return clone(subprocCloneFunc, stack, flags, NULL, NULL, NULL);
+ return clone(cloneFunc, stack, flags, NULL, NULL, NULL);
}
/* Child */
return 0;
}
-int subprocSystem(const char** argv, char** env) {
+int systemExe(const char** argv, char** env) {
bool exec_failed = false;
int sv[2];
close(sv[0]);
execve(argv[0], (char* const*)argv, (char* const*)env);
PLOG_W("execve('%s')", argv[0]);
- utilWriteToFd(sv[1], "A", 1);
+ util::writeToFd(sv[1], "A", 1);
exit(0);
}
close(sv[1]);
char buf[1];
- if (utilReadFromFd(sv[0], buf, sizeof(buf)) > 0) {
+ if (util::readFromFd(sv[0], buf, sizeof(buf)) > 0) {
exec_failed = true;
LOG_W("Couldn't execute '%s'", argv[0]);
}
if (WIFSIGNALED(status)) {
int exit_signal = WTERMSIG(status);
LOG_W("PID %d killed by signal: %d (%s)", pid, exit_signal,
- utilSigName(exit_signal));
+ util::sigName(exit_signal));
return 2;
}
LOG_W("Unknown exit status: %d", status);
}
}
+
+} // namespace subproc
#include "nsjail.h"
-#ifdef __cplusplus
namespace subproc {
void runChild(struct nsjconf_t* nsjconf, int fd_in, int fd_out, int fd_err);
void killAll(struct nsjconf_t* nsjconf);
/* Returns the exit code of the first failing subprocess, or 0 if none fail */
int reapProc(struct nsjconf_t* nsjconf);
+int systemExe(const char** argv, char** env);
+pid_t cloneProc(uintptr_t flags);
} // namespace subproc
-extern "C" {
-#endif
-
-int subprocSystem(const char** argv, char** env);
-pid_t subprocClone(uintptr_t flags);
-
-#ifdef __cplusplus
-} // extern "C"
-
-#endif
-
#endif /* NS_PROC_H */
#include <unistd.h>
extern "C" {
-#include "common.h"
#include "log.h"
-#include "util.h"
}
+#include "common.h"
#include "subproc.h"
+#include "util.h"
namespace user {
char fname[PATH_MAX];
snprintf(fname, sizeof(fname), "/proc/%d/setgroups", pid);
const char* denystr = "deny";
- if (!utilWriteBufToFile(fname, denystr, strlen(denystr), O_WRONLY | O_CLOEXEC)) {
- LOG_E("utilWriteBufToFile('%s', '%s') failed", fname, denystr);
+ if (!util::writeBufToFile(fname, denystr, strlen(denystr), O_WRONLY | O_CLOEXEC)) {
+ LOG_E("util::writeBufToFile('%s', '%s') failed", fname, denystr);
return false;
}
return true;
if (p->is_newidmap) {
continue;
}
- utilSSnPrintf(map, sizeof(map), "%lu %lu %zu\n", (unsigned long)p->inside_id,
+ util::sSnPrintf(map, sizeof(map), "%lu %lu %zu\n", (unsigned long)p->inside_id,
(unsigned long)p->outside_id, p->count);
}
}
LOG_D("Writing '%s' to '%s'", map, fname);
- if (!utilWriteBufToFile(fname, map, strlen(map), O_WRONLY | O_CLOEXEC)) {
- LOG_E("utilWriteBufToFile('%s', '%s') failed", fname, map);
+ if (!util::writeBufToFile(fname, map, strlen(map), O_WRONLY | O_CLOEXEC)) {
+ LOG_E("util::writeBufToFile('%s', '%s') failed", fname, map);
return false;
}
if (p->is_newidmap) {
continue;
}
- utilSSnPrintf(map, sizeof(map), "%lu %lu %zu\n", (unsigned long)p->inside_id,
+ util::sSnPrintf(map, sizeof(map), "%lu %lu %zu\n", (unsigned long)p->inside_id,
(unsigned long)p->outside_id, p->count);
}
}
LOG_D("Writing '%s' to '%s'", map, fname);
- if (!utilWriteBufToFile(fname, map, strlen(map), O_WRONLY | O_CLOEXEC)) {
- LOG_E("utilWriteBufToFile('%s', '%s') failed", fname, map);
+ if (!util::writeBufToFile(fname, map, strlen(map), O_WRONLY | O_CLOEXEC)) {
+ LOG_E("util::writeBufToFile('%s', '%s') failed", fname, map);
return false;
}
return true;
}
- if (subprocSystem(argv, environ) != 0) {
+ if (subproc::systemExe(argv, environ) != 0) {
LOG_E("'/usr/bin/newgidmap' failed");
return false;
}
return true;
}
- if (subprocSystem(argv, environ) != 0) {
+ if (subproc::systemExe(argv, environ) != 0) {
LOG_E("'/usr/bin/newuidmap' failed");
return false;
}
if (pw != NULL) {
return pw->pw_uid;
}
- if (utilIsANumber(id)) {
+ if (util::isANumber(id)) {
return (uid_t)strtoull(id, NULL, 0);
}
return (uid_t)-1;
if (gr != NULL) {
return gr->gr_gid;
}
- if (utilIsANumber(id)) {
+ if (util::isANumber(id)) {
return (gid_t)strtoull(id, NULL, 0);
}
return (gid_t)-1;
}
}
- struct idmap_t* p = reinterpret_cast<struct idmap_t*>(utilMalloc(sizeof(struct idmap_t)));
+ struct idmap_t* p =
+ reinterpret_cast<struct idmap_t*>(util::memAlloc(sizeof(struct idmap_t)));
p->inside_id = inside_id;
p->outside_id = outside_id;
p->count = cnt;
#include <unistd.h>
#include "common.h"
+
+extern "C" {
#include "log.h"
+}
-void* utilMalloc(size_t sz) {
+namespace util {
+
+void* memAlloc(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* r = utilMalloc(sz);
+void* clearAlloc(size_t sz) {
+ void* r = malloc(sz);
memset(r, '\0', sz);
return r;
}
-char* utilStrDup(const char* str) {
+char* strDup(const char* str) {
if (str == NULL) {
return NULL;
}
return ret;
}
-uint8_t* utilMemDup(const uint8_t* src, size_t len) {
+uint8_t* memDup(const uint8_t* src, size_t len) {
if (src == NULL) {
return NULL;
}
- uint8_t* ret = utilMalloc(len);
+ uint8_t* ret = reinterpret_cast<uint8_t*>(malloc(len));
memcpy(ret, src, len);
return ret;
}
-ssize_t utilReadFromFd(int fd, void* buf, size_t len) {
+ssize_t readFromFd(int fd, void* buf, size_t len) {
uint8_t* charbuf = (uint8_t*)buf;
size_t readSz = 0;
return readSz;
}
-ssize_t utilReadFromFile(const char* fname, void* buf, size_t len) {
+ssize_t readFromFile(const char* fname, void* buf, size_t len) {
int fd;
TEMP_FAILURE_RETRY(fd = open(fname, O_RDONLY | O_CLOEXEC));
if (fd == -1) {
LOG_E("open('%s', O_RDONLY|O_CLOEXEC)", fname);
return -1;
}
- ssize_t ret = utilReadFromFd(fd, buf, len);
+ ssize_t ret = readFromFd(fd, buf, len);
close(fd);
return ret;
}
-ssize_t utilWriteToFd(int fd, const void* buf, size_t len) {
+ssize_t writeToFd(int fd, const void* buf, size_t len) {
const uint8_t* charbuf = (const uint8_t*)buf;
size_t writtenSz = 0;
return true;
}
-bool utilWriteBufToFile(const char* filename, const void* buf, size_t len, int open_flags) {
+bool writeBufToFile(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 false;
}
- if (utilWriteToFd(fd, buf, len) == false) {
+ if (writeToFd(fd, buf, len) == false) {
PLOG_E("Couldn't write '%zu' bytes to file '%s' (fd='%d')", len, filename, fd);
close(fd);
unlink(filename);
return true;
}
-bool utilCreateDirRecursively(const char* dir) {
+bool createDirRecursively(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 sSnPrintf(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 isANumber(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 rndInitThread(void) {
#if defined(__NR_getrandom)
if (syscall(__NR_getrandom, &rndX, sizeof(rndX), 0) == sizeof(rndX)) {
return;
rndX = tv.tv_usec + ((uint64_t)tv.tv_sec << 32);
return;
}
- if (utilReadFromFd(fd, (uint8_t*)&rndX, sizeof(rndX)) != sizeof(rndX)) {
+ if (readFromFd(fd, (uint8_t*)&rndX, sizeof(rndX)) != sizeof(rndX)) {
PLOG_F("Couldn't read '%zu' bytes from /dev/urandom", sizeof(rndX));
close(fd);
}
close(fd);
}
-uint64_t utilRnd64(void) {
- pthread_once(&rndThreadOnce, utilRndInitThread);
+uint64_t rnd64(void) {
+ pthread_once(&rndThreadOnce, rndInitThread);
rndX = a * rndX + c;
return rndX;
}
-const char* utilSigName(int signo) {
+const char* sigName(int signo) {
static __thread char sigstr[32];
sigstr[0] = '\0';
}
static __thread char timestr[64];
-const char* utilTimeToStr(time_t t) {
+const char* timeToStr(time_t t) {
struct tm utctime;
localtime_r(&t, &utctime);
if (strftime(timestr, sizeof(timestr) - 1, "%FT%T%z", &utctime) == 0) {
}
return timestr;
}
+
+} // namespace util
#include "nsjail.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-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);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+namespace util {
+
+void* memAlloc(size_t sz);
+void* clearAlloc(size_t sz);
+char* strDup(const char* str);
+uint8_t* memDup(const uint8_t* src, size_t len);
+ssize_t readFromFd(int fd, void* buf, size_t len);
+ssize_t readFromFile(const char* fname, void* buf, size_t len);
+ssize_t writeToFd(int fd, const void* buf, size_t len);
+bool writeBufToFile(const char* filename, const void* buf, size_t len, int open_flags);
+bool createDirRecursively(const char* dir);
+int sSnPrintf(char* str, size_t size, const char* format, ...);
+bool isANumber(const char* s);
+uint64_t rnd64(void);
+const char* sigName(int signo);
+const char* timeToStr(time_t t);
+
+} // namespace util
#endif /* NS_UTIL_H */