X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Fcapability.c;h=f8ee1c6838b63d00d1ad259c95b16dbd79e6e084;hb=981e4cd325410384cdadd837f34c002699d2d750;hp=08b7a209da6bd4674ca5da523c1b0676a7c7c626;hpb=ec8927ca5940e809f0b72f530582c76f1db4f065;p=elogind.git diff --git a/src/shared/capability.c b/src/shared/capability.c index 08b7a209d..f8ee1c683 100644 --- a/src/shared/capability.c +++ b/src/shared/capability.c @@ -34,28 +34,25 @@ #include "capability.h" #include "util.h" #include "log.h" +#include "fileio.h" int have_effective_cap(int value) { - cap_t cap; + _cleanup_cap_free_ cap_t cap; cap_flag_value_t fv; - int r; cap = cap_get_proc(); if (!cap) return -errno; if (cap_get_flag(cap, value, CAP_EFFECTIVE, &fv) < 0) - r = -errno; + return -errno; else - r = fv == CAP_SET; - - cap_free(cap); - return r; + return fv == CAP_SET; } unsigned long cap_last_cap(void) { - static __thread unsigned long saved; - static __thread bool valid = false; + static thread_local unsigned long saved; + static thread_local bool valid = false; unsigned long p; if (valid) @@ -88,7 +85,7 @@ unsigned long cap_last_cap(void) { int capability_bounding_set_drop(uint64_t drop, bool right_now) { unsigned long i; - cap_t after_cap = NULL, temp_cap = NULL; + _cleanup_cap_free_ cap_t after_cap = NULL, temp_cap = NULL; cap_flag_value_t fv; int r; @@ -101,10 +98,8 @@ int capability_bounding_set_drop(uint64_t drop, bool right_now) { if (!after_cap) return -errno; - if (cap_get_flag(after_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0) { - cap_free(after_cap); + if (cap_get_flag(after_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0) return -errno; - } if (fv != CAP_SET) { static const cap_value_t v = CAP_SETPCAP; @@ -136,7 +131,7 @@ int capability_bounding_set_drop(uint64_t drop, bool right_now) { r = -errno; goto finish; } - v = i; + v = (cap_value_t) i; /* Also drop it from the inheritable set, so * that anything we exec() loses the @@ -161,13 +156,58 @@ int capability_bounding_set_drop(uint64_t drop, bool right_now) { r = 0; finish: - if (temp_cap) - cap_free(temp_cap); + cap_set_proc(after_cap); - if (after_cap) { - cap_set_proc(after_cap); - cap_free(after_cap); - } + 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_string_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; }