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
This commit is contained in:
parent
dae05bfd31
commit
374f6cc4f0
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -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
|
||||
|
89
Makefile
89
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
|
||||
|
22
caps.c
22
caps.c
@ -21,8 +21,8 @@
|
||||
|
||||
#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>
|
||||
@ -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 {
|
||||
|
316
cmdline.c
316
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;
|
||||
}
|
||||
}
|
||||
|
42
common.h
42
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 */
|
||||
|
293
config.c
293
config.c
@ -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 <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) */
|
326
config.cc
Normal file
326
config.cc
Normal file
@ -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 <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;
|
||||
}
|
10
config.h
10
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 */
|
||||
|
108
config.proto
108
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" */
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
2
log.c
2
log.c
@ -29,8 +29,8 @@
|
||||
#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>
|
||||
|
||||
|
75
mount.c
75
mount.c
@ -25,8 +25,8 @@
|
||||
#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>
|
||||
@ -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);
|
||||
|
2
mount.h
2
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 */
|
||||
|
8
net.c
8
net.c
@ -28,8 +28,8 @@
|
||||
#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>
|
||||
@ -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++;
|
||||
}
|
||||
}
|
||||
|
2
nsjail.c
2
nsjail.c
@ -24,8 +24,8 @@
|
||||
#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>
|
||||
|
@ -1 +0,0 @@
|
||||
Subproject commit 198cfc0dbe159c75026600055f28e8b797bdac3b
|
69
subproc.c
69
subproc.c
@ -29,8 +29,8 @@
|
||||
#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>
|
||||
@ -41,8 +41,8 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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) {
|
||||
|
14
user.c
14
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user