[submodule "kafel"]
path = kafel
url = https://github.com/google/kafel.git
-[submodule "protobuf-c-text"]
- path = protobuf-c-text
- url = https://github.com/protobuf-c/protobuf-c-text.git
#
CC ?= gcc
+CXX ?= g++
-EXTRA_CFLAGS := $(CFLAGS)
-
-CFLAGS += -O2 -c -std=gnu11 \
+COMMON_FLAGS += -O2 -c \
-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 \
-Wformat -Wformat=2 -Wformat-security -fPIE \
-Wno-format-nonliteral \
-Wall -Wextra -Werror \
-Ikafel/include
-LDFLAGS += -Wl,-z,now -Wl,-z,relro -pie -Wl,-z,noexecstack -lpthread -lcap
+CFLAGS += $(COMMON_FLAGS) -std=gnu11
+CXXFLAGS += $(COMMON_FLAGS) $(shell pkg-config --cflags protobuf) -std=c++11 -Wno-unused
+
+LDFLAGS += -Wl,-z,now -Wl,-z,relro -pie -Wl,-z,noexecstack -lpthread -lcap $(shell pkg-config --libs protobuf)
BIN = nsjail
LIBS = kafel/libkafel.a
-SRCS = nsjail.c caps.c cmdline.c config.c contain.c log.c cgroup.c mount.c net.c pid.c sandbox.c subproc.c user.c util.c uts.c cpu.c
-OBJS = $(SRCS:.c=.o)
+SRCS_C = nsjail.c caps.c cmdline.c contain.c log.c cgroup.c mount.c net.c pid.c sandbox.c subproc.c user.c util.c uts.c cpu.c
+SRCS_CXX = config.cc
+SRCS_PB = config.proto
+OBJS = $(SRCS_C:.c=.o) $(SRCS_CXX:.cc=.o) $(SRCS_PB:.proto=.pb.o)
+PROTO_DEPS = config.pb.cc config.pb.h
ifdef DEBUG
CFLAGS += -g -ggdb -gdwarf-4
+ CXXFLAGS += -g -ggdb -gdwarf-4
endif
USE_NL3 ?= yes
endif
endif
-USE_PROTOBUF ?= yes
-ifeq ($(USE_PROTOBUF), yes)
-ifeq ("$(shell which protoc-c)", "")
- USE_PROTOBUF := no
- PROTOC_WARNING := yes
-endif
-endif
-
-ifeq ($(USE_PROTOBUF), no)
-else ifeq ($(shell pkg-config --exists libprotobuf-c && echo yes), yes)
- PROTO_DEPS = config.pb-c.h config.pb-c.c
- SRCS += config.pb-c.c
- CFLAGS += -DNSJAIL_WITH_PROTOBUF -Iprotobuf-c-text/protobuf-c-text $(shell pkg-config --cflags libprotobuf-c)
- LIBS += protobuf-c-text/protobuf-c-text/.libs/libprotobuf-c-text.a
- LDFLAGS += $(shell pkg-config --libs libprotobuf-c)
-else ifneq ("$(wildcard /usr/include/google/protobuf-c/protobuf-c.h)", "")
- PROTO_DEPS = config.pb-c.h config.pb-c.c
- SRCS += config.pb-c.c
- CFLAGS += -DNSJAIL_WITH_PROTOBUF -Iprotobuf-c-text/protobuf-c-text -I/usr/include/google
- LIBS += protobuf-c-text/protobuf-c-text/.libs/libprotobuf-c-text.a
- LDFLAGS += -Wl,-lprotobuf-c
-else ifneq ("$(wildcard /usr/local/include/google/protobuf-c/protobuf-c.h)", "")
- PROTO_DEPS = config.pb-c.h config.pb-c.c
- SRCS += config.pb-c.c
- CFLAGS += -DNSJAIL_WITH_PROTOBUF -Iprotobuf-c-text/protobuf-c-text -I/usr/local/include/google
- LIBS += protobuf-c-text/protobuf-c-text/.libs/libprotobuf-c-text.a
- LDFLAGS += -Wl,--library-path=/usr/local/lib -Wl,-lprotobuf-c
-else
- USE_PROTOBUF := no
-endif
-
.PHONY: all clear depend indent
.c.o: %.c
$(CC) $(CFLAGS) $< -o $@
+.cc.o: %.cc
+ $(CXX) $(CXXFLAGS) $< -o $@
+
all: $(PROTO_DEPS) $(BIN)
-ifeq ($(PROTOC_WARNING), yes)
- $(info *********************************************************)
- $(info * 'protoc-c' is missing on your system *)
- $(info * Install 'protobuf-c-compiler' or a similar package *)
- $(info *********************************************************)
-endif
-ifeq ($(USE_PROTOBUF), no)
- $(info *********************************************************)
- $(info * Code compiled without libprotobuf-c/libprotobuf-c-dev *)
- $(info * The --config commandline option will be unavailable *)
- $(info *********************************************************)
-endif
$(BIN): $(LIBS) $(OBJS)
- $(CC) -o $(BIN) $(OBJS) $(LIBS) $(LDFLAGS)
+ $(CXX) -o $(BIN) $(OBJS) $(LIBS) $(LDFLAGS)
kafel/libkafel.a:
ifeq ("$(wildcard kafel/Makefile)","")
endif
$(MAKE) -C kafel
-protobuf-c-text/protobuf-c-text/.libs/libprotobuf-c-text.a:
-ifeq ("$(wildcard protobuf-c-text/configure)","")
- git submodule update --init
-endif
-ifeq ("$(wildcard protobuf-c-text/Makefile)","")
- sh -c "cd protobuf-c-text; CFLAGS=\"-fPIC -I/usr/include/google $(EXTRA_CFLAGS)\" ./autogen.sh --enable-shared=no --disable-doxygen-doc;"
-endif
- $(MAKE) -C protobuf-c-text
-
-$(PROTO_DEPS): config.proto
- protoc-c --c_out=. config.proto
+$(PROTO_DEPS): $(SRCS_PB)
+ protoc --cpp_out=. $(SRCS_PB)
clean:
$(RM) core Makefile.bak $(OBJS) $(BIN) $(PROTO_DEPS)
ifneq ("$(wildcard kafel/Makefile)","")
$(MAKE) -C kafel clean
endif
-ifneq ("$(wildcard protobuf-c-text/Makefile)","")
- $(MAKE) -C protobuf-c-text clean
-endif
depend:
- makedepend -Y -Ykafel/include -- -- $(SRCS)
+ makedepend -Y -Ykafel/include -- -- $(SRCS_C) $(SRCS_CXX)
indent:
+ clang-format --style=WebKit -i -sort-includes *.c *.h $(SRCS_CXX)
indent -linux -l100 -lc100 *.c *.h; rm -f *~
# DO NOT DELETE THIS LINE -- make depend depends on it.
nsjail.o: nsjail.h common.h caps.h cmdline.h log.h net.h subproc.h util.h
caps.o: caps.h common.h log.h util.h
-cmdline.o: cmdline.h common.h caps.h config.h log.h mount.h util.h user.h
-config.o: common.h caps.h config.h log.h mount.h user.h util.h
+cmdline.o: cmdline.h common.h caps.h config.h log.h mount.h user.h util.h
contain.o: contain.h common.h caps.h cgroup.h cpu.h log.h mount.h net.h pid.h
contain.o: user.h util.h uts.h
log.o: log.h common.h
util.o: util.h common.h log.h
uts.o: uts.h common.h log.h
cpu.o: cpu.h common.h log.h util.h
+config.o: common.h caps.h config.h log.h mount.h user.h util.h
#include "caps.h"
-#include <sys/capability.h>
#include <string.h>
+#include <sys/capability.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <unistd.h>
#include "log.h"
#include "util.h"
-#define VALSTR_STRUCT(x) { x, #x }
+#define VALSTR_STRUCT(x) \
+ { \
+ x, #x \
+ }
/* *INDENT-OFF* */
static struct {
- const int val;
- const char* const name;
+ const int val;
+ const char* const name;
} const capNames[] = {
VALSTR_STRUCT(CAP_CHOWN),
VALSTR_STRUCT(CAP_DAC_OVERRIDE),
VALSTR_STRUCT(CAP_BLOCK_SUSPEND),
#if defined(CAP_AUDIT_READ)
VALSTR_STRUCT(CAP_AUDIT_READ),
-#endif /* defined(CAP_AUDIT_READ) */
+#endif /* defined(CAP_AUDIT_READ) */
};
/* *INDENT-ON* */
}
if (prctl
(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, (unsigned long)capNames[i].val,
- 0UL, 0UL) == -1) {
+ 0UL, 0UL)
+ == -1) {
PLOG_W("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, %s)",
capNames[i].name);
} else {
} else {
struct ints_t *p;
TAILQ_FOREACH(p, &nsjconf->caps, pointers) {
- if (prctl
- (PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, (unsigned long)p->val, 0UL,
- 0UL) == -1) {
+ 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 "config.h"
#include "log.h"
#include "mount.h"
-#include "util.h"
#include "user.h"
+#include "util.h"
struct custom_option {
struct option opt;
/* *INDENT-OFF* */
struct custom_option custom_opts[] = {
- {{"help", no_argument, NULL, 'h'}, "Help plz.."},
- {{"mode", required_argument, NULL, 'M'},
- "Execution mode (default: o [MODE_STANDALONE_ONCE]):\n"
- "\tl: Wait for connections on a TCP port (specified with --port) "
- "[MODE_LISTEN_TCP]\n"
- "\to: Immediately launch a single process on the console using "
- "clone/execve [MODE_STANDALONE_ONCE]\n"
- "\te: Immediately launch a single process on the console using execve "
- "[MODE_STANDALONE_EXECVE]\n"
- "\tr: Immediately launch a single process on the console, keep doing it "
- "forever [MODE_STANDALONE_RERUN]"},
- {{"config", required_argument, NULL, 'C'}, "Configuration file in the config.proto ProtoBuf format"},
- {{"exec_file", required_argument, NULL, 'x'}, "File to exec (default: argv[0])"},
- {{"chroot", required_argument, NULL, 'c'}, "Directory containing / of the jail (default: none)"},
- {{"rw", no_argument, NULL, 0x601}, "Mount / and /proc as RW (default: RO)"},
- {{"user", required_argument, NULL, 'u'}, "Username/uid of processess inside the jail (default: your current uid). You can also use inside_ns_uid:outside_ns_uid:count convention here. Can be specified multiple times"},
- {{"group", required_argument, NULL, 'g'}, "Groupname/gid of processess inside the jail (default: your current gid). You can also use inside_ns_gid:global_ns_gid:count convention here. Can be specified multiple times"},
- {{"hostname", required_argument, NULL, 'H'}, "UTS name (hostname) of the jail (default: 'NSJAIL')"},
- {{"cwd", required_argument, NULL, 'D'}, "Directory in the namespace the process will run (default: '/')"},
- {{"port", required_argument, NULL, 'p'}, "TCP port to bind to (enables MODE_LISTEN_TCP) (default: 0)"},
- {{"bindhost", required_argument, NULL, 0x604}, "IP address to bind the port to (only in [MODE_LISTEN_TCP]), (default: '::')"},
- {{"max_conns_per_ip", required_argument, NULL, 'i'}, "Maximum number of connections per one IP (only in [MODE_LISTEN_TCP]), (default: 0 (unlimited))"},
- {{"log", required_argument, NULL, 'l'}, "Log file (default: use log_fd)"},
- {{"log_fd", required_argument, NULL, 'L'}, "Log FD (default: 2)"},
- {{"time_limit", required_argument, NULL, 't'}, "Maximum time that a jail can exist, in seconds (default: 600)"},
- {{"max_cpus", required_argument, NULL, 0x508}, "Maximum number of CPUs a single jailed process can use (default: 0 'no limit')"},
- {{"daemon", no_argument, NULL, 'd'}, "Daemonize after start"},
- {{"verbose", no_argument, NULL, 'v'}, "Verbose output"},
- {{"quiet", no_argument, NULL, 'q'}, "Only output warning and more important messages"},
- {{"keep_env", no_argument, NULL, 'e'}, "Should all environment variables be passed to the child?"},
- {{"env", required_argument, NULL, 'E'}, "Environment variable (can be used multiple times)"},
- {{"keep_caps", no_argument, NULL, 0x0501}, "Don't drop capabilities in the local namespace"},
- {{"silent", no_argument, NULL, 0x0502}, "Redirect child's fd:0/1/2 to /dev/null"},
- {{"skip_setsid", no_argument, NULL, 0x0504}, "Don't call setsid(), allows for terminal signal handling in the sandboxed process"},
- {{"pass_fd", required_argument, NULL, 0x0505}, "Don't close this FD before executing child (can be specified multiple times), by default: 0/1/2 are kept open"},
- {{"disable_no_new_privs", no_argument, NULL, 0x0507}, "Don't set the prctl(NO_NEW_PRIVS, 1) (DANGEROUS)"},
- {{"cap", required_argument, NULL, 0x0509}, "Retain this capability in local namespace (e.g. CAP_PTRACE). Can be specified multiple times"},
- {{"rlimit_as", required_argument, NULL, 0x0201}, "RLIMIT_AS in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 512)"},
- {{"rlimit_core", required_argument, NULL, 0x0202}, "RLIMIT_CORE in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 0)"},
- {{"rlimit_cpu", required_argument, NULL, 0x0203}, "RLIMIT_CPU, 'max' for RLIM_INFINITY, 'def' for the current value (default: 600)"},
- {{"rlimit_fsize", required_argument, NULL, 0x0204}, "RLIMIT_FSIZE in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 1)"},
- {{"rlimit_nofile", required_argument, NULL, 0x0205}, "RLIMIT_NOFILE, 'max' for RLIM_INFINITY, 'def' for the current value (default: 32)"},
- {{"rlimit_nproc", required_argument, NULL, 0x0206}, "RLIMIT_NPROC, 'max' for RLIM_INFINITY, 'def' for the current value (default: 'def')"},
- {{"rlimit_stack", required_argument, NULL, 0x0207}, "RLIMIT_STACK in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 'def')"},
- {{"persona_addr_compat_layout", no_argument, NULL, 0x0301}, "personality(ADDR_COMPAT_LAYOUT)"},
- {{"persona_mmap_page_zero", no_argument, NULL, 0x0302}, "personality(MMAP_PAGE_ZERO)"},
- {{"persona_read_implies_exec", no_argument, NULL, 0x0303}, "personality(READ_IMPLIES_EXEC)"},
- {{"persona_addr_limit_3gb", no_argument, NULL, 0x0304}, "personality(ADDR_LIMIT_3GB)"},
- {{"persona_addr_no_randomize", no_argument, NULL, 0x0305}, "personality(ADDR_NO_RANDOMIZE)"},
- {{"disable_clone_newnet", no_argument, NULL, 'N'}, "Don't use CLONE_NEWNET. Enable networking inside the jail"},
- {{"disable_clone_newuser", no_argument, NULL, 0x0402}, "Don't use CLONE_NEWUSER. Requires euid==0"},
- {{"disable_clone_newns", no_argument, NULL, 0x0403}, "Don't use CLONE_NEWNS"},
- {{"disable_clone_newpid", no_argument, NULL, 0x0404}, "Don't use CLONE_NEWPID"},
- {{"disable_clone_newipc", no_argument, NULL, 0x0405}, "Don't use CLONE_NEWIPC"},
- {{"disable_clone_newuts", no_argument, NULL, 0x0406}, "Don't use CLONE_NEWUTS"},
- {{"enable_clone_newcgroup", no_argument, NULL, 0x0407}, "Use CLONE_NEWCGROUP"},
- {{"uid_mapping", required_argument, NULL, 'U'}, "Add a custom uid mapping of the form inside_uid:outside_uid:count. Setting this requires newuidmap to be present"},
- {{"gid_mapping", required_argument, NULL, 'G'}, "Add a custom gid mapping of the form inside_gid:outside_gid:count. Setting this requires newgidmap to be present"},
- {{"bindmount_ro", required_argument, NULL, 'R'}, "List of mountpoints to be mounted --bind (ro) inside the container. Can be specified multiple times. Supports 'source' syntax, or 'source:dest'"},
- {{"bindmount", required_argument, NULL, 'B'}, "List of mountpoints to be mounted --bind (rw) inside the container. Can be specified multiple times. Supports 'source' syntax, or 'source:dest'"},
- {{"tmpfsmount", required_argument, NULL, 'T'}, "List of mountpoints to be mounted as RW/tmpfs inside the container. Can be specified multiple times. Supports 'dest' syntax"},
- {{"tmpfs_size", required_argument, NULL, 0x0602}, "Number of bytes to allocate for tmpfsmounts (default: 4194304)"},
- {{"disable_proc", no_argument, NULL, 0x0603}, "Disable mounting /proc in the jail"},
- {{"seccomp_policy", required_argument, NULL, 'P'}, "Path to file containing seccomp-bpf policy (see kafel/)"},
- {{"seccomp_string", required_argument, NULL, 0x0901}, "String with kafel seccomp-bpf policy (see kafel/)"},
- {{"cgroup_mem_max", required_argument, NULL, 0x0801}, "Maximum number of bytes to use in the group (default: '0' - disabled)"},
- {{"cgroup_mem_mount", required_argument, NULL, 0x0802}, "Location of memory cgroup FS (default: '/sys/fs/cgroup/memory')"},
- {{"cgroup_mem_parent", required_argument, NULL, 0x0803}, "Which pre-existing memory cgroup to use as a parent (default: 'NSJAIL')"},
- {{"cgroup_pids_max", required_argument, NULL, 0x0811}, "Maximum number of pids in a cgroup (default: '0' - disabled)"},
- {{"cgroup_pids_mount", required_argument, NULL, 0x0812}, "Location of pids cgroup FS (default: '/sys/fs/cgroup/pids')"},
- {{"cgroup_pids_parent", required_argument, NULL, 0x0813}, "Which pre-existing pids cgroup to use as a parent (default: 'NSJAIL')"},
- {{"iface_no_lo", no_argument, NULL, 0x700}, "Don't bring up the 'lo' interface"},
- {{"macvlan_iface", required_argument, NULL, 'I'}, "Interface which will be cloned (MACVLAN) and put inside the subprocess' namespace as 'vs'"},
- {{"macvlan_vs_ip", required_argument, NULL, 0x701}, "IP of the 'vs' interface (e.g. \"192.168.0.1\")"},
- {{"macvlan_vs_nm", required_argument, NULL, 0x702}, "Netmask of the 'vs' interface (e.g. \"255.255.255.0\")"},
- {{"macvlan_vs_gw", required_argument, NULL, 0x703}, "Default GW for the 'vs' interface (e.g. \"192.168.0.1\")"},
+ { { "help", no_argument, NULL, 'h' }, "Help plz.." },
+ { { "mode", required_argument, NULL, 'M' },
+ "Execution mode (default: o [MODE_STANDALONE_ONCE]):\n"
+ "\tl: Wait for connections on a TCP port (specified with --port) "
+ "[MODE_LISTEN_TCP]\n"
+ "\to: Immediately launch a single process on the console using "
+ "clone/execve [MODE_STANDALONE_ONCE]\n"
+ "\te: Immediately launch a single process on the console using execve "
+ "[MODE_STANDALONE_EXECVE]\n"
+ "\tr: Immediately launch a single process on the console, keep doing it "
+ "forever [MODE_STANDALONE_RERUN]" },
+ { { "config", required_argument, NULL, 'C' }, "Configuration file in the config.proto ProtoBuf format" },
+ { { "exec_file", required_argument, NULL, 'x' }, "File to exec (default: argv[0])" },
+ { { "chroot", required_argument, NULL, 'c' }, "Directory containing / of the jail (default: none)" },
+ { { "rw", no_argument, NULL, 0x601 }, "Mount / and /proc as RW (default: RO)" },
+ { { "user", required_argument, NULL, 'u' }, "Username/uid of processess inside the jail (default: your current uid). You can also use inside_ns_uid:outside_ns_uid:count convention here. Can be specified multiple times" },
+ { { "group", required_argument, NULL, 'g' }, "Groupname/gid of processess inside the jail (default: your current gid). You can also use inside_ns_gid:global_ns_gid:count convention here. Can be specified multiple times" },
+ { { "hostname", required_argument, NULL, 'H' }, "UTS name (hostname) of the jail (default: 'NSJAIL')" },
+ { { "cwd", required_argument, NULL, 'D' }, "Directory in the namespace the process will run (default: '/')" },
+ { { "port", required_argument, NULL, 'p' }, "TCP port to bind to (enables MODE_LISTEN_TCP) (default: 0)" },
+ { { "bindhost", required_argument, NULL, 0x604 }, "IP address to bind the port to (only in [MODE_LISTEN_TCP]), (default: '::')" },
+ { { "max_conns_per_ip", required_argument, NULL, 'i' }, "Maximum number of connections per one IP (only in [MODE_LISTEN_TCP]), (default: 0 (unlimited))" },
+ { { "log", required_argument, NULL, 'l' }, "Log file (default: use log_fd)" },
+ { { "log_fd", required_argument, NULL, 'L' }, "Log FD (default: 2)" },
+ { { "time_limit", required_argument, NULL, 't' }, "Maximum time that a jail can exist, in seconds (default: 600)" },
+ { { "max_cpus", required_argument, NULL, 0x508 }, "Maximum number of CPUs a single jailed process can use (default: 0 'no limit')" },
+ { { "daemon", no_argument, NULL, 'd' }, "Daemonize after start" },
+ { { "verbose", no_argument, NULL, 'v' }, "Verbose output" },
+ { { "quiet", no_argument, NULL, 'q' }, "Only output warning and more important messages" },
+ { { "keep_env", no_argument, NULL, 'e' }, "Should all environment variables be passed to the child?" },
+ { { "env", required_argument, NULL, 'E' }, "Environment variable (can be used multiple times)" },
+ { { "keep_caps", no_argument, NULL, 0x0501 }, "Don't drop capabilities in the local namespace" },
+ { { "silent", no_argument, NULL, 0x0502 }, "Redirect child's fd:0/1/2 to /dev/null" },
+ { { "skip_setsid", no_argument, NULL, 0x0504 }, "Don't call setsid(), allows for terminal signal handling in the sandboxed process" },
+ { { "pass_fd", required_argument, NULL, 0x0505 }, "Don't close this FD before executing child (can be specified multiple times), by default: 0/1/2 are kept open" },
+ { { "disable_no_new_privs", no_argument, NULL, 0x0507 }, "Don't set the prctl(NO_NEW_PRIVS, 1) (DANGEROUS)" },
+ { { "cap", required_argument, NULL, 0x0509 }, "Retain this capability in local namespace (e.g. CAP_PTRACE). Can be specified multiple times" },
+ { { "rlimit_as", required_argument, NULL, 0x0201 }, "RLIMIT_AS in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 512)" },
+ { { "rlimit_core", required_argument, NULL, 0x0202 }, "RLIMIT_CORE in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 0)" },
+ { { "rlimit_cpu", required_argument, NULL, 0x0203 }, "RLIMIT_CPU, 'max' for RLIM_INFINITY, 'def' for the current value (default: 600)" },
+ { { "rlimit_fsize", required_argument, NULL, 0x0204 }, "RLIMIT_FSIZE in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 1)" },
+ { { "rlimit_nofile", required_argument, NULL, 0x0205 }, "RLIMIT_NOFILE, 'max' for RLIM_INFINITY, 'def' for the current value (default: 32)" },
+ { { "rlimit_nproc", required_argument, NULL, 0x0206 }, "RLIMIT_NPROC, 'max' for RLIM_INFINITY, 'def' for the current value (default: 'def')" },
+ { { "rlimit_stack", required_argument, NULL, 0x0207 }, "RLIMIT_STACK in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 'def')" },
+ { { "persona_addr_compat_layout", no_argument, NULL, 0x0301 }, "personality(ADDR_COMPAT_LAYOUT)" },
+ { { "persona_mmap_page_zero", no_argument, NULL, 0x0302 }, "personality(MMAP_PAGE_ZERO)" },
+ { { "persona_read_implies_exec", no_argument, NULL, 0x0303 }, "personality(READ_IMPLIES_EXEC)" },
+ { { "persona_addr_limit_3gb", no_argument, NULL, 0x0304 }, "personality(ADDR_LIMIT_3GB)" },
+ { { "persona_addr_no_randomize", no_argument, NULL, 0x0305 }, "personality(ADDR_NO_RANDOMIZE)" },
+ { { "disable_clone_newnet", no_argument, NULL, 'N' }, "Don't use CLONE_NEWNET. Enable networking inside the jail" },
+ { { "disable_clone_newuser", no_argument, NULL, 0x0402 }, "Don't use CLONE_NEWUSER. Requires euid==0" },
+ { { "disable_clone_newns", no_argument, NULL, 0x0403 }, "Don't use CLONE_NEWNS" },
+ { { "disable_clone_newpid", no_argument, NULL, 0x0404 }, "Don't use CLONE_NEWPID" },
+ { { "disable_clone_newipc", no_argument, NULL, 0x0405 }, "Don't use CLONE_NEWIPC" },
+ { { "disable_clone_newuts", no_argument, NULL, 0x0406 }, "Don't use CLONE_NEWUTS" },
+ { { "enable_clone_newcgroup", no_argument, NULL, 0x0407 }, "Use CLONE_NEWCGROUP" },
+ { { "uid_mapping", required_argument, NULL, 'U' }, "Add a custom uid mapping of the form inside_uid:outside_uid:count. Setting this requires newuidmap to be present" },
+ { { "gid_mapping", required_argument, NULL, 'G' }, "Add a custom gid mapping of the form inside_gid:outside_gid:count. Setting this requires newgidmap to be present" },
+ { { "bindmount_ro", required_argument, NULL, 'R' }, "List of mountpoints to be mounted --bind (ro) inside the container. Can be specified multiple times. Supports 'source' syntax, or 'source:dest'" },
+ { { "bindmount", required_argument, NULL, 'B' }, "List of mountpoints to be mounted --bind (rw) inside the container. Can be specified multiple times. Supports 'source' syntax, or 'source:dest'" },
+ { { "tmpfsmount", required_argument, NULL, 'T' }, "List of mountpoints to be mounted as RW/tmpfs inside the container. Can be specified multiple times. Supports 'dest' syntax" },
+ { { "tmpfs_size", required_argument, NULL, 0x0602 }, "Number of bytes to allocate for tmpfsmounts (default: 4194304)" },
+ { { "disable_proc", no_argument, NULL, 0x0603 }, "Disable mounting /proc in the jail" },
+ { { "seccomp_policy", required_argument, NULL, 'P' }, "Path to file containing seccomp-bpf policy (see kafel/)" },
+ { { "seccomp_string", required_argument, NULL, 0x0901 }, "String with kafel seccomp-bpf policy (see kafel/)" },
+ { { "cgroup_mem_max", required_argument, NULL, 0x0801 }, "Maximum number of bytes to use in the group (default: '0' - disabled)" },
+ { { "cgroup_mem_mount", required_argument, NULL, 0x0802 }, "Location of memory cgroup FS (default: '/sys/fs/cgroup/memory')" },
+ { { "cgroup_mem_parent", required_argument, NULL, 0x0803 }, "Which pre-existing memory cgroup to use as a parent (default: 'NSJAIL')" },
+ { { "cgroup_pids_max", required_argument, NULL, 0x0811 }, "Maximum number of pids in a cgroup (default: '0' - disabled)" },
+ { { "cgroup_pids_mount", required_argument, NULL, 0x0812 }, "Location of pids cgroup FS (default: '/sys/fs/cgroup/pids')" },
+ { { "cgroup_pids_parent", required_argument, NULL, 0x0813 }, "Which pre-existing pids cgroup to use as a parent (default: 'NSJAIL')" },
+ { { "iface_no_lo", no_argument, NULL, 0x700 }, "Don't bring up the 'lo' interface" },
+ { { "macvlan_iface", required_argument, NULL, 'I' }, "Interface which will be cloned (MACVLAN) and put inside the subprocess' namespace as 'vs'" },
+ { { "macvlan_vs_ip", required_argument, NULL, 0x701 }, "IP of the 'vs' interface (e.g. \"192.168.0.1\")" },
+ { { "macvlan_vs_nm", required_argument, NULL, 0x702 }, "Netmask of the 'vs' interface (e.g. \"255.255.255.0\")" },
+ { { "macvlan_vs_gw", required_argument, NULL, 0x703 }, "Default GW for the 'vs' interface (e.g. \"192.168.0.1\")" },
};
struct custom_option deprecated_opts[] = {
// Compatibilty flags for MACVLAN.
// TODO(rswiecki): Remove this at some point.
- {{"iface", required_argument, NULL, 'I'}, "Interface which will be cloned (MACVLAN) and put inside the subprocess' namespace as 'vs'"},
- {{"iface_vs_ip", required_argument, NULL, 0x701}, "IP of the 'vs' interface (e.g. \"192.168.0.1\")"},
- {{"iface_vs_nm", required_argument, NULL, 0x702}, "Netmask of the 'vs' interface (e.g. \"255.255.255.0\")"},
- {{"iface_vs_gw", required_argument, NULL, 0x703}, "Default GW for the 'vs' interface (e.g. \"192.168.0.1\")"},
+ { { "iface", required_argument, NULL, 'I' }, "Interface which will be cloned (MACVLAN) and put inside the subprocess' namespace as 'vs'" },
+ { { "iface_vs_ip", required_argument, NULL, 0x701 }, "IP of the 'vs' interface (e.g. \"192.168.0.1\")" },
+ { { "iface_vs_nm", required_argument, NULL, 0x702 }, "Netmask of the 'vs' interface (e.g. \"255.255.255.0\")" },
+ { { "iface_vs_gw", required_argument, NULL, 0x703 }, "Default GW for the 'vs' interface (e.g. \"192.168.0.1\")" },
};
/* *INDENT-ON* */
bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
{
- /* *INDENT-OFF* */
- (*nsjconf) = (const struct nsjconf_t){
- .exec_file = NULL,
- .hostname = "NSJAIL",
- .cwd = "/",
- .chroot = NULL,
- .argv = 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, "def", 1),
- .rl_stack = cmdlineParseRLimit(RLIMIT_STACK, "def", 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,
- .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 = (size_t)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,
- .num_cpus = sysconf(_SC_NPROCESSORS_ONLN),
- };
- /* *INDENT-ON* */
+ /* *INDENT-OFF* */
+ (*nsjconf) = (const struct nsjconf_t){
+ .exec_file = NULL,
+ .hostname = "NSJAIL",
+ .cwd = "/",
+ .chroot = NULL,
+ .argv = 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, "def", 1),
+ .rl_stack = cmdlineParseRLimit(RLIMIT_STACK, "def", 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,
+ .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 = (size_t)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,
+ .num_cpus = sysconf(_SC_NPROCESSORS_ONLN),
+ };
+ /* *INDENT-ON* */
TAILQ_INIT(&nsjconf->pids);
TAILQ_INIT(&nsjconf->mountpts);
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;
}
}
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;
}
}
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;
}
}
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;
}
}
#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))); \
+#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)))
+ void _STRMERGE(__defer_f_, count)(void* _defer_arg __attribute__((unused)))
#define defer _DEFER(a, __COUNTER__)
#endif
#endif
char remote_txt[64];
struct sockaddr_in6 remote_addr;
int pid_syscall_fd;
- TAILQ_ENTRY(pids_t) pointers;
+ TAILQ_ENTRY(pids_t)
+ pointers;
};
struct mounts_t {
bool isDir;
bool isSymlink;
bool mandatory;
- TAILQ_ENTRY(mounts_t) pointers;
+ TAILQ_ENTRY(mounts_t)
+ pointers;
};
struct idmap_t {
uid_t outside_id;
size_t count;
bool is_newidmap;
- TAILQ_ENTRY(idmap_t) pointers;
+ TAILQ_ENTRY(idmap_t)
+ pointers;
};
struct ints_t {
int val;
- TAILQ_ENTRY(ints_t) pointers;
+ TAILQ_ENTRY(ints_t)
+ pointers;
};
enum ns_mode_t {
struct charptr_t {
char *val;
- TAILQ_ENTRY(charptr_t) pointers;
+ TAILQ_ENTRY(charptr_t)
+ pointers;
};
enum llevel_t {
char *kafel_string;
uid_t orig_euid;
long num_cpus;
- TAILQ_HEAD(udmaplist, idmap_t) uids;
- TAILQ_HEAD(gdmaplist, idmap_t) gids;
- TAILQ_HEAD(envlist, charptr_t) envs;
- TAILQ_HEAD(pidslist, pids_t) pids;
- TAILQ_HEAD(mountptslist, mounts_t) mountpts;
- TAILQ_HEAD(fdslistt, ints_t) open_fds;
- TAILQ_HEAD(capslistt, ints_t) caps;
+ TAILQ_HEAD(udmaplist, idmap_t)
+ uids;
+ TAILQ_HEAD(gdmaplist, idmap_t)
+ gids;
+ TAILQ_HEAD(envlist, charptr_t)
+ envs;
+ TAILQ_HEAD(pidslist, pids_t)
+ pids;
+ TAILQ_HEAD(mountptslist, mounts_t)
+ mountpts;
+ TAILQ_HEAD(fdslistt, ints_t)
+ open_fds;
+ TAILQ_HEAD(capslistt, ints_t)
+ caps;
};
#endif /* NS_COMMON_H */
+++ /dev/null
-/*
-
- nsjail - config parsing
- -----------------------------------------
-
- Copyright 2017 Google Inc. All Rights Reserved.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-*/
-
-#include "common.h"
-
-#include <stdio.h>
-#include <sys/mount.h>
-#include <sys/personality.h>
-
-#include "caps.h"
-#include "config.h"
-#include "log.h"
-#include "mount.h"
-#include "user.h"
-#include "util.h"
-
-#if !defined(NSJAIL_WITH_PROTOBUF)
-bool configParse(struct nsjconf_t * nsjconf UNUSED, const char *file UNUSED)
-{
- LOG_W("nsjail was not compiled with the protobuf-c library");
- return false;
-}
-#else /* !defined(NSJAIL_WITH_PROTOBUF) */
-
-#include "config.pb-c.h"
-#include "protobuf-c-text.h"
-
-static bool configParseInternal(struct nsjconf_t *nsjconf, Nsjail__NsJailConfig * njc)
-{
- switch (njc->mode) {
- case NSJAIL__MODE__LISTEN:
- nsjconf->mode = MODE_LISTEN_TCP;
- break;
- case NSJAIL__MODE__ONCE:
- nsjconf->mode = MODE_STANDALONE_ONCE;
- break;
- case NSJAIL__MODE__RERUN:
- nsjconf->mode = MODE_STANDALONE_RERUN;
- break;
- case NSJAIL__MODE__EXECVE:
- nsjconf->mode = MODE_STANDALONE_EXECVE;
- break;
- default:
- LOG_E("Uknown running mode: %d", njc->mode);
- return false;
- }
- nsjconf->chroot = utilStrDup(njc->chroot_dir);
- nsjconf->is_root_rw = njc->is_root_rw;
- nsjconf->hostname = utilStrDup(njc->hostname);
- nsjconf->cwd = utilStrDup(njc->cwd);
- nsjconf->port = njc->port;
- nsjconf->bindhost = utilStrDup(njc->bindhost);
- nsjconf->max_conns_per_ip = njc->max_conns_per_ip;
- nsjconf->tlimit = njc->time_limit;
- nsjconf->max_cpus = njc->max_cpus;
- nsjconf->daemonize = njc->daemon;
-
- if (njc->has_log_fd) {
- nsjconf->log_fd = njc->log_fd;
- }
- nsjconf->logfile = utilStrDup(njc->log_file);
- if (njc->has_log_level) {
- switch (njc->log_level) {
- case NSJAIL__LOG_LEVEL__DEBUG:
- nsjconf->loglevel = DEBUG;
- break;
- case NSJAIL__LOG_LEVEL__INFO:
- nsjconf->loglevel = INFO;
- break;
- case NSJAIL__LOG_LEVEL__WARNING:
- nsjconf->loglevel = WARNING;
- break;
- case NSJAIL__LOG_LEVEL__ERROR:
- nsjconf->loglevel = ERROR;
- break;
- case NSJAIL__LOG_LEVEL__FATAL:
- nsjconf->loglevel = FATAL;
- break;
- default:
- LOG_E("Unknown log_level: %d", njc->log_level);
- return false;
- }
- }
-
- if (njc->has_log_fd || njc->log_file || njc->has_log_level) {
- if (logInitLogFile(nsjconf) == false) {
- return false;
- }
- }
-
- nsjconf->keep_env = njc->keep_env;
- for (size_t i = 0; i < njc->n_envar; i++) {
- struct charptr_t *p = utilMalloc(sizeof(struct charptr_t));
- p->val = utilStrDup(njc->envar[i]);
- TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers);
- }
-
- nsjconf->keep_caps = njc->keep_caps;
- for (size_t i = 0; i < njc->n_cap; i++) {
- struct ints_t *f = utilMalloc(sizeof(struct ints_t));
- f->val = capsNameToVal(njc->cap[i]);
- if (f->val == -1) {
- return false;
- }
- TAILQ_INSERT_HEAD(&nsjconf->caps, f, pointers);
- }
-
- nsjconf->is_silent = njc->silent;
- nsjconf->skip_setsid = njc->skip_setsid;
-
- for (size_t i = 0; i < njc->n_pass_fd; i++) {
- struct ints_t *f = 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 = njc->rlimit_as * 1024ULL * 1024ULL;
- nsjconf->rl_core = njc->rlimit_core * 1024ULL * 1024ULL;
- nsjconf->rl_cpu = njc->rlimit_cpu;
- nsjconf->rl_fsize = njc->rlimit_fsize * 1024ULL * 1024ULL;
- nsjconf->rl_nofile = njc->rlimit_nofile;
- if (njc->has_rlimit_nproc) {
- nsjconf->rl_nproc = njc->rlimit_nproc;
- }
- if (njc->has_rlimit_stack) {
- nsjconf->rl_stack = njc->rlimit_stack * 1024ULL * 1024ULL;
- }
-
- if (njc->persona_addr_compat_layout) {
- nsjconf->personality |= ADDR_COMPAT_LAYOUT;
- }
- if (njc->persona_mmap_page_zero) {
- nsjconf->personality |= MMAP_PAGE_ZERO;
- }
- if (njc->persona_read_implies_exec) {
- nsjconf->personality |= READ_IMPLIES_EXEC;
- }
- if (njc->persona_addr_limit_3gb) {
- nsjconf->personality |= ADDR_LIMIT_3GB;
- }
- if (njc->persona_addr_no_randomize) {
- nsjconf->personality |= ADDR_NO_RANDOMIZE;
- }
-
- nsjconf->clone_newnet = njc->clone_newnet;
- nsjconf->clone_newuser = njc->clone_newuser;
- nsjconf->clone_newns = njc->clone_newns;
- nsjconf->clone_newpid = njc->clone_newpid;
- nsjconf->clone_newipc = njc->clone_newipc;
- nsjconf->clone_newuts = njc->clone_newuts;
- nsjconf->clone_newcgroup = njc->clone_newcgroup;
-
- for (size_t i = 0; i < njc->n_uidmap; i++) {
- if (userParseId
- (nsjconf, njc->uidmap[i]->inside_id, njc->uidmap[i]->outside_id,
- njc->uidmap[i]->count, false /* is_gid */ ,
- njc->uidmap[i]->use_newidmap) == false) {
- return false;
- }
- }
- for (size_t i = 0; i < njc->n_gidmap; i++) {
- if (userParseId
- (nsjconf, njc->gidmap[i]->inside_id, njc->gidmap[i]->outside_id,
- njc->gidmap[i]->count, true /* is_gid */ ,
- njc->gidmap[i]->use_newidmap) == false) {
- return false;
- }
- }
-
- nsjconf->mount_proc = njc->mount_proc;
- for (size_t i = 0; i < njc->n_mount; i++) {
- const char *src = njc->mount[i]->src;
- const char *src_env = njc->mount[i]->prefix_src_env;
- const char *dst = njc->mount[i]->dst;
- const char *dst_env = njc->mount[i]->prefix_dst_env;
- const char *fstype = njc->mount[i]->fstype;
- const char *options = njc->mount[i]->options;
-
- uintptr_t flags = (njc->mount[i]->rw == false) ? MS_RDONLY : 0;
- flags |= njc->mount[i]->is_bind ? (MS_BIND | MS_REC) : 0;
- bool mandatory = njc->mount[i]->mandatory;
-
- const bool *isDir =
- (njc->mount[i]->has_is_dir) ? (const bool *)&njc->mount[i]->is_dir : NULL;
-
- uint8_t *src_content = NULL;
- size_t src_content_len = 0;
- if (njc->mount[i]->has_src_content) {
- src_content = njc->mount[i]->src_content.data;
- src_content_len = njc->mount[i]->src_content.len;
- }
-
- if (mountAddMountPt
- (nsjconf, src, dst, fstype, options, flags, isDir, mandatory, src_env,
- dst_env, src_content, src_content_len, njc->mount[i]->is_symlink) == false) {
- LOG_E("Couldn't add mountpoint for src:'%s' dst:'%s'", src, dst);
- return false;
- }
- }
-
- if (njc->seccomp_policy_file) {
- if ((nsjconf->kafel_file = fopen(njc->seccomp_policy_file, "rb")) == NULL) {
- PLOG_W("Couldn't open file with seccomp policy '%s'",
- njc->seccomp_policy_file);
- return false;
- }
- }
- nsjconf->kafel_string = utilStrDup(njc->seccomp_string);
-
- nsjconf->cgroup_mem_max = njc->cgroup_mem_max;
- nsjconf->cgroup_mem_mount = utilStrDup(njc->cgroup_mem_mount);
- nsjconf->cgroup_mem_parent = utilStrDup(njc->cgroup_mem_parent);
-
- nsjconf->cgroup_pids_max = njc->cgroup_pids_max;
- nsjconf->cgroup_pids_mount = utilStrDup(njc->cgroup_pids_mount);
- nsjconf->cgroup_pids_parent = utilStrDup(njc->cgroup_pids_parent);
-
- nsjconf->iface_no_lo = njc->iface_no_lo;
- nsjconf->iface_vs = utilStrDup(njc->macvlan_iface);
- nsjconf->iface_vs_ip = utilStrDup(njc->macvlan_vs_ip);
- nsjconf->iface_vs_nm = utilStrDup(njc->macvlan_vs_nm);
- nsjconf->iface_vs_gw = utilStrDup(njc->macvlan_vs_gw);
-
- if (njc->exec_bin) {
- char **argv = utilCalloc(sizeof(const char *) * (njc->exec_bin->n_arg + 2));
- if (njc->exec_bin->arg0) {
- argv[0] = utilStrDup(njc->exec_bin->arg0);
- } else {
- argv[0] = utilStrDup(njc->exec_bin->path);
- }
- for (size_t i = 0; i < njc->exec_bin->n_arg; i++) {
- argv[i + 1] = utilStrDup(njc->exec_bin->arg[i]);
- }
- argv[njc->exec_bin->n_arg + 1] = NULL;
- nsjconf->exec_file = utilStrDup(njc->exec_bin->path);
- nsjconf->argv = argv;
- }
-
- return true;
-}
-
-bool configParse(struct nsjconf_t * nsjconf, const char *file)
-{
- LOG_I("Parsing configuration from '%s'", file);
-
- FILE *f = fopen(file, "rb");
- if (f == NULL) {
- PLOG_W("Couldn't open '%s' for reading", file);
- return false;
- }
-
- ProtobufCTextError error;
- Nsjail__NsJailConfig *njc =
- (Nsjail__NsJailConfig *) protobuf_c_text_from_file(&nsjail__ns_jail_config__descriptor,
- f, &error, NULL);
- if (njc == NULL) {
- LOG_W("Couldn't parse config from '%s': %s", file, error.error_txt);
- fclose(f);
- return false;
- }
-
- bool ret = configParseInternal(nsjconf, njc);
-
- char *config_str = protobuf_c_text_to_string((ProtobufCMessage *) njc, NULL);
- if (config_str) {
- LOG_D("Parsed config:\n%s", config_str);
- free(config_str);
- }
-
- fclose(f);
- return ret;
-}
-#endif /* !defined(NSJAIL_WITH_PROTOBUF) */
--- /dev/null
+/*
+
+ nsjail - config parsing
+ -----------------------------------------
+
+ Copyright 2017 Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+extern "C" {
+#include "common.h"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/mount.h>
+#include <sys/personality.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "caps.h"
+#include "config.h"
+#include "log.h"
+#include "mount.h"
+#include "user.h"
+#include "util.h"
+}
+
+#include <fstream>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/text_format.h>
+#include <string>
+
+#include "config.pb.h"
+
+static bool configParseInternal(struct nsjconf_t* nsjconf,
+ const nsjail::NsJailConfig& njc)
+{
+ switch (njc.mode()) {
+ case nsjail::Mode::LISTEN:
+ nsjconf->mode = MODE_LISTEN_TCP;
+ break;
+ case nsjail::Mode::ONCE:
+ nsjconf->mode = MODE_STANDALONE_ONCE;
+ break;
+ case nsjail::Mode::RERUN:
+ nsjconf->mode = MODE_STANDALONE_RERUN;
+ break;
+ case nsjail::Mode::EXECVE:
+ nsjconf->mode = MODE_STANDALONE_EXECVE;
+ break;
+ default:
+ LOG_E("Uknown running mode: %d", njc.mode());
+ return false;
+ }
+ nsjconf->chroot = njc.has_chroot_dir() ? utilStrDup(njc.chroot_dir().c_str()) : NULL;
+ nsjconf->is_root_rw = njc.is_root_rw();
+ nsjconf->hostname = njc.has_hostname() ? utilStrDup(njc.hostname().c_str()) : NULL;
+ nsjconf->cwd = njc.has_cwd() ? utilStrDup(njc.cwd().c_str()) : NULL;
+ nsjconf->port = njc.port();
+ nsjconf->bindhost = njc.has_bindhost() ? utilStrDup(njc.bindhost().c_str()) : NULL;
+ nsjconf->max_conns_per_ip = njc.max_conns_per_ip();
+ nsjconf->tlimit = njc.time_limit();
+ nsjconf->max_cpus = njc.max_cpus();
+ nsjconf->daemonize = njc.daemon();
+
+ if (njc.has_log_fd()) {
+ nsjconf->log_fd = njc.log_fd();
+ }
+ nsjconf->logfile = njc.has_log_file() ? utilStrDup(njc.log_file().c_str()) : NULL;
+ if (njc.has_log_level()) {
+ switch (njc.log_level()) {
+ case nsjail::LogLevel::DEBUG:
+ nsjconf->loglevel = DEBUG;
+ break;
+ case nsjail::LogLevel::INFO:
+ nsjconf->loglevel = INFO;
+ break;
+ case nsjail::LogLevel::WARNING:
+ nsjconf->loglevel = WARNING;
+ break;
+ case nsjail::LogLevel::ERROR:
+ nsjconf->loglevel = ERROR;
+ break;
+ case nsjail::LogLevel::FATAL:
+ nsjconf->loglevel = FATAL;
+ break;
+ default:
+ LOG_E("Unknown log_level: %d", njc.log_level());
+ return false;
+ }
+ }
+
+ if (njc.has_log_fd() || njc.has_log_file() || njc.has_log_level()) {
+ if (logInitLogFile(nsjconf) == false) {
+ return false;
+ }
+ }
+
+ nsjconf->keep_env = njc.keep_env();
+ for (ssize_t i = 0; i < njc.envar_size(); i++) {
+ struct charptr_t* p = reinterpret_cast<charptr_t*>(utilMalloc(sizeof(struct charptr_t)));
+ p->val = utilStrDup(njc.envar(i).c_str());
+ TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers);
+ }
+
+ nsjconf->keep_caps = njc.keep_caps();
+ for (ssize_t i = 0; i < njc.cap_size(); i++) {
+ struct ints_t* f = reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
+ f->val = capsNameToVal(njc.cap(i).c_str());
+ if (f->val == -1) {
+ return false;
+ }
+ TAILQ_INSERT_HEAD(&nsjconf->caps, f, pointers);
+ }
+
+ nsjconf->is_silent = njc.silent();
+ nsjconf->skip_setsid = njc.skip_setsid();
+
+ for (ssize_t i = 0; i < njc.pass_fd_size(); i++) {
+ struct ints_t* f = reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
+ f->val = njc.pass_fd(i);
+ TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
+ }
+
+ nsjconf->disable_no_new_privs = njc.disable_no_new_privs();
+
+ nsjconf->rl_as = njc.rlimit_as() * 1024ULL * 1024ULL;
+ nsjconf->rl_core = njc.rlimit_core() * 1024ULL * 1024ULL;
+ nsjconf->rl_cpu = njc.rlimit_cpu();
+ nsjconf->rl_fsize = njc.rlimit_fsize() * 1024ULL * 1024ULL;
+ nsjconf->rl_nofile = njc.rlimit_nofile();
+ if (njc.has_rlimit_nproc()) {
+ nsjconf->rl_nproc = njc.rlimit_nproc();
+ }
+ if (njc.has_rlimit_stack()) {
+ nsjconf->rl_stack = njc.rlimit_stack() * 1024ULL * 1024ULL;
+ }
+
+ if (njc.persona_addr_compat_layout()) {
+ nsjconf->personality |= ADDR_COMPAT_LAYOUT;
+ }
+ if (njc.persona_mmap_page_zero()) {
+ nsjconf->personality |= MMAP_PAGE_ZERO;
+ }
+ if (njc.persona_read_implies_exec()) {
+ nsjconf->personality |= READ_IMPLIES_EXEC;
+ }
+ if (njc.persona_addr_limit_3gb()) {
+ nsjconf->personality |= ADDR_LIMIT_3GB;
+ }
+ if (njc.persona_addr_no_randomize()) {
+ nsjconf->personality |= ADDR_NO_RANDOMIZE;
+ }
+
+ nsjconf->clone_newnet = njc.clone_newnet();
+ nsjconf->clone_newuser = njc.clone_newuser();
+ nsjconf->clone_newns = njc.clone_newns();
+ nsjconf->clone_newpid = njc.clone_newpid();
+ nsjconf->clone_newipc = njc.clone_newipc();
+ nsjconf->clone_newuts = njc.clone_newuts();
+ nsjconf->clone_newcgroup = njc.clone_newcgroup();
+
+ for (ssize_t i = 0; i < njc.uidmap_size(); i++) {
+ if (userParseId(
+ nsjconf,
+ njc.uidmap(i).has_inside_id() ? njc.uidmap(i).inside_id().c_str()
+ : NULL,
+ njc.uidmap(i).has_outside_id() ? njc.uidmap(i).outside_id().c_str()
+ : NULL,
+ njc.uidmap(i).count(), false /* is_gid */,
+ njc.uidmap(i).use_newidmap())
+ == false) {
+ return false;
+ }
+ }
+ for (ssize_t i = 0; i < njc.gidmap_size(); i++) {
+ if (userParseId(
+ nsjconf,
+ njc.gidmap(i).has_inside_id() ? njc.gidmap(i).inside_id().c_str()
+ : NULL,
+ njc.gidmap(i).has_outside_id() ? njc.gidmap(i).outside_id().c_str()
+ : NULL,
+ njc.gidmap(i).count(), true /* is_gid */,
+ njc.gidmap(i).use_newidmap())
+ == false) {
+ return false;
+ }
+ }
+
+ nsjconf->mount_proc = njc.mount_proc();
+ for (ssize_t i = 0; i < njc.mount_size(); i++) {
+ const char* src = (njc.mount(i).has_src()) ? njc.mount(i).src().c_str() : NULL;
+ const char* src_env = (njc.mount(i).has_prefix_src_env()) ? njc.mount(i).prefix_src_env().c_str() : NULL;
+ const char* dst = (njc.mount(i).has_dst()) ? njc.mount(i).dst().c_str() : NULL;
+ const char* dst_env = (njc.mount(i).has_prefix_dst_env()) ? njc.mount(i).prefix_dst_env().c_str() : NULL;
+ const char* fstype = (njc.mount(i).has_fstype()) ? njc.mount(i).fstype().c_str() : NULL;
+ const char* options = (njc.mount(i).has_options()) ? njc.mount(i).options().c_str() : NULL;
+
+ uintptr_t flags = (njc.mount(i).rw() == false) ? MS_RDONLY : 0;
+ flags |= njc.mount(i).is_bind() ? (MS_BIND | MS_REC) : 0;
+ bool mandatory = njc.mount(i).mandatory();
+
+ const bool isDir = (njc.mount(i).has_is_dir() && njc.mount(i).is_dir()) ? true : false;
+ const bool* isDirPtr = (njc.mount(i).has_is_dir()) ? &isDir : NULL;
+
+ const char* src_content = NULL;
+ size_t src_content_len = 0;
+ if (njc.mount(i).has_src_content()) {
+ src_content = njc.mount(i).src_content().data();
+ src_content_len = njc.mount(i).src_content().size();
+ }
+
+ if (mountAddMountPt(nsjconf, src, dst, fstype, options, flags, isDirPtr,
+ mandatory, src_env, dst_env, src_content,
+ src_content_len, njc.mount(i).is_symlink())
+ == false) {
+ LOG_E("Couldn't add mountpoint for src:'%s' dst:'%s'", src, dst);
+ return false;
+ }
+ }
+
+ if (njc.has_seccomp_policy_file()) {
+ if ((nsjconf->kafel_file = fopen(njc.seccomp_policy_file().c_str(), "rb")) == NULL) {
+ PLOG_W("Couldn't open file with seccomp policy '%s'",
+ njc.seccomp_policy_file().c_str());
+ return false;
+ }
+ }
+
+ std::string kafel_string;
+ for (ssize_t i = 0; i < njc.seccomp_string().size(); i++) {
+ kafel_string += njc.seccomp_string(i);
+ }
+ nsjconf->kafel_string = njc.seccomp_string().size() > 0
+ ? utilStrDup(kafel_string.c_str())
+ : NULL;
+
+ nsjconf->cgroup_mem_max = njc.cgroup_mem_max();
+ nsjconf->cgroup_mem_mount = njc.has_cgroup_mem_mount()
+ ? utilStrDup(njc.cgroup_mem_mount().c_str())
+ : NULL;
+ nsjconf->cgroup_mem_parent = njc.has_cgroup_mem_parent()
+ ? utilStrDup(njc.cgroup_mem_parent().c_str())
+ : NULL;
+
+ nsjconf->cgroup_pids_max = njc.cgroup_pids_max();
+ nsjconf->cgroup_pids_mount = njc.has_cgroup_pids_mount()
+ ? utilStrDup(njc.cgroup_pids_mount().c_str())
+ : NULL;
+ nsjconf->cgroup_pids_parent = njc.has_cgroup_pids_parent()
+ ? utilStrDup(njc.cgroup_pids_parent().c_str())
+ : NULL;
+
+ nsjconf->iface_no_lo = njc.iface_no_lo();
+ nsjconf->iface_vs = njc.has_macvlan_iface() ? utilStrDup(njc.macvlan_iface().c_str()) : NULL;
+ nsjconf->iface_vs_ip = njc.has_macvlan_vs_ip() ? utilStrDup(njc.macvlan_vs_ip().c_str()) : NULL;
+ nsjconf->iface_vs_nm = njc.has_macvlan_vs_nm() ? utilStrDup(njc.macvlan_vs_nm().c_str()) : NULL;
+ nsjconf->iface_vs_gw = njc.has_macvlan_vs_gw() ? utilStrDup(njc.macvlan_vs_gw().c_str()) : NULL;
+
+ if (njc.has_exec_bin()) {
+ char** argv = reinterpret_cast<char**>(utilCalloc(sizeof(const char*) * (njc.exec_bin().arg().size() + 2)));
+ if (njc.exec_bin().has_arg0()) {
+ argv[0] = utilStrDup(njc.exec_bin().arg0().c_str());
+ } else {
+ argv[0] = utilStrDup(njc.exec_bin().path().c_str());
+ }
+ for (ssize_t i = 0; i < njc.exec_bin().arg().size(); i++) {
+ argv[i + 1] = utilStrDup(njc.exec_bin().arg(i).c_str());
+ }
+ argv[njc.exec_bin().arg().size() + 1] = NULL;
+ nsjconf->exec_file = njc.exec_bin().has_path()
+ ? utilStrDup(njc.exec_bin().path().c_str())
+ : NULL;
+ nsjconf->argv = argv;
+ }
+
+ return true;
+}
+
+static void LogHandler(google::protobuf::LogLevel level, const char* filename, int line, const std::string& message)
+{
+ LOG_W("config.cc: '%s'", message.c_str());
+}
+
+extern "C" bool configParse(struct nsjconf_t* nsjconf, const char* file)
+{
+ LOG_I("Parsing configuration from '%s'", file);
+
+ int fd = open(file, O_RDONLY);
+ if (fd == -1) {
+ PLOG_W("Couldn't open config file '%s'", file);
+ return false;
+ }
+
+ SetLogHandler(LogHandler);
+ google::protobuf::io::FileInputStream input(fd);
+ input.SetCloseOnDelete(true);
+
+ nsjail::NsJailConfig nsc;
+
+ auto parser = google::protobuf::TextFormat::Parser();
+
+ if (!parser.Parse(&input, &nsc)) {
+ LOG_W("Couldn't parse file '%s' from Text into ProtoBuf", file);
+ return false;
+ }
+ if (!configParseInternal(nsjconf, nsc)) {
+ LOG_W("Couldn't parse the ProtoBuf");
+ return false;
+ }
+ LOG_D("Parsed config:\n'%s'", nsc.DebugString().c_str());
+
+ return true;
+}
#ifndef NS_CONFIG_H
#define NS_CONFIG_H
-#include "common.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
-bool configParse(struct nsjconf_t *nsjconf, const char *file);
+#include "common.h"
+ bool configParse(struct nsjconf_t *nsjconf, const char *file);
+#ifdef __cplusplus
+} // extern "C"
+#endif
#endif /* NS_CONFIG_H */
message IdMap
{
/* Empty string means "current uid/gid" */
- required string inside_id = 1 [ default = "" ];
- required string outside_id = 2 [ default = "" ];
+ optional string inside_id = 1 [ default = "" ];
+ optional string outside_id = 2 [ default = "" ];
/* See 'man user_namespaces' for the meaning of count */
- required uint32 count = 3 [ default = 1 ];
+ optional uint32 count = 3 [ default = 1 ];
/* Does this map use /usr/bin/new[u|g]idmap binary? */
- required bool use_newidmap = 4 [ default = false ];
+ optional bool use_newidmap = 4 [ default = false ];
}
message MountPt
{
/* Can be empty for mount --bind mounts */
optional string fstype = 6 [ default = "" ];
/* E.g. size=5000000 for 'tmpfs' */
- required string options = 7 [ default = "" ];
+ optional string options = 7 [ default = "" ];
/* Is it 'mount --bind src dst' type of mount */
- required bool is_bind = 8 [ default = false ];
+ optional bool is_bind = 8 [ default = false ];
/* It it R/W mount */
- required bool rw = 9 [ default = false ];
+ optional bool rw = 9 [ default = false ];
/* Is it directory? If not specified an internal
heuristics will be used to determine that */
optional bool is_dir = 10;
/* Should the sandboxing fail if we cannot mount this resource? */
- required bool mandatory = 11 [ default = true ];
+ optional bool mandatory = 11 [ default = true ];
/* Is it a symlink (instead of real mount point)? */
- required bool is_symlink = 12 [ default = false ];
+ optional bool is_symlink = 12 [ default = false ];
}
message Exe
{
{
/* Optional name and description for this config */
optional string name = 1 [ default = "" ];
- optional string description = 2 [ default = "" ];
+ repeated string description = 2;
/* Execution mode: see 'msg Mode' description for more */
- required Mode mode = 3 [ default = ONCE ];
+ optional Mode mode = 3 [ default = ONCE ];
/* Equivalent to a bind mount with dst='/' */
optional string chroot_dir = 4;
/* Applies both to the chroot_dir and to /proc mounts */
- required bool is_root_rw = 5 [ default = false ];
+ optional bool is_root_rw = 5 [ default = false ];
/* Hostname inside jail */
- required string hostname = 8 [ default = "NSJAIL" ];
+ optional string hostname = 8 [ default = "NSJAIL" ];
/* Initial current working directory for the binary */
- required string cwd = 9 [ default = "/" ];
+ optional string cwd = 9 [ default = "/" ];
/* TCP port to listen to. Valid with mode=LISTEN only */
- required uint32 port = 10 [ default = 0 ];
+ optional uint32 port = 10 [ default = 0 ];
/* Host to bind to for mode=LISTEN. Must be in IPv6 format */
- required string bindhost = 11 [ default = "::" ];
+ optional string bindhost = 11 [ default = "::" ];
/* For mode=LISTEN, maximum number of connections from a single IP */
- required uint32 max_conns_per_ip = 12 [ default = 0 ];
+ optional uint32 max_conns_per_ip = 12 [ default = 0 ];
/* Wall-time time limit for commands */
- required uint32 time_limit = 13 [ default = 600 ];
+ optional uint32 time_limit = 13 [ default = 600 ];
/* Should nsjail go into background? */
- required bool daemon = 14 [ default = false ];
+ optional bool daemon = 14 [ default = false ];
/* Maximum number of CPUs to use: 0 - no limit */
- required uint32 max_cpus = 15;
+ optional uint32 max_cpus = 15 [ default = 0 ];
/* FD to log to. */
optional int32 log_fd = 16;
/* Should the current environment variables be kept
when executing the binary */
- required bool keep_env = 19 [ default = false ];
+ optional bool keep_env = 19 [ default = false ];
/* EnvVars to be set before executing binaries */
repeated string envar = 20;
/* Should capabilities be preserved or dropped */
- required bool keep_caps = 21 [ default = false ];
+ optional bool keep_caps = 21 [ default = false ];
/* Which capabilities should be preserved if keep_caps == false.
Format: "CAP_SYS_PTRACE" */
repeated string cap = 63;
/* Should nsjail close FD=0,1,2 before executing the process */
- required bool silent = 22 [ default = false ];
+ optional bool silent = 22 [ default = false ];
/* Should the child process have control over terminal?
Can be useful to allow /bin/sh to provide
job control / signals */
- required bool skip_setsid = 23 [ default = false ];
+ optional bool skip_setsid = 23 [ default = false ];
/* Which FDs should be passed to the newly executed process
By default only FD=0,1,2 are passed */
repeated int32 pass_fd = 24;
/* Setting it to true will allow to have set-uid binaries
inside the jail */
- required bool disable_no_new_privs = 25 [ default = false ];
+ optional bool disable_no_new_privs = 25 [ default = false ];
- required uint64 rlimit_as = 26 [ default = 512 ]; /* In MiB */
- required uint64 rlimit_core = 27 [ default = 0 ]; /* In MiB */
- required uint64 rlimit_cpu = 28 [ default = 600 ]; /* In seconds */
- required uint64 rlimit_fsize = 29 [ default = 1 ]; /* In MiB */
- required uint64 rlimit_nofile = 30 [ default = 32 ];
+ optional uint64 rlimit_as = 26 [ default = 512 ]; /* In MiB */
+ optional uint64 rlimit_core = 27 [ default = 0 ]; /* In MiB */
+ optional uint64 rlimit_cpu = 28 [ default = 600 ]; /* In seconds */
+ optional uint64 rlimit_fsize = 29 [ default = 1 ]; /* In MiB */
+ optional uint64 rlimit_nofile = 30 [ default = 32 ];
optional uint64 rlimit_nproc = 31; /* This is system-wide: tricky to use */
optional uint64 rlimit_stack = 32; /* In MiB */
/* See 'man personality' for more */
- required bool persona_addr_compat_layout = 33 [ default = false ];
- required bool persona_mmap_page_zero = 34 [ default = false ];
- required bool persona_read_implies_exec = 35 [ default = false ];
- required bool persona_addr_limit_3gb = 36 [ default = false ];
- required bool persona_addr_no_randomize = 37 [ default = false ];
+ optional bool persona_addr_compat_layout = 33 [ default = false ];
+ optional bool persona_mmap_page_zero = 34 [ default = false ];
+ optional bool persona_read_implies_exec = 35 [ default = false ];
+ optional bool persona_addr_limit_3gb = 36 [ default = false ];
+ optional bool persona_addr_no_randomize = 37 [ default = false ];
/* Which name-spaces should be used? */
- required bool clone_newnet = 38 [ default = true ];
- required bool clone_newuser = 39 [ default = true ];
- required bool clone_newns = 40 [ default = true ];
- required bool clone_newpid = 41 [ default = true ];
- required bool clone_newipc = 42 [ default = true ];
- required bool clone_newuts = 43 [ default = true ];
+ optional bool clone_newnet = 38 [ default = true ];
+ optional bool clone_newuser = 39 [ default = true ];
+ optional bool clone_newns = 40 [ default = true ];
+ optional bool clone_newpid = 41 [ default = true ];
+ optional bool clone_newipc = 42 [ default = true ];
+ optional bool clone_newuts = 43 [ default = true ];
/* It's only supported in newer kernels, hence disabled by default */
- required bool clone_newcgroup = 44 [ default = false ];
+ optional bool clone_newcgroup = 44 [ default = false ];
/* Mappings for UIDs and GIDs. See the description for 'msg IdMap'
for more */
/* Should /proc be mounted (R/O)? This can also be added in the 'mount'
section below */
- required bool mount_proc = 47 [ default = false ];
+ optional bool mount_proc = 47 [ default = false ];
/* Mount points inside the jail. See the description for 'msg MountPt'
for more */
repeated MountPt mount = 48;
/* Kafel seccomp-bpf policy file or a string:
Homepage of the project: https://github.com/google/kafel */
optional string seccomp_policy_file = 49;
- optional string seccomp_string = 50;
+ repeated string seccomp_string = 50;
/* If > 0, maximum cumulative size of RAM used inside any jail */
- required uint64 cgroup_mem_max = 51 [ default = 0 ]; /* In MiB */
+ optional uint64 cgroup_mem_max = 51 [ default = 0 ]; /* In MiB */
/* Mount point for cgroups-memory in your system */
- required string cgroup_mem_mount = 52 [ default = "/sys/fs/cgroup/memory" ];
+ optional string cgroup_mem_mount = 52 [ default = "/sys/fs/cgroup/memory" ];
/* Writeable directory (for the nsjail user) under cgroup_mem_mount */
- required string cgroup_mem_parent = 53 [ default = "NSJAIL" ];
+ optional string cgroup_mem_parent = 53 [ default = "NSJAIL" ];
/* If > 0, maximum number of PIDs (threads/processes) inside jail */
- required uint64 cgroup_pids_max = 54 [ default = 0 ];
+ optional uint64 cgroup_pids_max = 54 [ default = 0 ];
/* Mount point for cgroups-pids in your system */
- required string cgroup_pids_mount = 55 [ default = "/sys/fs/cgroup/pids" ];
+ optional string cgroup_pids_mount = 55 [ default = "/sys/fs/cgroup/pids" ];
/* Writeable directory (for the nsjail user) under cgroup_pids_mount */
- required string cgroup_pids_parent = 56 [ default = "NSJAIL" ];
+ optional string cgroup_pids_parent = 56 [ default = "NSJAIL" ];
/* Should the 'lo' interface be brought up (active) inside this jail? */
- required bool iface_no_lo = 57 [ default = false ];
+ optional bool iface_no_lo = 57 [ default = false ];
/* Parameters for the cloned MACVLAN interface inside jail */
optional string macvlan_iface = 58; /* Interface to be cloned, eg 'eth0' */
- required string macvlan_vs_ip = 59 [ default = "192.168.0.2" ];
- required string macvlan_vs_nm = 60 [ default = "255.255.255.0" ];
- required string macvlan_vs_gw = 61 [ default = "192.168.0.1" ];
+ optional string macvlan_vs_ip = 59 [ default = "192.168.0.2" ];
+ optional string macvlan_vs_nm = 60 [ default = "255.255.255.0" ];
+ optional string macvlan_vs_gw = 61 [ default = "192.168.0.1" ];
/* Binary path (with arguments) to be executed. If not specified here, it
can be specified with cmd-line as "-- /path/to/command arg1 arg2" */
name: "apache-with-cloned-net"
-description: "
-Tested under Ubuntu 17.04. Other Linux distros might use different
-locations for the Apache's HTTPD configuration files and system
-libraries.
-
-On the basis of (GitHub's) @farconada work in:
-https://github.com/google/nsjail/issues/31
-
-Run as: sudo ./nsjail --config configs/apache.cfg
-"
+description: "Tested under Ubuntu 17.04. Other Linux distros might "
+description: "use different locations for the Apache's HTTPD configuration "
+description: "files and system libraries"
+description: "Run as: sudo ./nsjail --config configs/apache.cfg"
mode: ONCE
hostname: "APACHE-NSJ"
rlimit_as: 1024
rlimit_fsize: 1024
-rlimit_cpu: -1
+rlimit_cpu: 18446744073709551615
rlimit_nofile: 64
time_limit: 0
is_bind: true
}
-seccomp_string: "
- POLICY example {
- KILL {
- ptrace,
- process_vm_readv,
- process_vm_writev
- }
- }
- USE example DEFAULT ALLOW
-"
+seccomp_string: "seccomp_string: "
+seccomp_string: " POLICY example {"
+seccomp_string: " KILL {"
+seccomp_string: " ptrace,"
+seccomp_string: " process_vm_readv,"
+seccomp_string: " process_vm_writev"
+seccomp_string: " }"
+seccomp_string: " }"
+seccomp_string: " USE example DEFAULT ALLOW"
macvlan_iface: "enp0s31f6"
macvlan_vs_ip: "192.168.10.223"
name: "bash-with-fake-geteuid"
-description:
-"An example/demo policy which allows to execute /bin/bash and other commands in
-a fairly restricted jail containing only some directories from the main
-system, and with blocked __NR_syslog syscall. Also, __NR_geteuid returns -1337
-value, which /usr/bin/id will show as euid=4294965959, and ptrace is blocked
-but returns success, hence strange behavior of the strace command.
-
-This is an example/demo policy, hence it repeats many default values from the
-https://github.com/google/nsjail/blob/master/config.proto PB schema"
+description: "An example/demo policy which allows to execute /bin/bash and other commands in "
+description: "a fairly restricted jail containing only some directories from the main "
+description: "system, and with blocked __NR_syslog syscall. Also, __NR_geteuid returns -1337 "
+description: "value, which /usr/bin/id will show as euid=4294965959, and ptrace is blocked "
+description: "but returns success, hence strange behavior of the strace command. "
+description: "This is an example/demo policy, hence it repeats many default values from the "
+description: "https://github.com/google/nsjail/blob/master/config.proto PB schema "
mode: ONCE
hostname: "JAILED-BASH"
mandatory: false
}
-seccomp_string: "
- POLICY example {
- ERRNO(1337) { geteuid },
- KILL { syslog },
- ERRNO(0) { ptrace }
- }
- USE example DEFAULT ALLOW
-"
+seccomp_string: "POLICY example { "
+seccomp_string: " ERRNO(1337) { geteuid }, "
+seccomp_string: " "
+seccomp_string: " KILL { syslog }, "
+seccomp_string: " ERRNO(0) { ptrace } "
+seccomp_string: "} "
+seccomp_string: "USE example DEFAULT ALLOW "
exec_bin {
path: "/bin/bash"
name: "chrome-with-net"
-description: "
-Don't use for anything serious - this is just a demo policy. See notes
-at the end of this description for more.
-This policy allows to run Chrome inside a jail. Access to networking is
-permitted with this setup (clone_newnet: false).
-
-The only permitted home directory is $HOME/.mozilla and $HOME/Documents.
-The rest of available on the FS files/dires are libs and X-related files/dirs.
-
-Run as:
-
-./nsjail --config configs/chrome-with-net.cfg
-
-You can then go to https://uploadfiles.io/ and try to upload a file in order
-to see how your local directory (also, all system directories) look like.
-
-Note: Using this profile for anything serious is *A VERY BAD* idea. Chrome
-provides excellent FS&syscall sandbox for Linux, as this profile disables
-this sandboxing with --no-sandbox and substitutes Chrome's syscall/ns policy
-with more relaxed namespacing.
-"
+description: "Don't use for anything serious - this is just a demo policy. See notes"
+description: "at the end of this description for more."
+description: ""
+description: "This policy allows to run Chrome inside a jail. Access to networking is"
+description: "permitted with this setup (clone_newnet: false)."
+description: ""
+description: "The only permitted home directory is $HOME/.mozilla and $HOME/Documents."
+description: "The rest of available on the FS files/dires are libs and X-related files/dirs."
+description: ""
+description: "Run as:"
+description: ""
+description: "./nsjail --config configs/chrome-with-net.cfg"
+description: ""
+description: "You can then go to https://uploadfiles.io/ and try to upload a file in order"
+description: "to see how your local directory (also, all system directories) look like."
+description: ""
+description: "Note: Using this profile for anything serious is *A VERY BAD* idea. Chrome"
+description: "provides excellent FS&syscall sandbox for Linux, as this profile disables"
+description: "this sandboxing with --no-sandbox and substitutes Chrome's syscall/ns policy"
+description: "with more relaxed namespacing."
mode: ONCE
hostname: "CHROME"
is_bind: true
}
-seccomp_string: "
- POLICY example {
- KILL {
- ptrace,
- process_vm_readv,
- process_vm_writev
- }
- }
- USE example DEFAULT ALLOW
-"
+seccomp_string: " POLICY example {"
+seccomp_string: " KILL {"
+seccomp_string: " ptrace,"
+seccomp_string: " process_vm_readv,"
+seccomp_string: " process_vm_writev"
+seccomp_string: " }"
+seccomp_string: " }"
+seccomp_string: " USE example DEFAULT ALLOW"
exec_bin {
path: "/opt/google/chrome/google-chrome"
name: "firefox-with-cloned-net"
-description: "
-This policy allows to run firefox inside a jail on a separate eth interface.
-A separate networking context separates process from the global \"lo\", and
-from global abstract socket namespace.
-The only permitted home directory is $HOME/.mozilla and $HOME/Documents.
-The rest of available on the FS files/dires are libs and X-related files/dirs.
-
-As this needs to be run as root, you will have to set-up correct uid&gid
-mappings (here: 'jagger'), name of your local interface (here: 'enp0s31f6'),
-and correct IPv4 addresses.
-
-IPv6 should work out-of-the-box, given that your local IPv6 discovery is set
-up correctly.
-
-Run as:
-
-sudo ./nsjail --config configs/firefox-with-cloned-net.cfg
-
-You can then go to https://uploadfiles.io/ and try to upload a file in order
-to see how your local directory (also, all system directories) look like.
-"
+description: "This policy allows to run firefox inside a jail on a separate eth interface."
+description: "A separate networking context separates process from the global \"lo\", and"
+description: "from global abstract socket namespace."
+description: ""
+description: "The only permitted home directory is $HOME/.mozilla and $HOME/Documents."
+description: "The rest of available on the FS files/dires are libs and X-related files/dirs."
+description: ""
+description: "As this needs to be run as root, you will have to set-up correct uid&gid"
+description: "mappings (here: 'jagger'), name of your local interface (here: 'enp0s31f6'),"
+description: "and correct IPv4 addresses."
+description: ""
+description: "IPv6 should work out-of-the-box, given that your local IPv6 discovery is set"
+description: "up correctly."
+description: ""
+description: "Run as:"
+description: ""
+description: "sudo ./nsjail --config configs/firefox-with-cloned-net.cfg"
+description: ""
+description: "You can then go to https://uploadfiles.io/ and try to upload a file in order"
+description: "to see how your local directory (also, all system directories) look like."
mode: ONCE
hostname: "FF-MACVTAP"
is_bind: true
}
-seccomp_string: "
- POLICY example {
- KILL {
- ptrace,
- process_vm_readv,
- process_vm_writev
- }
- }
- USE example DEFAULT ALLOW
-"
+seccomp_string: " POLICY example {"
+seccomp_string: " KILL {"
+seccomp_string: " ptrace,"
+seccomp_string: " process_vm_readv,"
+seccomp_string: " process_vm_writev"
+seccomp_string: " }"
+seccomp_string: " }"
+seccomp_string: " USE example DEFAULT ALLOW"
macvlan_iface: "enp0s31f6"
macvlan_vs_ip: "192.168.10.223"
name: "firefox-with-net"
-description: "
-This policy allows to run firefox inside a jail. Access to networking is
-permitted with this setup (clone_newnet: false).
-The only permitted home directory is $HOME/.mozilla and $HOME/Documents.
-The rest of available on the FS files/dires are libs and X-related files/dirs.
-
-Run as:
-
-./nsjail --config configs/firefox-with-net.cfg
-
-You can then go to https://uploadfiles.io/ and try to upload a file in order
-to see how your local directory (also, all system directories) look like.
-"
+description: "This policy allows to run firefox inside a jail. Access to networking is"
+description: "permitted with this setup (clone_newnet: false)."
+description: ""
+description: "The only permitted home directory is $HOME/.mozilla and $HOME/Documents."
+description: "The rest of available on the FS files/dires are libs and X-related files/dirs."
+description: ""
+description: "Run as:"
+description: ""
+description: "./nsjail --config configs/firefox-with-net.cfg"
+description: ""
+description: "You can then go to https://uploadfiles.io/ and try to upload a file in order"
+description: "to see how your local directory (also, all system directories) look like."
mode: ONCE
hostname: "FIREFOX"
is_bind: true
}
-seccomp_string: "
- POLICY example {
- KILL {
- ptrace,
- process_vm_readv,
- process_vm_writev
- }
- }
- USE example DEFAULT ALLOW
-"
+seccomp_string: " POLICY example {"
+seccomp_string: " KILL {"
+seccomp_string: " ptrace,"
+seccomp_string: " process_vm_readv,"
+seccomp_string: " process_vm_writev"
+seccomp_string: " }"
+seccomp_string: " }"
+seccomp_string: " USE example DEFAULT ALLOW"
exec_bin {
path: "/usr/lib/firefox/firefox"
name: "documents-with-xorg"
-description: "
-This policy allows to run many X-org based tool, which are allowed
-to access $HOME/Documents directory only. An example of use is:
-./nsjail --config configs/documents-with-xorg.cfg -- \\
- /usr/bin/geeqie /user/Documents/
-
-What is more, this policy doesn't allow to access networking.
-"
+description: "This policy allows to run many X-org based tool, which are allowed"
+description: "to access $HOME/Documents directory only. An example of use is:"
+description: ""
+description: "./nsjail --config configs/documents-with-xorg.cfg -- \\"
+description: " /usr/bin/geeqie /user/Documents/"
+description: ""
+description: "What is more, this policy doesn't allow to access networking."
mode: ONCE
hostname: "NSJAIL"
is_bind: true
}
-seccomp_string: "
- POLICY example {
- KILL {
- ptrace,
- process_vm_readv,
- process_vm_writev
- }
- }
- USE example DEFAULT ALLOW
-"
+seccomp_string: " POLICY example {"
+seccomp_string: " KILL {"
+seccomp_string: " ptrace,"
+seccomp_string: " process_vm_readv,"
+seccomp_string: " process_vm_writev"
+seccomp_string: " }"
+seccomp_string: " }"
+seccomp_string: " USE example DEFAULT ALLOW"
name: "imagemagick-convert"
-description: "
-This policy allows to run ImageMagick's convert inside a jail.
-Your $HOME's Documents will be mapped as /user/Documents
-Run as:
-
-./nsjail --config imagemagick-convert.cfg -- /usr/bin/convert \\
- jpg:/user/Documents/input.jpg png:/user/Documents/output.png
-"
+description: "This policy allows to run ImageMagick's convert inside a jail."
+description: "Your $HOME's Documents will be mapped as /user/Documents"
+description: ""
+description: "Run as:"
+description: ""
+description: "./nsjail --config imagemagick-convert.cfg -- /usr/bin/convert \\"
+description: " jpg:/user/Documents/input.jpg png:/user/Documents/output.png"
mode: ONCE
hostname: "IM-CONVERT"
mandatory: false
}
-seccomp_string: "
- POLICY example {
- KILL {
- ptrace,
- process_vm_readv,
- process_vm_writev
- }
- }
- USE example DEFAULT ALLOW
-"
+seccomp_string: " POLICY example {"
+seccomp_string: " KILL {"
+seccomp_string: " ptrace,"
+seccomp_string: " process_vm_readv,"
+seccomp_string: " process_vm_writev"
+seccomp_string: " }"
+seccomp_string: " }"
+seccomp_string: " USE example DEFAULT ALLOW"
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
-#include <sys/types.h>
#include <sys/syscall.h>
+#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/sched.h>
#include <sched.h>
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include "subproc.h"
#include "util.h"
-#define VALSTR_STRUCT(x) { x, #x }
+#define VALSTR_STRUCT(x) \
+ { \
+ x, #x \
+ }
#if !defined(MS_LAZYTIME)
-#define MS_LAZYTIME (1<<25)
+#define MS_LAZYTIME (1 << 25)
#endif /* if !defined(MS_LAZYTIME) */
const char *mountFlagsToStr(uintptr_t flags)
static __thread char mountFlagsStr[1024];
mountFlagsStr[0] = '\0';
- /* *INDENT-OFF* */
- static struct {
- const uintptr_t flag;
- const char* const name;
- } const mountFlags[] = {
- VALSTR_STRUCT(MS_RDONLY),
- VALSTR_STRUCT(MS_NOSUID),
- VALSTR_STRUCT(MS_NODEV),
- VALSTR_STRUCT(MS_NOEXEC),
- VALSTR_STRUCT(MS_SYNCHRONOUS),
- VALSTR_STRUCT(MS_REMOUNT),
- VALSTR_STRUCT(MS_MANDLOCK),
- VALSTR_STRUCT(MS_DIRSYNC),
- VALSTR_STRUCT(MS_NOATIME),
- VALSTR_STRUCT(MS_NODIRATIME),
- VALSTR_STRUCT(MS_BIND),
- VALSTR_STRUCT(MS_MOVE),
- VALSTR_STRUCT(MS_REC),
- VALSTR_STRUCT(MS_SILENT),
- VALSTR_STRUCT(MS_POSIXACL),
- VALSTR_STRUCT(MS_UNBINDABLE),
- VALSTR_STRUCT(MS_PRIVATE),
- VALSTR_STRUCT(MS_SLAVE),
- VALSTR_STRUCT(MS_SHARED),
- VALSTR_STRUCT(MS_RELATIME),
- VALSTR_STRUCT(MS_KERNMOUNT),
- VALSTR_STRUCT(MS_I_VERSION),
- VALSTR_STRUCT(MS_STRICTATIME),
- VALSTR_STRUCT(MS_LAZYTIME),
- };
- /* *INDENT-ON* */
+ /* *INDENT-OFF* */
+ static struct {
+ const uintptr_t flag;
+ const char* const name;
+ } const mountFlags[] = {
+ VALSTR_STRUCT(MS_RDONLY),
+ VALSTR_STRUCT(MS_NOSUID),
+ VALSTR_STRUCT(MS_NODEV),
+ VALSTR_STRUCT(MS_NOEXEC),
+ VALSTR_STRUCT(MS_SYNCHRONOUS),
+ VALSTR_STRUCT(MS_REMOUNT),
+ VALSTR_STRUCT(MS_MANDLOCK),
+ VALSTR_STRUCT(MS_DIRSYNC),
+ VALSTR_STRUCT(MS_NOATIME),
+ VALSTR_STRUCT(MS_NODIRATIME),
+ VALSTR_STRUCT(MS_BIND),
+ VALSTR_STRUCT(MS_MOVE),
+ VALSTR_STRUCT(MS_REC),
+ VALSTR_STRUCT(MS_SILENT),
+ VALSTR_STRUCT(MS_POSIXACL),
+ VALSTR_STRUCT(MS_UNBINDABLE),
+ VALSTR_STRUCT(MS_PRIVATE),
+ VALSTR_STRUCT(MS_SLAVE),
+ VALSTR_STRUCT(MS_SHARED),
+ VALSTR_STRUCT(MS_RELATIME),
+ VALSTR_STRUCT(MS_KERNMOUNT),
+ VALSTR_STRUCT(MS_I_VERSION),
+ VALSTR_STRUCT(MS_STRICTATIME),
+ VALSTR_STRUCT(MS_LAZYTIME),
+ };
+ /* *INDENT-ON* */
for (size_t i = 0; i < ARRAYSIZE(mountFlags); i++) {
if (flags & mountFlags[i].flag) {
bool mountAddMountPt(struct nsjconf_t * nsjconf, const char *src, const char *dst,
const char *fstype, const char *options, uintptr_t flags, const bool * isDir,
bool mandatory, const char *src_env, const char *dst_env,
- const uint8_t * src_content, size_t src_content_len, bool is_symlink)
+ const char *src_content, size_t src_content_len, bool is_symlink)
{
struct mounts_t *p = utilCalloc(sizeof(struct mounts_t));
}
}
- p->src_content = utilMemDup(src_content, src_content_len);
+ p->src_content = utilMemDup((const uint8_t *)src_content, src_content_len);
p->src_content_len = src_content_len;
TAILQ_INSERT_TAIL(&nsjconf->mountpts, p, pointers);
bool mountAddMountPt(struct nsjconf_t *nsjconf, const char *src, const char *dst,
const char *fstype, const char *options, uintptr_t flags, const bool * isDir,
bool mandatory, const char *src_env, const char *dst_env,
- const uint8_t * src_content, size_t src_content_len, bool is_symlink);
+ const char *src_content, size_t src_content_len, bool is_symlink);
const char *mountDescribeMountPt(struct mounts_t *mpt);
#endif /* NS_MOUNT_H */
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <sched.h>
-#include <stdio.h>
#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
unsigned int cnt = 0;
struct pids_t *p;
TAILQ_FOREACH(p, &nsjconf->pids, pointers) {
- if (memcmp
- (addr.sin6_addr.s6_addr, p->remote_addr.sin6_addr.s6_addr,
- sizeof(*p->remote_addr.sin6_addr.s6_addr)) == 0) {
+ if (memcmp(addr.sin6_addr.s6_addr, p->remote_addr.sin6_addr.s6_addr,
+ sizeof(*p->remote_addr.sin6_addr.s6_addr))
+ == 0) {
cnt++;
}
}
#include <errno.h>
#include <signal.h>
#include <stdbool.h>
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
+++ /dev/null
-Subproject commit 198cfc0dbe159c75026600055f28e8b797bdac3b
#include <sched.h>
#include <setjmp.h>
#include <signal.h>
-#include <stdio.h>
#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <time.h>
#include <unistd.h>
-#include "common.h"
#include "cgroup.h"
+#include "common.h"
#include "contain.h"
#include "log.h"
#include "net.h"
static const char subprocDoneChar = 'D';
-#define VALSTR_STRUCT(x) { x, #x }
+#define VALSTR_STRUCT(x) \
+ { \
+ x, #x \
+ }
#if !defined(CLONE_NEWCGROUP)
#define CLONE_NEWCGROUP 0x02000000
static __thread char cloneFlagName[1024];
cloneFlagName[0] = '\0';
- /* *INDENT-OFF* */
- static struct {
- const uintptr_t flag;
- const char* const name;
- } const cloneFlags[] = {
- VALSTR_STRUCT(CLONE_VM),
- VALSTR_STRUCT(CLONE_FS),
- VALSTR_STRUCT(CLONE_FILES),
- VALSTR_STRUCT(CLONE_SIGHAND),
- VALSTR_STRUCT(CLONE_PTRACE),
- VALSTR_STRUCT(CLONE_VFORK),
- VALSTR_STRUCT(CLONE_PARENT),
- VALSTR_STRUCT(CLONE_THREAD),
- VALSTR_STRUCT(CLONE_NEWNS),
- VALSTR_STRUCT(CLONE_SYSVSEM),
- VALSTR_STRUCT(CLONE_SETTLS),
- VALSTR_STRUCT(CLONE_PARENT_SETTID),
- VALSTR_STRUCT(CLONE_CHILD_CLEARTID),
- VALSTR_STRUCT(CLONE_DETACHED),
- VALSTR_STRUCT(CLONE_UNTRACED),
- VALSTR_STRUCT(CLONE_CHILD_SETTID),
- VALSTR_STRUCT(CLONE_NEWCGROUP),
- VALSTR_STRUCT(CLONE_NEWUTS),
- VALSTR_STRUCT(CLONE_NEWIPC),
- VALSTR_STRUCT(CLONE_NEWUSER),
- VALSTR_STRUCT(CLONE_NEWPID),
- VALSTR_STRUCT(CLONE_NEWNET),
- VALSTR_STRUCT(CLONE_IO),
- };
- /* *INDENT-ON* */
+ /* *INDENT-OFF* */
+ static struct {
+ const uintptr_t flag;
+ const char* const name;
+ } const cloneFlags[] = {
+ VALSTR_STRUCT(CLONE_VM),
+ VALSTR_STRUCT(CLONE_FS),
+ VALSTR_STRUCT(CLONE_FILES),
+ VALSTR_STRUCT(CLONE_SIGHAND),
+ VALSTR_STRUCT(CLONE_PTRACE),
+ VALSTR_STRUCT(CLONE_VFORK),
+ VALSTR_STRUCT(CLONE_PARENT),
+ VALSTR_STRUCT(CLONE_THREAD),
+ VALSTR_STRUCT(CLONE_NEWNS),
+ VALSTR_STRUCT(CLONE_SYSVSEM),
+ VALSTR_STRUCT(CLONE_SETTLS),
+ VALSTR_STRUCT(CLONE_PARENT_SETTID),
+ VALSTR_STRUCT(CLONE_CHILD_CLEARTID),
+ VALSTR_STRUCT(CLONE_DETACHED),
+ VALSTR_STRUCT(CLONE_UNTRACED),
+ VALSTR_STRUCT(CLONE_CHILD_SETTID),
+ VALSTR_STRUCT(CLONE_NEWCGROUP),
+ VALSTR_STRUCT(CLONE_NEWUTS),
+ VALSTR_STRUCT(CLONE_NEWIPC),
+ VALSTR_STRUCT(CLONE_NEWUSER),
+ VALSTR_STRUCT(CLONE_NEWPID),
+ VALSTR_STRUCT(CLONE_NEWNET),
+ VALSTR_STRUCT(CLONE_IO),
+ };
+ /* *INDENT-ON* */
for (size_t i = 0; i < ARRAYSIZE(cloneFlags); i++) {
if (flags & cloneFlags[i].flag) {
}
LOG_D("setresgid(%d, %d, %d)", TAILQ_FIRST(&nsjconf->gids)->inside_id,
TAILQ_FIRST(&nsjconf->gids)->inside_id, TAILQ_FIRST(&nsjconf->gids)->inside_id);
- if (syscall
- (__NR_setresgid, TAILQ_FIRST(&nsjconf->gids)->inside_id,
- TAILQ_FIRST(&nsjconf->gids)->inside_id,
- TAILQ_FIRST(&nsjconf->gids)->inside_id) == -1) {
+ if (syscall(__NR_setresgid, TAILQ_FIRST(&nsjconf->gids)->inside_id,
+ TAILQ_FIRST(&nsjconf->gids)->inside_id, TAILQ_FIRST(&nsjconf->gids)->inside_id)
+ == -1) {
PLOG_E("setresgid(%u)", TAILQ_FIRST(&nsjconf->gids)->inside_id);
return false;
}
LOG_D("setresuid(%d, %d, %d)", TAILQ_FIRST(&nsjconf->uids)->inside_id,
TAILQ_FIRST(&nsjconf->uids)->inside_id, TAILQ_FIRST(&nsjconf->uids)->inside_id);
- if (syscall
- (__NR_setresuid, TAILQ_FIRST(&nsjconf->uids)->inside_id,
- TAILQ_FIRST(&nsjconf->uids)->inside_id,
- TAILQ_FIRST(&nsjconf->uids)->inside_id) == -1) {
+ if (syscall(__NR_setresuid, TAILQ_FIRST(&nsjconf->uids)->inside_id,
+ TAILQ_FIRST(&nsjconf->uids)->inside_id, TAILQ_FIRST(&nsjconf->uids)->inside_id)
+ == -1) {
PLOG_E("setresuid(%u)", TAILQ_FIRST(&nsjconf->uids)->inside_id);
return false;
}