From 374f6cc4f0623c9782664a448e0291737e0ec637 Mon Sep 17 00:00:00 2001 From: Robert Swiecki Date: Wed, 13 Sep 2017 22:03:21 +0200 Subject: [PATCH] config: Initial work on converting config.c to c++ protobuf lib config: Initial work on converting config.c to c++ protobuf lib #2 config: Initial work on converting config.c to c++ protobuf lib #3 config: Initial work on converting config.c to c++ protobuf lib #4 config: Initial work on converting config.c to c++ protobuf lib #5 config: Initial work on converting config.c to c++ protobuf lib #6 --- .gitmodules | 3 - Makefile | 89 ++---- caps.c | 22 +- cmdline.c | 316 +++++++++---------- common.h | 42 ++- config.c | 293 ------------------ config.cc | 326 ++++++++++++++++++++ config.h | 10 +- config.proto | 108 +++---- configs/apache.cfg | 35 +-- configs/bash-with-fake-geteuid.cfg | 31 +- configs/demo-dont-use-chrome-with-net.cfg | 59 ++-- configs/firefox-with-cloned-net.cfg | 59 ++-- configs/firefox-with-net.cfg | 43 ++- configs/home-documents-with-xorg-no-net.cfg | 33 +- configs/imagemagick-convert.cfg | 33 +- log.c | 2 +- mount.c | 75 ++--- mount.h | 2 +- net.c | 8 +- nsjail.c | 2 +- protobuf-c-text | 1 - subproc.c | 69 +++-- user.c | 14 +- 24 files changed, 832 insertions(+), 843 deletions(-) delete mode 100644 config.c create mode 100644 config.cc delete mode 160000 protobuf-c-text diff --git a/.gitmodules b/.gitmodules index 53c4720..4c3ff73 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [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 diff --git a/Makefile b/Makefile index 60d9b33..289a021 100644 --- a/Makefile +++ b/Makefile @@ -18,25 +18,31 @@ # 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 @@ -48,58 +54,18 @@ ifeq ($(NL3_EXISTS), 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)","") @@ -107,39 +73,27 @@ 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 @@ -154,3 +108,4 @@ user.o: user.h common.h log.h subproc.h util.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 diff --git a/caps.c b/caps.c index 5a17ccb..774ede2 100644 --- a/caps.c +++ b/caps.c @@ -21,8 +21,8 @@ #include "caps.h" -#include #include +#include #include #include #include @@ -30,12 +30,15 @@ #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), @@ -76,7 +79,7 @@ static struct { 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* */ @@ -209,7 +212,8 @@ bool capsInitNs(struct nsjconf_t *nsjconf) } 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 { @@ -219,9 +223,9 @@ bool capsInitNs(struct nsjconf_t *nsjconf) } 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 { diff --git a/cmdline.c b/cmdline.c index a3ac216..66f758e 100644 --- a/cmdline.c +++ b/cmdline.c @@ -45,8 +45,8 @@ #include "config.h" #include "log.h" #include "mount.h" -#include "util.h" #include "user.h" +#include "util.h" struct custom_option { struct option opt; @@ -55,91 +55,91 @@ struct custom_option { /* *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* */ @@ -306,61 +306,61 @@ static char *cmdlineSplitStrByColon(char *spec) 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); @@ -576,12 +576,13 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf) 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; } } @@ -590,12 +591,13 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf) 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; } } @@ -604,12 +606,13 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf) 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; } } @@ -618,12 +621,13 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf) 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; } } diff --git a/common.h b/common.h index cf7191b..cdbdd38 100644 --- a/common.h +++ b/common.h @@ -47,10 +47,10 @@ static void __attribute__ ((unused)) __clang_cleanup_func(void (^*dfunc) (void)) #define defer void (^_STRMERGE(__defer_f_, __COUNTER__))(void) __attribute__((cleanup(__clang_cleanup_func))) __attribute__((unused)) = ^ #else #define __block -#define _DEFER(a, count) \ - auto void _STRMERGE(__defer_f_, count)(void *_defer_arg __attribute__((unused))); \ +#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 @@ -61,7 +61,8 @@ struct pids_t { char remote_txt[64]; struct sockaddr_in6 remote_addr; int pid_syscall_fd; - TAILQ_ENTRY(pids_t) pointers; + TAILQ_ENTRY(pids_t) + pointers; }; struct mounts_t { @@ -75,7 +76,8 @@ struct mounts_t { bool isDir; bool isSymlink; bool mandatory; - TAILQ_ENTRY(mounts_t) pointers; + TAILQ_ENTRY(mounts_t) + pointers; }; struct idmap_t { @@ -83,12 +85,14 @@ struct idmap_t { uid_t outside_id; size_t count; bool is_newidmap; - TAILQ_ENTRY(idmap_t) pointers; + TAILQ_ENTRY(idmap_t) + pointers; }; struct ints_t { int val; - TAILQ_ENTRY(ints_t) pointers; + TAILQ_ENTRY(ints_t) + pointers; }; enum ns_mode_t { @@ -100,7 +104,8 @@ enum ns_mode_t { struct charptr_t { char *val; - TAILQ_ENTRY(charptr_t) pointers; + TAILQ_ENTRY(charptr_t) + pointers; }; enum llevel_t { @@ -167,13 +172,20 @@ struct nsjconf_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 */ diff --git a/config.c b/config.c deleted file mode 100644 index b899c14..0000000 --- a/config.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - - 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 -#include -#include - -#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) */ diff --git a/config.cc b/config.cc new file mode 100644 index 0000000..8110320 --- /dev/null +++ b/config.cc @@ -0,0 +1,326 @@ +/* + + 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 +#include +#include +#include +#include +#include + +#include "caps.h" +#include "config.h" +#include "log.h" +#include "mount.h" +#include "user.h" +#include "util.h" +} + +#include +#include +#include +#include + +#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(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(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(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(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; +} diff --git a/config.h b/config.h index 1dfd98b..4b00bc3 100644 --- a/config.h +++ b/config.h @@ -22,8 +22,14 @@ #ifndef NS_CONFIG_H #define NS_CONFIG_H +#ifdef __cplusplus +extern "C" { +#endif + #include "common.h" + bool configParse(struct nsjconf_t *nsjconf, const char *file); -bool configParse(struct nsjconf_t *nsjconf, const char *file); - +#ifdef __cplusplus +} // extern "C" +#endif #endif /* NS_CONFIG_H */ diff --git a/config.proto b/config.proto index 7010d35..42a9485 100644 --- a/config.proto +++ b/config.proto @@ -19,12 +19,12 @@ enum LogLevel { 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 { @@ -41,18 +41,18 @@ 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 { @@ -67,32 +67,32 @@ message NsJailConfig { /* 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; @@ -104,52 +104,52 @@ message NsJailConfig /* 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 */ @@ -158,7 +158,7 @@ message NsJailConfig /* 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; @@ -166,30 +166,30 @@ message NsJailConfig /* 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" */ diff --git a/configs/apache.cfg b/configs/apache.cfg index 4735ed6..e7162ff 100644 --- a/configs/apache.cfg +++ b/configs/apache.cfg @@ -1,21 +1,15 @@ 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 @@ -123,16 +117,15 @@ mount { 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" diff --git a/configs/bash-with-fake-geteuid.cfg b/configs/bash-with-fake-geteuid.cfg index 74af795..d647a04 100644 --- a/configs/bash-with-fake-geteuid.cfg +++ b/configs/bash-with-fake-geteuid.cfg @@ -1,13 +1,11 @@ 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" @@ -169,14 +167,13 @@ mount { 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" diff --git a/configs/demo-dont-use-chrome-with-net.cfg b/configs/demo-dont-use-chrome-with-net.cfg index 1414cb4..9a17f33 100644 --- a/configs/demo-dont-use-chrome-with-net.cfg +++ b/configs/demo-dont-use-chrome-with-net.cfg @@ -1,26 +1,25 @@ 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" @@ -166,16 +165,14 @@ mount { 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" diff --git a/configs/firefox-with-cloned-net.cfg b/configs/firefox-with-cloned-net.cfg index ebe730c..39b774f 100644 --- a/configs/firefox-with-cloned-net.cfg +++ b/configs/firefox-with-cloned-net.cfg @@ -1,26 +1,25 @@ 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" @@ -152,16 +151,14 @@ mount { 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" diff --git a/configs/firefox-with-net.cfg b/configs/firefox-with-net.cfg index efa71dc..dc8f4fd 100644 --- a/configs/firefox-with-net.cfg +++ b/configs/firefox-with-net.cfg @@ -1,18 +1,17 @@ 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" @@ -138,16 +137,14 @@ mount { 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" diff --git a/configs/home-documents-with-xorg-no-net.cfg b/configs/home-documents-with-xorg-no-net.cfg index 0c73623..4363e36 100644 --- a/configs/home-documents-with-xorg-no-net.cfg +++ b/configs/home-documents-with-xorg-no-net.cfg @@ -1,13 +1,12 @@ 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" @@ -127,13 +126,11 @@ mount { 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" diff --git a/configs/imagemagick-convert.cfg b/configs/imagemagick-convert.cfg index 4bc910e..bd50500 100644 --- a/configs/imagemagick-convert.cfg +++ b/configs/imagemagick-convert.cfg @@ -1,13 +1,12 @@ 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" @@ -77,13 +76,11 @@ mount { 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" diff --git a/log.c b/log.c index 3c9b98a..7782a9b 100644 --- a/log.c +++ b/log.c @@ -29,8 +29,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/mount.c b/mount.c index 0771738..854809d 100644 --- a/mount.c +++ b/mount.c @@ -25,8 +25,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -40,10 +40,13 @@ #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) @@ -51,37 +54,37 @@ 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) { @@ -387,7 +390,7 @@ bool mountInitNs(struct nsjconf_t * nsjconf) 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)); @@ -455,7 +458,7 @@ bool mountAddMountPt(struct nsjconf_t * nsjconf, const char *src, const char *ds } } - 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); diff --git a/mount.h b/mount.h index a7fd948..be9633f 100644 --- a/mount.h +++ b/mount.h @@ -32,7 +32,7 @@ bool mountInitNs(struct nsjconf_t *nsjconf); 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 */ diff --git a/net.c b/net.c index 5802b14..9b5c09e 100644 --- a/net.c +++ b/net.c @@ -28,8 +28,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -171,9 +171,9 @@ bool netLimitConns(struct nsjconf_t * nsjconf, int connsock) 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++; } } diff --git a/nsjail.c b/nsjail.c index 2930138..90c496d 100644 --- a/nsjail.c +++ b/nsjail.c @@ -24,8 +24,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/protobuf-c-text b/protobuf-c-text deleted file mode 160000 index 198cfc0..0000000 --- a/protobuf-c-text +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 198cfc0dbe159c75026600055f28e8b797bdac3b diff --git a/subproc.c b/subproc.c index 060432c..bfc1c35 100644 --- a/subproc.c +++ b/subproc.c @@ -29,8 +29,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -41,8 +41,8 @@ #include #include -#include "common.h" #include "cgroup.h" +#include "common.h" #include "contain.h" #include "log.h" #include "net.h" @@ -52,7 +52,10 @@ 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 @@ -63,36 +66,36 @@ static const char *subprocCloneFlagsToStr(uintptr_t flags) 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) { diff --git a/user.c b/user.c index d4d7074..c4fdeac 100644 --- a/user.c +++ b/user.c @@ -265,19 +265,17 @@ bool userInitNsFromChild(struct nsjconf_t * nsjconf) } 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; }