caps: move capability-setting code to caps.*
authorRobert Swiecki <robert@swiecki.net>
Wed, 5 Jul 2017 11:03:14 +0000 (13:03 +0200)
committerRobert Swiecki <robert@swiecki.net>
Wed, 5 Jul 2017 11:03:14 +0000 (13:03 +0200)
Makefile
caps.c [new file with mode: 0644]
caps.h [new file with mode: 0644]
cgroup.h
cmdline.c
common.h
config.c
contain.c
nsjail.c

index d9dfdc1b59a0c972f25f0b9294097f05f9967ebb..132400c14eb4be45314bad8fbab80edd3474a79d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -28,11 +28,11 @@ CFLAGS += -O2 -c -std=gnu11 \
        -Wall -Wextra -Werror \
        -Ikafel/include
 
-LDFLAGS += -Wl,-z,now -Wl,-z,relro -pie -Wl,-z,noexecstack -lpthread
+LDFLAGS += -Wl,-z,now -Wl,-z,relro -pie -Wl,-z,noexecstack -lpthread -lcap
 
 BIN = nsjail
 LIBS = kafel/libkafel.a
-SRCS = nsjail.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
+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)
 
 ifdef DEBUG
@@ -136,11 +136,12 @@ indent:
 
 # DO NOT DELETE THIS LINE -- make depend depends on it.
 
-nsjail.o: nsjail.h common.h cmdline.h log.h net.h subproc.h util.h
-cmdline.o: cmdline.h common.h config.h log.h mount.h util.h user.h
+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
+cmdline.o: cmdline.h common.h caps.h config.h log.h mount.h util.h user.h
 config.o: common.h config.h log.h mount.h user.h util.h
-contain.o: contain.h common.h cgroup.h cpu.h log.h mount.h net.h pid.h user.h
-contain.o: util.h uts.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
 cgroup.o: cgroup.h common.h log.h util.h
 mount.o: mount.h common.h log.h subproc.h util.h
diff --git a/caps.c b/caps.c
new file mode 100644 (file)
index 0000000..89de38b
--- /dev/null
+++ b/caps.c
@@ -0,0 +1,246 @@
+/*
+
+   nsjail - capability-related operations
+   -----------------------------------------
+
+   Copyright 2014 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 "caps.h"
+
+#include <sys/capability.h>
+#include <string.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "log.h"
+
+#define VALSTR_STRUCT(x) { x, #x }
+
+/*  *INDENT-OFF* */
+static struct {
+       const int val;
+    const char* const name;
+} const capNames[] = {
+    VALSTR_STRUCT(CAP_CHOWN),
+    VALSTR_STRUCT(CAP_DAC_OVERRIDE),
+    VALSTR_STRUCT(CAP_DAC_READ_SEARCH),
+    VALSTR_STRUCT(CAP_FOWNER),
+    VALSTR_STRUCT(CAP_FSETID),
+    VALSTR_STRUCT(CAP_KILL),
+    VALSTR_STRUCT(CAP_SETGID),
+    VALSTR_STRUCT(CAP_SETUID),
+    VALSTR_STRUCT(CAP_SETPCAP),
+    VALSTR_STRUCT(CAP_LINUX_IMMUTABLE),
+    VALSTR_STRUCT(CAP_NET_BIND_SERVICE),
+    VALSTR_STRUCT(CAP_NET_BROADCAST),
+    VALSTR_STRUCT(CAP_NET_ADMIN),
+    VALSTR_STRUCT(CAP_NET_RAW),
+    VALSTR_STRUCT(CAP_IPC_LOCK),
+    VALSTR_STRUCT(CAP_IPC_OWNER),
+    VALSTR_STRUCT(CAP_SYS_MODULE),
+    VALSTR_STRUCT(CAP_SYS_RAWIO),
+    VALSTR_STRUCT(CAP_SYS_CHROOT),
+    VALSTR_STRUCT(CAP_SYS_PTRACE),
+    VALSTR_STRUCT(CAP_SYS_PACCT),
+    VALSTR_STRUCT(CAP_SYS_ADMIN),
+    VALSTR_STRUCT(CAP_SYS_BOOT),
+    VALSTR_STRUCT(CAP_SYS_NICE),
+    VALSTR_STRUCT(CAP_SYS_RESOURCE),
+    VALSTR_STRUCT(CAP_SYS_TIME),
+    VALSTR_STRUCT(CAP_SYS_TTY_CONFIG),
+    VALSTR_STRUCT(CAP_MKNOD),
+    VALSTR_STRUCT(CAP_LEASE),
+    VALSTR_STRUCT(CAP_AUDIT_WRITE),
+    VALSTR_STRUCT(CAP_AUDIT_CONTROL),
+    VALSTR_STRUCT(CAP_SETFCAP),
+    VALSTR_STRUCT(CAP_MAC_OVERRIDE),
+    VALSTR_STRUCT(CAP_MAC_ADMIN),
+    VALSTR_STRUCT(CAP_SYSLOG),
+    VALSTR_STRUCT(CAP_WAKE_ALARM),
+    VALSTR_STRUCT(CAP_BLOCK_SUSPEND),
+    VALSTR_STRUCT(CAP_AUDIT_READ),
+};
+/*  *INDENT-ON* */
+
+int capsNameToVal(const char *name)
+{
+       for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
+               if (strcmp(name, capNames[i].name) == 0) {
+                       return capNames[i].val;
+               }
+       }
+       LOG_W("Uknown capability: '%s'", name);
+       return -1;
+}
+
+static const char *capsValToStr(int val)
+{
+       static __thread char capsStr[1024];
+       for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
+               if (val == capNames[i].val) {
+                       snprintf(capsStr, sizeof(capsStr), "%s", capNames[i].name);
+                       return capsStr;
+               }
+       }
+
+       snprintf(capsStr, sizeof(capsStr), "CAP_UNKNOWN(%d)", val);
+       return capsStr;
+}
+
+bool capsInitInternal(struct nsjconf_t * nsjconf, bool is_global)
+{
+       cap_t cap_orig = cap_get_pid(getpid());
+       if (cap_orig == NULL) {
+               PLOG_W("capget(PID=%d)", (int)getpid());
+               return false;
+       }
+
+       cap_t cap_new = cap_dup(cap_orig);
+       if (cap_new == NULL) {
+               PLOG_W("cap_dup()");
+               cap_free(cap_orig);
+               return false;
+       }
+
+       struct capslistt *l = is_global ? &nsjconf->global_caps : &nsjconf->local_caps;
+       if (is_global || nsjconf->keep_caps == false) {
+               if (cap_clear_flag(cap_new, CAP_INHERITABLE) == -1) {
+                       PLOG_W("cap_clear_flag(CAP_INHERITABLE)");
+                       cap_free(cap_orig);
+                       cap_free(cap_new);
+                       return false;
+               }
+               if (is_global == false) {
+                       if (cap_clear_flag(cap_new, CAP_PERMITTED) == -1) {
+                               PLOG_W("cap_clear_flag(CAP_PERMITTED)");
+                               cap_free(cap_orig);
+                               cap_free(cap_new);
+                               return false;
+                       }
+                       if (cap_clear_flag(cap_new, CAP_EFFECTIVE) == -1) {
+                               PLOG_W("cap_clear_flag(CAP_EFFECTIVE)");
+                               cap_free(cap_orig);
+                               cap_free(cap_new);
+                               return false;
+                       }
+               }
+
+               struct ints_t *p;
+               TAILQ_FOREACH(p, l, pointers) {
+                       cap_flag_value_t v;
+                       if (cap_get_flag(cap_orig, p->val, CAP_PERMITTED, &v) == -1) {
+                               PLOG_W("cap_get_flag(cap_orig, CAP_PERMITTED, %s)",
+                                      capsValToStr(p->val));
+                               cap_free(cap_orig);
+                               cap_free(cap_new);
+                               return false;
+                       }
+                       if (v != CAP_SET) {
+                               LOG_W("Capability %s is not permitted in the %s namespace",
+                                     capsValToStr(p->val), is_global ? "global" : "local");
+                               cap_free(cap_orig);
+                               cap_free(cap_new);
+                               return false;
+                       }
+                       if (cap_set_flag(cap_new, CAP_INHERITABLE, 1, &p->val, CAP_SET) == -1) {
+                               PLOG_W("cap_set_flag(cap_new, CAP_INHERITABLE, %s)",
+                                      capsValToStr(p->val));
+                               cap_free(cap_orig);
+                               cap_free(cap_new);
+                               return false;
+                       }
+                       if (is_global == false) {
+                               if (cap_set_flag(cap_new, CAP_PERMITTED, 1, &p->val, CAP_SET) == -1) {
+                                       PLOG_W("cap_set_flag(cap_new, CAP_PERMITTED, %s)",
+                                              capsValToStr(p->val));
+                                       cap_free(cap_orig);
+                                       cap_free(cap_new);
+                                       return false;
+                               }
+                               if (cap_set_flag(cap_new, CAP_EFFECTIVE, 1, &p->val, CAP_SET) == -1) {
+                                       PLOG_W("cap_set_flag(cap_new, CAP_EFFECTIVE, %s)",
+                                              capsValToStr(p->val));
+                                       cap_free(cap_orig);
+                                       cap_free(cap_new);
+                                       return false;
+                               }
+                       }
+               }
+       }
+
+       if (is_global == false || nsjconf->keep_caps == true) {
+               for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
+                       cap_flag_value_t v;
+                       if (cap_get_flag(cap_orig, capNames[i].val, CAP_PERMITTED, &v) == -1) {
+                               PLOG_W("cap_get_flag(cap_orig, CAP_PERMITTED, %s)",
+                                      capNames[i].name);
+                               cap_free(cap_orig);
+                               cap_free(cap_new);
+                               return false;
+                       }
+                       if (cap_set_flag(cap_new, CAP_INHERITABLE, 1, &capNames[i].val, v) == -1) {
+                               PLOG_W("cap_set_flag(cap_new, CAP_INHERITABLE, %s)",
+                                      capNames[i].name);
+                               cap_free(cap_orig);
+                               cap_free(cap_new);
+                               return false;
+                       }
+               }
+       }
+
+       if (cap_set_proc(cap_new) == -1) {
+               PLOG_W("cap_set_proc()");
+               cap_free(cap_orig);
+               cap_free(cap_new);
+               return false;
+       }
+#if defined(PR_CAP_AMBIENT)
+       if (is_global == false && nsjconf->keep_caps == true) {
+               for (unsigned long i = 0; i < CAP_LAST_CAP; i++) {
+                       if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0UL, 0UL) == -1) {
+                               PLOG_W("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, %s)",
+                                      capsValToStr(i));
+                       }
+               }
+       } else {
+               struct ints_t *p;
+               TAILQ_FOREACH(p, l, pointers) {
+                       if (prctl
+                           (PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, (unsigned long)p->val, 0UL,
+                            0UL) == -1) {
+                               PLOG_W("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, %s)",
+                                      capsValToStr(p->val));
+                       }
+               }
+       }
+#endif                         /* defined(PR_CAP_AMBIENT) */
+
+       cap_free(cap_orig);
+       cap_free(cap_new);
+       return true;
+}
+
+bool capsInitGlobalNs(struct nsjconf_t * nsjconf)
+{
+       return capsInitInternal(nsjconf, true /* global */ );
+}
+
+bool capsInitLocalNs(struct nsjconf_t * nsjconf)
+{
+       return capsInitInternal(nsjconf, false /* local */ );
+}
diff --git a/caps.h b/caps.h
new file mode 100644 (file)
index 0000000..516739d
--- /dev/null
+++ b/caps.h
@@ -0,0 +1,31 @@
+/*
+
+   nsjail - capability-related operations
+   -----------------------------------------
+
+   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.
+
+*/
+
+#ifndef NS_CAPS_H
+#define NS_CAPS_H
+
+#include "common.h"
+
+int capsNameToVal(const char *name);
+bool capsInitGlobalNs(struct nsjconf_t *nsjconf);
+bool capsInitLocalNs(struct nsjconf_t *nsjconf);
+
+#endif                         /* NS_CAPS_H */
index 0e647db5bd67010b919fe8d9514a863b54f16736..9a76e26e216a60a9e15c2a892b558e3ab4c32bbe 100644 (file)
--- a/cgroup.h
+++ b/cgroup.h
@@ -27,7 +27,7 @@
 
 #include "common.h"
 
-bool cgroupInitNsFromParent(struct nsjconf_t * nsjconf, pid_t pid);
+bool cgroupInitNsFromParent(struct nsjconf_t *nsjconf, pid_t pid);
 bool cgroupInitNs(void);
 void cgroupFinishFromParent(struct nsjconf_t *nsjconf, pid_t pid);
 
index 98e477c0b29ba963201bdfd6d2b8254af0604b2b..26e5a3600bd7746fa626c52f28439a9b310d1b67 100644 (file)
--- a/cmdline.c
+++ b/cmdline.c
@@ -41,6 +41,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include "caps.h"
 #include "config.h"
 #include "log.h"
 #include "mount.h"
@@ -90,6 +91,8 @@ struct custom_option custom_opts[] = {
     {{"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)"},
+    {{"global_cap", required_argument, NULL, 0x0509}, "Retain this capability in global namespace (e.g. CAP_PTRACE). Can be specified multiple times"},
+    {{"local_cap", required_argument, NULL, 0x050A}, "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)"},
@@ -364,18 +367,20 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
        TAILQ_INIT(&nsjconf->envs);
        TAILQ_INIT(&nsjconf->uids);
        TAILQ_INIT(&nsjconf->gids);
+       TAILQ_INIT(&nsjconf->global_caps);
+       TAILQ_INIT(&nsjconf->local_caps);
 
        static char cmdlineTmpfsSz[PATH_MAX] = "size=4194304";
 
-       struct fds_t *f;
-       f = utilMalloc(sizeof(struct fds_t));
-       f->fd = STDIN_FILENO;
+       struct ints_t *f;
+       f = utilMalloc(sizeof(struct ints_t));
+       f->val = STDIN_FILENO;
        TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
-       f = utilMalloc(sizeof(struct fds_t));
-       f->fd = STDOUT_FILENO;
+       f = utilMalloc(sizeof(struct ints_t));
+       f->val = STDOUT_FILENO;
        TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
-       f = utilMalloc(sizeof(struct fds_t));
-       f->fd = STDERR_FILENO;
+       f = utilMalloc(sizeof(struct ints_t));
+       f->val = STDERR_FILENO;
        TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
 
        // Generate options array for getopt_long.
@@ -531,9 +536,9 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                        nsjconf->skip_setsid = true;
                        break;
                case 0x0505:{
-                               struct fds_t *f;
-                               f = utilMalloc(sizeof(struct fds_t));
-                               f->fd = (int)strtol(optarg, NULL, 0);
+                               struct ints_t *f;
+                               f = utilMalloc(sizeof(struct ints_t));
+                               f->val = (int)strtol(optarg, NULL, 0);
                                TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
                        } break;
                case 0x0507:
@@ -542,6 +547,24 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                case 0x0508:
                        nsjconf->max_cpus = strtoul(optarg, NULL, 0);
                        break;
+               case 0x509:{
+                               struct ints_t *f = utilMalloc(sizeof(struct ints_t));
+                               f->val = capsNameToVal(optarg);
+                               if (f->val == -1) {
+                                       return false;
+                               }
+                               TAILQ_INSERT_HEAD(&nsjconf->global_caps, f, pointers);
+                       }
+                       break;
+               case 0x50A:{
+                               struct ints_t *f = utilMalloc(sizeof(struct ints_t));
+                               f->val = capsNameToVal(optarg);
+                               if (f->val == -1) {
+                                       return false;
+                               }
+                               TAILQ_INSERT_HEAD(&nsjconf->local_caps, f, pointers);
+                       }
+                       break;
                case 0x0601:
                        nsjconf->is_root_rw = true;
                        break;
index 5638d6c1d5afac8d2b7522f91b7aa37e9c75a43f..61d4a1dd082020d614d62084990e3c7968382545 100644 (file)
--- a/common.h
+++ b/common.h
@@ -86,9 +86,9 @@ struct idmap_t {
         TAILQ_ENTRY(idmap_t) pointers;
 };
 
-struct fds_t {
-       int fd;
-        TAILQ_ENTRY(fds_t) pointers;
+struct ints_t {
+       int val;
+        TAILQ_ENTRY(ints_t) pointers;
 };
 
 enum ns_mode_t {
@@ -172,7 +172,8 @@ struct nsjconf_t {
         TAILQ_HEAD(envlist, charptr_t) envs;
         TAILQ_HEAD(pidslist, pids_t) pids;
         TAILQ_HEAD(mountptslist, mounts_t) mountpts;
-        TAILQ_HEAD(fdslistt, fds_t) open_fds;
+        TAILQ_HEAD(fdslistt, ints_t) open_fds;
+        TAILQ_HEAD(capslistt, ints_t) global_caps, local_caps;
 };
 
 #endif                         /* NS_COMMON_H */
index 4b1d5a50d6239dcf84c76c308b31fa41a06e2e6e..2696e5dfb90b4fd9b5243e1d7061c05ac7a4ba1b 100644 (file)
--- a/config.c
+++ b/config.c
@@ -117,8 +117,8 @@ static bool configParseInternal(struct nsjconf_t *nsjconf, Nsjail__NsJailConfig
        nsjconf->skip_setsid = njc->skip_setsid;
 
        for (size_t i = 0; i < njc->n_pass_fd; i++) {
-               struct fds_t *f = utilMalloc(sizeof(struct fds_t));
-               f->fd = njc->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);
        }
 
index fc0a5304e37012bcd9dcab951f6b918315b7b995..4a24ffa1c964b989c86179ded8811a70352848a3 100644 (file)
--- a/contain.c
+++ b/contain.c
@@ -42,6 +42,7 @@
 #include <sys/time.h>
 #include <unistd.h>
 
+#include "caps.h"
 #include "cgroup.h"
 #include "cpu.h"
 #include "log.h"
@@ -88,59 +89,10 @@ static bool containDropPrivs(struct nsjconf_t *nsjconf)
                        PLOG_W("prctl(PR_SET_NO_NEW_PRIVS, 1)");
                }
        }
-
-       struct __user_cap_header_struct cap_hdr = {
-               .version = _LINUX_CAPABILITY_VERSION_3,
-               .pid = 0,
-       };
-       struct __user_cap_data_struct cap_data[_LINUX_CAPABILITY_U32S_3];
-       if (syscall(__NR_capget, &cap_hdr, &cap_data) == -1) {
-               PLOG_E("capget()");
+       if (capsInitLocalNs(nsjconf) == false) {
                return false;
        }
 
-       if (nsjconf->keep_caps == true) {
-               for (size_t i = 0; i < _LINUX_CAPABILITY_U32S_3; i++) {
-                       cap_data[i].inheritable = cap_data[i].permitted;
-                       cap_data[i].effective = cap_data[i].permitted;
-               }
-               if (syscall(__NR_capset, &cap_hdr, &cap_data) == -1) {
-                       PLOG_E("capset()");
-                       return false;
-               }
-#if defined(PR_CAP_AMBIENT)
-               for (unsigned long i = 0; i < 128UL; i++) {
-                       /*
-                        * Number of capabilities varies between kernels, so
-                        * wait for the first one which returns EINVAL
-                        */
-                       if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0UL, 0UL, 0UL) == -1
-                           && errno != EINVAL) {
-                               PLOG_W("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, %lu)", i);
-                       }
-               }
-#endif                         /* defined(PR_CAP_AMBIENT) */
-       } else {
-               for (unsigned long i = 0; i < 128UL; i++) {
-                       /*
-                        * Number of capabilities varies between kernels, so
-                        * wait for the first one which returns EINVAL
-                        */
-                       if (prctl(PR_CAPBSET_DROP, i, 0UL, 0UL, 0UL) == -1 && errno != EINVAL) {
-                               PLOG_W("prctl(PR_CAPBSET_DROP, %lu", i);
-                       }
-               }
-               if (prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) == -1) {
-                       PLOG_E("prctl(PR_SET_KEEPCAPS, 0)");
-                       return false;
-               }
-
-               memset(&cap_data, '\0', sizeof(cap_data));
-               if (syscall(__NR_capset, &cap_hdr, &cap_data) == -1) {
-                       PLOG_E("capset()");
-                       return false;
-               }
-       }
        return true;
 }
 
@@ -217,9 +169,9 @@ static bool containSetLimits(struct nsjconf_t *nsjconf)
 
 static bool containPassFd(struct nsjconf_t *nsjconf, int fd)
 {
-       struct fds_t *p;
+       struct ints_t *p;
        TAILQ_FOREACH(p, &nsjconf->open_fds, pointers) {
-               if (p->fd == fd) {
+               if (p->val == fd) {
                        return true;
                }
        }
index 4c683d43400dbf0faf1e1dfdbef90259829c70db..d001a034bd6d4fff312656fa4861963404d3daae 100644 (file)
--- a/nsjail.c
+++ b/nsjail.c
@@ -30,6 +30,7 @@
 #include <sys/time.h>
 #include <unistd.h>
 
+#include "caps.h"
 #include "cmdline.h"
 #include "log.h"
 #include "net.h"
@@ -168,6 +169,7 @@ int main(int argc, char *argv[])
 {
        struct nsjconf_t nsjconf;
        if (!cmdlineParse(argc, argv, &nsjconf)) {
+               LOG_E("Couldn't parse cmdline options");
                exit(1);
        }
        if (nsjconf.clone_newuser == false && geteuid() != 0) {
@@ -183,6 +185,10 @@ int main(int argc, char *argv[])
        if (nsjailSetTimer(&nsjconf) == false) {
                exit(1);
        }
+       if (capsInitGlobalNs(&nsjconf) == false) {
+               LOG_E("Couldn't initialize global capabilities");
+               exit(1);
+       }
 
        if (nsjconf.mode == MODE_LISTEN_TCP) {
                nsjailListenMode(&nsjconf);