X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fexecute.c;h=745dcfcdb8526d76c8c981546ebf756f91b99a03;hb=ec2002f84928c0b5921a961cb2b8637563f29daa;hp=b7ae522692f452f23b9107255e76aec5d07ac47d;hpb=da19d5c19f60ec80e1733b1e994311c59c6eda73;p=elogind.git diff --git a/src/execute.c b/src/execute.c index b7ae52269..745dcfcdb 100644 --- a/src/execute.c +++ b/src/execute.c @@ -904,6 +904,68 @@ fail: } #endif +static int do_capability_bounding_set_drop(uint64_t drop) { + unsigned long i; + cap_t old_cap = NULL, new_cap = NULL; + cap_flag_value_t fv; + int r; + + /* If we are run as PID 1 we will lack CAP_SETPCAP by default + * in the effective set (yes, the kernel drops that when + * executing init!), so get it back temporarily so that we can + * call PR_CAPBSET_DROP. */ + + old_cap = cap_get_proc(); + if (!old_cap) + return -errno; + + if (cap_get_flag(old_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0) { + r = -errno; + goto finish; + } + + if (fv != CAP_SET) { + static const cap_value_t v = CAP_SETPCAP; + + new_cap = cap_dup(old_cap); + if (!new_cap) { + r = -errno; + goto finish; + } + + if (cap_set_flag(new_cap, CAP_EFFECTIVE, 1, &v, CAP_SET) < 0) { + r = -errno; + goto finish; + } + + if (cap_set_proc(new_cap) < 0) { + r = -errno; + goto finish; + } + } + + for (i = 0; i <= CAP_LAST_CAP; i++) + if (drop & ((uint64_t) 1ULL << (uint64_t) i)) { + if (prctl(PR_CAPBSET_DROP, i) < 0) { + r = -errno; + goto finish; + } + } + + r = 0; + +finish: + if (new_cap) + cap_free(new_cap); + + if (old_cap) { + cap_set_proc(old_cap); + cap_free(old_cap); + } + + return r; +} + int exec_spawn(ExecCommand *command, char **argv, const ExecContext *context, @@ -981,7 +1043,7 @@ int exec_spawn(ExecCommand *command, /* This string must fit in 10 chars (i.e. the length * of "/sbin/init") */ - rename_process("sd:exec"); + rename_process("sd.exec"); /* We reset exactly these signals, since they are the * only ones we set to SIG_IGN in the main daemon. All @@ -1106,7 +1168,8 @@ int exec_spawn(ExecCommand *command, snprintf(t, sizeof(t), "%i", adj); char_array_0(t); - if (write_one_line_file("/proc/self/oom_adj", t) < 0) { + if (write_one_line_file("/proc/self/oom_adj", t) < 0 + && errno != EACCES) { r = EXIT_OOM_ADJUST; goto fail_child; } @@ -1250,13 +1313,10 @@ 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 (do_capability_bounding_set_drop(context->capability_bounding_set_drop) < 0) { + r = EXIT_CAPABILITIES; + goto fail_child; + } if (context->user) if (enforce_user(context, uid) < 0) { @@ -1650,7 +1710,7 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { fprintf(f, "%sSyslogFacility: %s\n" "%sSyslogLevel: %s\n", - prefix, log_facility_to_string(LOG_FAC(c->syslog_priority)), + prefix, log_facility_unshifted_to_string(c->syslog_priority >> 3), prefix, log_level_to_string(LOG_PRI(c->syslog_priority))); if (c->capabilities) {