diff --git a/caps.c b/caps.c index 9ea27db..c73a0ec 100644 --- 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 516739d..a268cb7 100644 --- 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 */ diff --git a/cmdline.c b/cmdline.c index 724014f..d9abc69 100644 --- 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: diff --git a/common.h b/common.h index 18b58e2..cf7191b 100644 --- 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 */ diff --git a/config.c b/config.c index af9bdc0..2696e5d 100644 --- 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; diff --git a/config.proto b/config.proto index 5bce133..2d053fc 100644 --- a/config.proto +++ b/config.proto @@ -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? diff --git a/configs/bash-with-fake-geteuid.cfg b/configs/bash-with-fake-geteuid.cfg index 7437a44..17a2fd0 100644 --- a/configs/bash-with-fake-geteuid.cfg +++ b/configs/bash-with-fake-geteuid.cfg @@ -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 diff --git a/contain.c b/contain.c index 4a24ffa..0c3df8a 100644 --- 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; } diff --git a/nsjail.c b/nsjail.c index d001a03..2930138 100644 --- 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);