From a103496ca585e22bb5e386e3238b468d133f5659 Mon Sep 17 00:00:00 2001 From: Ismo Puustinen Date: Fri, 8 Jan 2016 00:00:04 +0200 Subject: capabilities: keep bounding set in non-inverted format. Change the capability bounding set parser and logic so that the bounding set is kept as a positive set internally. This means that the set reflects those capabilities that we want to keep instead of drop. --- src/core/dbus-execute.c | 4 +--- src/core/execute.c | 9 +++++---- src/core/execute.h | 2 +- src/core/load-fragment-gperf.gperf.m4 | 2 +- src/core/load-fragment.c | 26 ++++++++++++++------------ src/core/load-fragment.h | 2 +- src/core/main.c | 10 +++++----- src/core/unit.c | 2 +- 8 files changed, 29 insertions(+), 28 deletions(-) (limited to 'src/core') diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 1f736b2686..825cef7694 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -293,9 +293,7 @@ static int property_get_capability_bounding_set( assert(reply); assert(c); - /* We store this negated internally, to match the kernel, but - * we expose it normalized. */ - return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop); + return sd_bus_message_append(reply, "t", c->capability_bounding_set); } static int property_get_capabilities( diff --git a/src/core/execute.c b/src/core/execute.c index 9b76861919..7aeb5f1144 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1866,8 +1866,8 @@ static int exec_child( } } - if (context->capability_bounding_set_drop) { - r = capability_bounding_set_drop(context->capability_bounding_set_drop, false); + if (!cap_test_all(context->capability_bounding_set)) { + r = capability_bounding_set_drop(context->capability_bounding_set, false); if (r < 0) { *exit_status = EXIT_CAPABILITIES; return r; @@ -2114,6 +2114,7 @@ void exec_context_init(ExecContext *c) { c->timer_slack_nsec = NSEC_INFINITY; c->personality = PERSONALITY_INVALID; c->runtime_directory_mode = 0755; + c->capability_bounding_set = CAP_ALL; } void exec_context_done(ExecContext *c) { @@ -2517,12 +2518,12 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { (c->secure_bits & 1<secure_bits & 1<capability_bounding_set_drop) { + if (c->capability_bounding_set != CAP_ALL) { unsigned long l; fprintf(f, "%sCapabilityBoundingSet:", prefix); for (l = 0; l <= cap_last_cap(); l++) - if (!(c->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) l))) + if (c->capability_bounding_set & (UINT64_C(1) << l)) fprintf(f, " %s", strna(capability_to_name(l))); fputs("\n", f); diff --git a/src/core/execute.h b/src/core/execute.h index be5be9f531..9d2cdb8728 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -155,7 +155,7 @@ struct ExecContext { char **read_write_dirs, **read_only_dirs, **inaccessible_dirs; unsigned long mount_flags; - uint64_t capability_bounding_set_drop; + uint64_t capability_bounding_set; cap_t capabilities; int secure_bits; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 0408b9a829..862cb8dd3a 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -47,7 +47,7 @@ $1.SyslogLevel, config_parse_log_level, 0, $1.SyslogLevelPrefix, config_parse_bool, 0, offsetof($1, exec_context.syslog_level_prefix) $1.Capabilities, config_parse_exec_capabilities, 0, offsetof($1, exec_context) $1.SecureBits, config_parse_exec_secure_bits, 0, offsetof($1, exec_context) -$1.CapabilityBoundingSet, config_parse_bounding_set, 0, offsetof($1, exec_context.capability_bounding_set_drop) +$1.CapabilityBoundingSet, config_parse_capability_set, 0, offsetof($1, exec_context.capability_bounding_set) $1.TimerSlackNSec, config_parse_nsec, 0, offsetof($1, exec_context.timer_slack_nsec) $1.NoNewPrivileges, config_parse_no_new_privileges, 0, offsetof($1, exec_context) m4_ifdef(`HAVE_SECCOMP', diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index cb553e1252..da14337ba8 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -38,6 +38,7 @@ #include "bus-internal.h" #include "bus-util.h" #include "cap-list.h" +#include "capability-util.h" #include "cgroup.h" #include "conf-parser.h" #include "cpu-set-util.h" @@ -1024,7 +1025,7 @@ int config_parse_exec_secure_bits(const char *unit, return 0; } -int config_parse_bounding_set( +int config_parse_capability_set( const char *unit, const char *filename, unsigned line, @@ -1036,8 +1037,8 @@ int config_parse_bounding_set( void *data, void *userdata) { - uint64_t *capability_bounding_set_drop = data; - uint64_t capability_bounding_set, sum = 0; + uint64_t *capability_set = data; + uint64_t sum = 0, initial = 0; bool invert = false; const char *p; @@ -1051,10 +1052,8 @@ int config_parse_bounding_set( rvalue++; } - /* Note that we store this inverted internally, since the - * kernel wants it like this. But we actually expose it - * non-inverted everywhere to have a fully normalized - * interface. */ + if (strcmp(lvalue, "CapabilityBoundingSet") == 0) + initial = CAP_ALL; /* initialized to all bits on */ p = rvalue; for (;;) { @@ -1080,11 +1079,14 @@ int config_parse_bounding_set( sum |= ((uint64_t) UINT64_C(1)) << (uint64_t) cap; } - capability_bounding_set = invert ? ~sum : sum; - if (*capability_bounding_set_drop != 0 && capability_bounding_set != 0) - *capability_bounding_set_drop = ~(~*capability_bounding_set_drop | capability_bounding_set); + sum = invert ? ~sum : sum; + + if (sum == 0 || *capability_set == initial) + /* "" or uninitialized data -> replace */ + *capability_set = sum; else - *capability_bounding_set_drop = ~capability_bounding_set; + /* previous data -> merge */ + *capability_set |= sum; return 0; } @@ -4002,7 +4004,7 @@ void unit_dump_config_items(FILE *f) { { config_parse_log_level, "LEVEL" }, { config_parse_exec_capabilities, "CAPABILITIES" }, { config_parse_exec_secure_bits, "SECUREBITS" }, - { config_parse_bounding_set, "BOUNDINGSET" }, + { config_parse_capability_set, "BOUNDINGSET" }, { config_parse_limit, "LIMIT" }, { config_parse_unit_deps, "UNIT [...]" }, { config_parse_exec, "PATH [ARGUMENT [...]]" }, diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index a451fc164a..f0027a6b43 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -56,7 +56,7 @@ int config_parse_exec_cpu_sched_prio(const char *unit, const char *filename, uns int config_parse_exec_cpu_affinity(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_capabilities(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_secure_bits(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); -int config_parse_bounding_set(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_capability_set(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bytes_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_sec_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/core/main.c b/src/core/main.c index f9de54028e..7a428fcccf 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -117,7 +117,7 @@ static usec_t arg_runtime_watchdog = 0; static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE; static char **arg_default_environment = NULL; static struct rlimit *arg_default_rlimit[_RLIMIT_MAX] = {}; -static uint64_t arg_capability_bounding_set_drop = 0; +static uint64_t arg_capability_bounding_set = CAP_ALL; static nsec_t arg_timer_slack_nsec = NSEC_INFINITY; static usec_t arg_default_timer_accuracy_usec = 1 * USEC_PER_MINUTE; static Set* arg_syscall_archs = NULL; @@ -644,7 +644,7 @@ static int parse_config_file(void) { { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers }, { "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog }, { "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog }, - { "Manager", "CapabilityBoundingSet", config_parse_bounding_set, 0, &arg_capability_bounding_set_drop }, + { "Manager", "CapabilityBoundingSet", config_parse_capability_set, 0, &arg_capability_bounding_set }, #ifdef HAVE_SECCOMP { "Manager", "SystemCallArchitectures", config_parse_syscall_archs, 0, &arg_syscall_archs }, #endif @@ -1631,14 +1631,14 @@ int main(int argc, char *argv[]) { if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0) log_error_errno(errno, "Failed to adjust timer slack: %m"); - if (arg_capability_bounding_set_drop) { - r = capability_bounding_set_drop_usermode(arg_capability_bounding_set_drop); + if (!cap_test_all(arg_capability_bounding_set)) { + r = capability_bounding_set_drop_usermode(arg_capability_bounding_set); if (r < 0) { log_emergency_errno(r, "Failed to drop capability bounding set of usermode helpers: %m"); error_message = "Failed to drop capability bounding set of usermode helpers"; goto finish; } - r = capability_bounding_set_drop(arg_capability_bounding_set_drop, true); + r = capability_bounding_set_drop(arg_capability_bounding_set, true); if (r < 0) { log_emergency_errno(r, "Failed to drop capability bounding set: %m"); error_message = "Failed to drop capability bounding set"; diff --git a/src/core/unit.c b/src/core/unit.c index b977ac7f0c..e1bc6c75cb 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3231,7 +3231,7 @@ int unit_patch_contexts(Unit *u) { ec->no_new_privileges = true; if (ec->private_devices) - ec->capability_bounding_set_drop |= (uint64_t) 1ULL << (uint64_t) CAP_MKNOD; + ec->capability_bounding_set &= ~(UINT64_C(1) << CAP_MKNOD); } cc = unit_get_cgroup_context(u); -- cgit v1.2.3