From 260abb780a135e4cae8c10715c7e85675efc345a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Mar 2011 03:13:15 +0100 Subject: [PATCH] exec: properly apply capability bounding set, add inverted bounding sets --- TODO | 17 +++++++------ man/systemd.exec.xml | 57 +++++++++++++++++++++++++++++++------------- src/dbus-execute.c | 18 ++++++++++++++ src/dbus-execute.h | 3 ++- src/execute.c | 15 +++++++++--- src/load-fragment.c | 21 ++++++++++++++-- 6 files changed, 101 insertions(+), 30 deletions(-) diff --git a/TODO b/TODO index d2614b73..620cdfff 100644 --- a/TODO +++ b/TODO @@ -23,23 +23,26 @@ F15: * 0595f9a1c182a84581749823ef47c5f292e545f9 is borked, freezes shutdown (path: after installing inotify watches, recheck file again to fix race) -* capability_bounding_set_drop not used - -* rework syslog.service being up logic in PID 1 - * rsyslog.service should hook itself into syslog.target? * syslog.target should be pulled in by multi-user.target? * pull in .service from meta .targers AND vice versa too. i.e. syslog.target ←→ rsyslog.service, rpcbind similarly -* drop Names= option? Symlinks only should be used. We don't want to need to read all service files. - Features: + +* hide passwords on TAB + +* add switch to systemctl to show enabled but not running services. Or + another switch that shows service that have been running since + booting but aren't running anymore. + +* reuse mkdtemp namespace dirs in /tmp? + * don't strip facility from kmsg log messages as soon as that is possible. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=9d90c8d9cde929cbc575098e825d7c29d9f45054 -* recreate systemd'd D-Bus private socket file on SIGUSR2 +* recreate systemd's D-Bus private socket file on SIGUSR2 * be more specific what failed: Unmounting file systems. diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index f96d181a..fb8496f5 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -597,16 +597,34 @@ - Capabilities= - Controls the + CapabilityBoundingSet= + + Controls which + capabilities to include in the + capability bounding set for the + executed process. See capabilities7 - set for the executed process. Take a - capability string as described in - cap_from_text3. - Note that this capability set is - usually influenced by the capabilities - attached to the executed - file. + for details. Takes a whitespace + seperated list of capability names as + read by + cap_from_name3. + Capabilities listed will be included + in the bounding set, all others are + removed. If the list of capabilities + is prefixed with ~ all but the listed + capabilities will be included, the + effect of this assignment + inverted. Note that this option does + not actually set or unset any + capabilities in the effective, + permitted or inherited capability + sets. That's what + Capabilities= is + for. If this option is not used the + capability bounding set is not + modified on process execution, hence + no limits on the capabilities of the + process are enforced. @@ -625,16 +643,21 @@ - CapabilityBoundingSetDrop= - + Capabilities= Controls the - capability bounding set drop set for - the executed process. See capabilities7 - for details. Takes a list of - capability names as read by - cap_from_name3. - + set for the executed process. Take a + capability string describing the + effective, permitted and inherited + capability sets as documented in + cap_from_text3. + Note that these capability sets are + usually influenced by the capabilities + attached to the executed file. Due to + that + CapabilityBoundingSet= + is probably the much more useful + setting. diff --git a/src/dbus-execute.c b/src/dbus-execute.c index 504651fc..35e6d377 100644 --- a/src/dbus-execute.c +++ b/src/dbus-execute.c @@ -234,6 +234,24 @@ int bus_execute_append_timer_slack_nsec(Manager *m, DBusMessageIter *i, const ch return 0; } +int bus_execute_append_capability_bs(Manager *m, DBusMessageIter *i, const char *property, void *data) { + ExecContext *c = data; + uint64_t normal, inverted; + + assert(m); + assert(i); + assert(property); + assert(c); + + /* We store this negated internally, to match the kernel, bu + * we expose it normalized. */ + + normal = *(uint64_t*) data; + inverted = ~normal; + + return bus_property_append_uint64(m, i, property, &inverted); +} + int bus_execute_append_capabilities(Manager *m, DBusMessageIter *i, const char *property, void *data) { ExecContext *c = data; char *t = NULL; diff --git a/src/dbus-execute.h b/src/dbus-execute.h index 082456a9..8bfaaaf1 100644 --- a/src/dbus-execute.h +++ b/src/dbus-execute.h @@ -131,7 +131,7 @@ { interface, "SyslogLevelPrefix", bus_property_append_bool, "b", &(context).syslog_level_prefix }, \ { interface, "Capabilities", bus_execute_append_capabilities, "s",&(context) }, \ { interface, "SecureBits", bus_property_append_int, "i", &(context).secure_bits }, \ - { interface, "CapabilityBoundingSetDrop", bus_property_append_uint64, "t", &(context).capability_bounding_set_drop }, \ + { interface, "CapabilityBoundingSet", bus_execute_append_capability_bs, "t", &(context).capability_bounding_set_drop }, \ { interface, "User", bus_property_append_string, "s", (context).user }, \ { interface, "Group", bus_property_append_string, "s", (context).group }, \ { interface, "SupplementaryGroups", bus_property_append_strv, "as", (context).supplementary_groups }, \ @@ -167,6 +167,7 @@ int bus_execute_append_cpu_sched_priority(Manager *m, DBusMessageIter *i, const int bus_execute_append_affinity(Manager *m, DBusMessageIter *i, const char *property, void *data); int bus_execute_append_timer_slack_nsec(Manager *m, DBusMessageIter *i, const char *property, void *data); int bus_execute_append_capabilities(Manager *m, DBusMessageIter *i, const char *property, void *data); +int bus_execute_append_capability_bs(Manager *m, DBusMessageIter *i, const char *property, void *data); int bus_execute_append_rlimits(Manager *m, DBusMessageIter *i, const char *property, void *data); int bus_execute_append_command(Manager *m, DBusMessageIter *u, const char *property, void *data); int bus_execute_append_kill_mode(Manager *m, DBusMessageIter *i, const char *property, void *data); diff --git a/src/execute.c b/src/execute.c index c1edf61f..a467411f 100644 --- a/src/execute.c +++ b/src/execute.c @@ -1249,6 +1249,15 @@ int exec_spawn(ExecCommand *command, } } + if (context->capability_bounding_set_drop) + for (i = 0; i <= CAP_LAST_CAP; i++) + if (context->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) i)) { + if (prctl(PR_CAPBSET_DROP, i) < 0) { + r = EXIT_CAPABILITIES; + goto fail_child; + } + } + if (context->user) if (enforce_user(context, uid) < 0) { r = EXIT_USER; @@ -1664,15 +1673,15 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { (c->secure_bits & SECURE_NOROOT_LOCKED) ? "noroot-locked" : ""); if (c->capability_bounding_set_drop) { - fprintf(f, "%sCapabilityBoundingSetDrop:", prefix); + fprintf(f, "%sCapabilityBoundingSet:", prefix); for (i = 0; i <= CAP_LAST_CAP; i++) - if (c->capability_bounding_set_drop & (1 << i)) { + if (!(c->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) i))) { char *t; if ((t = cap_to_name(i))) { fprintf(f, " %s", t); - free(t); + cap_free(t); } } diff --git a/src/load-fragment.c b/src/load-fragment.c index 334bc713..ac22b945 100644 --- a/src/load-fragment.c +++ b/src/load-fragment.c @@ -852,12 +852,24 @@ static int config_parse_bounding_set( char *w; size_t l; char *state; + bool invert = false; + uint64_t sum = 0; assert(filename); assert(lvalue); assert(rvalue); assert(data); + if (rvalue[0] == '~') { + invert = true; + 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. */ + FOREACH_WORD_QUOTED(w, l, rvalue, state) { char *t; int r; @@ -874,9 +886,14 @@ static int config_parse_bounding_set( return 0; } - c->capability_bounding_set_drop |= 1 << cap; + sum |= ((uint64_t) 1ULL) << (uint64_t) cap; } + if (invert) + c->capability_bounding_set_drop |= sum; + else + c->capability_bounding_set_drop |= ~sum; + return 0; } @@ -1772,7 +1789,7 @@ static int load_from_path(Unit *u, const char *path) { { "SyslogLevelPrefix", config_parse_bool, &(context).syslog_level_prefix, section }, \ { "Capabilities", config_parse_capabilities, &(context), section }, \ { "SecureBits", config_parse_secure_bits, &(context), section }, \ - { "CapabilityBoundingSetDrop", config_parse_bounding_set, &(context), section }, \ + { "CapabilityBoundingSet", config_parse_bounding_set, &(context), section }, \ { "TimerSlackNSec", config_parse_timer_slack_nsec,&(context), section }, \ { "LimitCPU", config_parse_limit, &(context).rlimit[RLIMIT_CPU], section }, \ { "LimitFSIZE", config_parse_limit, &(context).rlimit[RLIMIT_FSIZE], section }, \ -- 2.39.5