caps: just local caps
This commit is contained in:
parent
54a522326f
commit
39ce9d22a7
27
caps.c
27
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 */ );
|
||||
}
|
||||
|
3
caps.h
3
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 */
|
||||
|
37
cmdline.c
37
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:
|
||||
|
5
common.h
5
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 */
|
||||
|
3
config.c
3
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;
|
||||
|
||||
|
@ -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?
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user