caps: just local caps
authorRobert Swiecki <robert@swiecki.net>
Wed, 5 Jul 2017 15:29:57 +0000 (17:29 +0200)
committerRobert Swiecki <robert@swiecki.net>
Wed, 5 Jul 2017 15:29:57 +0000 (17:29 +0200)
caps.c
caps.h
cmdline.c
common.h
config.c
config.proto
configs/bash-with-fake-geteuid.cfg
contain.c
nsjail.c

diff --git a/caps.c b/caps.c
index 9ea27dbf6272cb4da515faf8d47965c8367a11fe..c73a0ecb648595c101840479f0e143facc149d2c 100644 (file)
--- a/caps.c
+++ b/caps.c
@@ -150,15 +150,12 @@ static void capsClrFlag(cap_t cap, cap_value_t id, cap_value_t type)
        }
 }
 
-bool capsInitInternal(struct nsjconf_t *nsjconf, bool is_global)
+bool capsInitNs(struct nsjconf_t *nsjconf)
 {
        cap_t cap_orig = capsGet();
        cap_t cap_new = capsGet();
 
-       struct capslistt *l = is_global ? &nsjconf->global_caps : &nsjconf->local_caps;
-       bool keep_caps = is_global ? nsjconf->keep_global_caps : nsjconf->keep_local_caps;
-
-       if (keep_caps) {
+       if (nsjconf->keep_caps) {
                for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
                        if (capsGetCap(cap_orig, capNames[i].val, CAP_PERMITTED) == CAP_SET) {
                                capsSetCap(cap_new, capNames[i].val, CAP_INHERITABLE);
@@ -169,10 +166,10 @@ bool capsInitInternal(struct nsjconf_t *nsjconf, bool is_global)
        } else {
                capsClearType(cap_new, CAP_INHERITABLE);
                struct ints_t *p;
-               TAILQ_FOREACH(p, l, pointers) {
+               TAILQ_FOREACH(p, &nsjconf->caps, pointers) {
                        if (capsGetCap(cap_orig, p->val, CAP_PERMITTED) != CAP_SET) {
-                               LOG_W("Capability %s is not permitted in the %s namespace",
-                                     capsValToStr(p->val), is_global ? "global" : "local");
+                               LOG_W("Capability %s is not permitted in the namespace",
+                                     capsValToStr(p->val));
                                capsFree(cap_orig);
                                capsFree(cap_new);
                                return false;
@@ -190,7 +187,7 @@ bool capsInitInternal(struct nsjconf_t *nsjconf, bool is_global)
 #define PR_CAP_AMBIENT 47
 #define PR_CAP_AMBIENT_RAISE 2
 #endif                         /* !defined(PR_CAP_AMBIENT) */
-       if (keep_caps) {
+       if (nsjconf->keep_caps) {
                for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
                        if (capsGetCap(cap_orig, capNames[i].val, CAP_PERMITTED) != CAP_SET) {
                                continue;
@@ -204,7 +201,7 @@ bool capsInitInternal(struct nsjconf_t *nsjconf, bool is_global)
                }
        } else {
                struct ints_t *p;
-               TAILQ_FOREACH(p, l, pointers) {
+               TAILQ_FOREACH(p, &nsjconf->caps, pointers) {
                        if (prctl
                            (PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, (unsigned long)p->val, 0UL,
                             0UL) == -1) {
@@ -218,13 +215,3 @@ bool capsInitInternal(struct nsjconf_t *nsjconf, bool is_global)
        capsFree(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
index 516739dc5f3eb0ec826936d8d259848bbfc0b8fb..a268cb725b12dea17f41b760ab42b5772e6845b9 100644 (file)
--- a/caps.h
+++ b/caps.h
@@ -25,7 +25,6 @@
 #include "common.h"
 
 int capsNameToVal(const char *name);
-bool capsInitGlobalNs(struct nsjconf_t *nsjconf);
-bool capsInitLocalNs(struct nsjconf_t *nsjconf);
+bool capsInitNs(struct nsjconf_t *nsjconf);
 
 #endif                         /* NS_CAPS_H */
index 724014f50c7245526782e520dffa28b30b606c59..d9abc6966f14a2144b3f7436c2541e4a6a885b3d 100644 (file)
--- a/cmdline.c
+++ b/cmdline.c
@@ -86,14 +86,12 @@ struct custom_option custom_opts[] = {
     {{"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_global_caps", no_argument, NULL, 0x0500}, "Don't drop capabilities in the global namespace"},
-    {{"keep_local_caps", no_argument, NULL, 0x0501}, "Don't drop capabilities in the local namespace"},
+    {{"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)"},
-    {{"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)"},
+    {{"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)"},
@@ -142,7 +140,6 @@ struct custom_option deprecated_opts[] = {
     {{"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\")"},
-    {{"keep_caps", no_argument, NULL, 0x0501}, "Don't drop capabilities in the local namespace"},
 };
 /*  *INDENT-ON* */
 
@@ -217,16 +214,16 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
              "bind:[%s]:%d, "
              "max_conns_per_ip:%u, time_limit:%ld, personality:%#lx, daemonize:%s, "
              "clone_newnet:%s, clone_newuser:%s, clone_newns:%s, clone_newpid:%s, "
-             "clone_newipc:%s, clonew_newuts:%s, clone_newcgroup:%s, keep_global_caps:%s, "
-             "keep_local_caps:%s, tmpfs_size:%zu, disable_no_new_privs:%s, max_cpus:%zu",
+             "clone_newipc:%s, clonew_newuts:%s, clone_newcgroup:%s, keep_caps:%s, "
+             "tmpfs_size:%zu, disable_no_new_privs:%s, max_cpus:%zu",
              nsjconf->hostname, nsjconf->chroot ? nsjconf->chroot : "[NULL]", nsjconf->argv[0],
              nsjconf->bindhost, nsjconf->port, nsjconf->max_conns_per_ip, nsjconf->tlimit,
              nsjconf->personality, logYesNo(nsjconf->daemonize), logYesNo(nsjconf->clone_newnet),
              logYesNo(nsjconf->clone_newuser), logYesNo(nsjconf->clone_newns),
              logYesNo(nsjconf->clone_newpid), logYesNo(nsjconf->clone_newipc),
              logYesNo(nsjconf->clone_newuts), logYesNo(nsjconf->clone_newcgroup),
-             logYesNo(nsjconf->keep_global_caps), logYesNo(nsjconf->keep_local_caps),
-             nsjconf->tmpfs_size, logYesNo(nsjconf->disable_no_new_privs), nsjconf->max_cpus);
+             logYesNo(nsjconf->keep_caps), nsjconf->tmpfs_size,
+             logYesNo(nsjconf->disable_no_new_privs), nsjconf->max_cpus);
 
        {
                struct mounts_t *p;
@@ -322,8 +319,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
       .daemonize = false,
       .tlimit = 0,
       .max_cpus = 0,
-      .keep_global_caps = false,
-      .keep_local_caps = false,
+      .keep_caps = false,
       .disable_no_new_privs = false,
       .rl_as = 512 * (1024 * 1024),
       .rl_core = 0,
@@ -370,8 +366,7 @@ 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);
+       TAILQ_INIT(&nsjconf->caps);
 
        static char cmdlineTmpfsSz[PATH_MAX] = "size=4194304";
 
@@ -529,11 +524,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                case 0x0407:
                        nsjconf->clone_newcgroup = true;
                        break;
-               case 0x0500:
-                       nsjconf->keep_global_caps = true;
-                       break;
                case 0x0501:
-                       nsjconf->keep_local_caps = true;
+                       nsjconf->keep_caps = true;
                        break;
                case 0x0502:
                        nsjconf->is_silent = true;
@@ -559,16 +551,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                                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);
+                               TAILQ_INSERT_HEAD(&nsjconf->caps, f, pointers);
                        }
                        break;
                case 0x0601:
index 18b58e2183fa490f3b16104c620f7c911d15601b..cf7191b6b297d5354457c25c83cfa0a4c5b407ae 100644 (file)
--- a/common.h
+++ b/common.h
@@ -127,8 +127,7 @@ struct nsjconf_t {
        time_t tlimit;
        size_t max_cpus;
        bool keep_env;
-       bool keep_global_caps;
-       bool keep_local_caps;
+       bool keep_caps;
        bool disable_no_new_privs;
        __rlim64_t rl_as;
        __rlim64_t rl_core;
@@ -174,7 +173,7 @@ struct nsjconf_t {
         TAILQ_HEAD(pidslist, pids_t) pids;
         TAILQ_HEAD(mountptslist, mounts_t) mountpts;
         TAILQ_HEAD(fdslistt, ints_t) open_fds;
-        TAILQ_HEAD(capslistt, ints_t) global_caps, local_caps;
+        TAILQ_HEAD(capslistt, ints_t) caps;
 };
 
 #endif                         /* NS_COMMON_H */
index af9bdc0ea218120f175db857b18e0d791e943bd2..2696e5dfb90b4fd9b5243e1d7061c05ac7a4ba1b 100644 (file)
--- a/config.c
+++ b/config.c
@@ -112,8 +112,7 @@ static bool configParseInternal(struct nsjconf_t *nsjconf, Nsjail__NsJailConfig
                TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers);
        }
 
-       nsjconf->keep_local_caps = njc->keep_local_caps;
-       nsjconf->keep_global_caps = njc->keep_global_caps;
+       nsjconf->keep_caps = njc->keep_caps;
        nsjconf->is_silent = njc->silent;
        nsjconf->skip_setsid = njc->skip_setsid;
 
index 5bce133243a1678ef101a5ba75ed84ad770e2328..2d053fc30924b9e24969fecb67d268f992f6eed1 100644 (file)
@@ -108,10 +108,8 @@ message NsJailConfig
     /* EnvVars to be set before executing binaries */
     repeated string envar = 20;
 
-    /* Should local (inside ns) capabilities be preserved or dropped */
-    required bool keep_local_caps = 21 [ default = false ];
-    /* Should global (outside ns) capabilities be preserved or dropped */
-    required bool keep_global_caps = 63 [ default = false ];
+    /* Should capabilities be preserved or dropped */
+    required bool keep_caps = 21 [ default = false ];
     /* Should nsjail close FD=0,1,2 before executing the process */
     required bool silent = 22 [ default = false ];
     /* Should the child process have control over terminal?
index 7437a446250e08a22006002b46203b851505fffb..17a2fd0d81e164ccf03291e97c097e599d2aeef1 100644 (file)
@@ -28,7 +28,7 @@ envar: "TERM=linux"
 envar: "HOME=/"
 envar: "PS1=[\\H:\\t:\\s-\\V:\\w]\\$ "
 
-keep_local_caps: true
+keep_caps: true
 silent: false
 skip_setsid: true
 pass_fd: 100
index 4a24ffa1c964b989c86179ded8811a70352848a3..0c3df8a4eb21bb4379c489b2baf827afcbc01ce0 100644 (file)
--- a/contain.c
+++ b/contain.c
@@ -89,7 +89,7 @@ static bool containDropPrivs(struct nsjconf_t *nsjconf)
                        PLOG_W("prctl(PR_SET_NO_NEW_PRIVS, 1)");
                }
        }
-       if (capsInitLocalNs(nsjconf) == false) {
+       if (capsInitNs(nsjconf) == false) {
                return false;
        }
 
index d001a034bd6d4fff312656fa4861963404d3daae..2930138312c6c0d7b906950f512c23279080bcb5 100644 (file)
--- a/nsjail.c
+++ b/nsjail.c
@@ -185,10 +185,6 @@ 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);