From 939b8f14dcd9312140d001b55b4e7a87173682ef Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 May 2012 23:33:38 +0200 Subject: [PATCH] capabilities: when dropping capabilities system-wide also drop them from usermode helpers This hooks things up with /proc/sys/kernel/usermodehelper/bset and /proc/sys/kernel/usermodehelper/inheritable. --- TODO | 12 +++++----- src/core/main.c | 5 ++++ src/shared/capability.c | 51 +++++++++++++++++++++++++++++++++++++++++ src/shared/capability.h | 3 ++- 4 files changed, 64 insertions(+), 7 deletions(-) diff --git a/TODO b/TODO index 4742981c0..3b3c451c7 100644 --- a/TODO +++ b/TODO @@ -6,9 +6,9 @@ Fedora 18: * chrony/ntp target? Bugfixes: -* fix building of --disable-logind, hournald and coredunp pull-in parts of sd_login +* log_warning() in journald gets looped back into journal via kmsg? -* fix emergency mode breakage after the Type=idle change +* fix building of --disable-logind, hournald and coredunp pull-in parts of sd_login * remove MS_SHARED from src/core/execute.c and src/test/test-ns.c. They are always combined with MS_REMOUNT, which currently does nothing in the kernel, but might which fail in the @@ -31,7 +31,9 @@ Bugfixes: * properly handle .mount unit state tracking when two mount points are stacked one on top of another on the exact same mount point. Features: -* logind: listen to power/suspend/lid-button events +* parse kernel cmdline option for capability bset + +* logind: listen to power-button events - run poweroff if no session is active - console session should beep when we refuse to poweroff - graphical sessions will show a dialog, like they do already today @@ -39,8 +41,6 @@ Features: * journalctl /dev/sda, journalctl /usr/bin/httpd, journalctl --device=b12:8 (--device=n12, --device=+usb:1-1) -* also reset /proc/sys/kernel/usermodehelper/bset /proc/sys/kernel/usermodehelper/inheritable in system.conf's CapabilityBoundingSet= - * make use of /sys/power/wake_lock in inhibitors * introduce "systemctl help" which invokes man for the man pages listed in Documentation= @@ -49,7 +49,7 @@ Features: * make sure show-logs checks for utf8 validity, not ascii validity -* add CapbilityBoundingSet to system.conf to set system-wide caps bounds, and same for TimerSlackNS +* add TimerSlackNS to system.conf to set system-wide caps bounds * when breaking cycles drop sysv services first, then services from /run, then from /etc, then from /usr diff --git a/src/core/main.c b/src/core/main.c index 9248c388a..4c3ee7d5a 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1493,6 +1493,11 @@ int main(int argc, char *argv[]) { log_error("Failed to drop capability bounding set: %s", strerror(-r)); goto finish; } + r = capability_bounding_set_drop_usermode(arg_capability_bounding_set_drop); + if (r < 0) { + log_error("Failed to drop capability bounding set of usermode helpers: %s", strerror(-r)); + goto finish; + } } r = manager_new(arg_running_as, &m); diff --git a/src/shared/capability.c b/src/shared/capability.c index 08b7a209d..9b743e86d 100644 --- a/src/shared/capability.c +++ b/src/shared/capability.c @@ -171,3 +171,54 @@ finish: return r; } + +static int drop_from_file(const char *fn, uint64_t drop) { + int r, k; + uint32_t hi, lo; + uint64_t current, after; + char *p; + + r = read_one_line_file(fn, &p); + if (r < 0) + return r; + + assert_cc(sizeof(hi) == sizeof(unsigned)); + assert_cc(sizeof(lo) == sizeof(unsigned)); + + k = sscanf(p, "%u %u", &lo, &hi); + free(p); + + if (k != 2) + return -EIO; + + current = (uint64_t) lo | ((uint64_t) hi << 32ULL); + after = current & ~drop; + + if (current == after) + return 0; + + lo = (unsigned) (after & 0xFFFFFFFFULL); + hi = (unsigned) ((after >> 32ULL) & 0xFFFFFFFFULL); + + if (asprintf(&p, "%u %u", lo, hi) < 0) + return -ENOMEM; + + r = write_one_line_file(fn, p); + free(p); + + return r; +} + +int capability_bounding_set_drop_usermode(uint64_t drop) { + int r; + + r = drop_from_file("/proc/sys/kernel/usermodehelper/inheritable", drop); + if (r < 0) + return r; + + r = drop_from_file("/proc/sys/kernel/usermodehelper/bset", drop); + if (r < 0) + return r; + + return r; +} diff --git a/src/shared/capability.h b/src/shared/capability.h index 0cc5dd08a..6cb31bb51 100644 --- a/src/shared/capability.h +++ b/src/shared/capability.h @@ -27,6 +27,7 @@ unsigned long cap_last_cap(void); int have_effective_cap(int value); -int capability_bounding_set_drop(uint64_t caps, bool right_now); +int capability_bounding_set_drop(uint64_t drop, bool right_now); +int capability_bounding_set_drop_usermode(uint64_t drop); #endif -- 2.30.2