From: Lennart Poettering Date: Tue, 11 Oct 2011 13:16:52 +0000 (+0200) Subject: unit: introduce ConditionCapability X-Git-Tag: v37~5 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=62590f23c14d06e33bb1712a5e3cf04f12f189cb;p=systemd unit: introduce ConditionCapability --- diff --git a/TODO b/TODO index 99e026e3..91490181 100644 --- a/TODO +++ b/TODO @@ -19,7 +19,7 @@ Bugfixes: Features: -* ConditionCapability= +* unset container= in PID1? * if we can not get user quota for tmpfs, mount a separate tmpfs instance for every user in /run/user/$USER with a configured maximum size diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index e47c1467..897f99f2 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -673,6 +673,7 @@ ConditionKernelCommandLine= ConditionVirtualization= ConditionSecurity= + ConditionCapability= ConditionNull= Before starting a unit @@ -749,9 +750,9 @@ value to check if being executed in any virtualized environment, or one of vm and - container to test against - a specific type of virtualization - solution, or one of + container to test + against a specific type of + virtualization solution, or one of qemu, kvm, vmware, @@ -775,7 +776,19 @@ system. Currently the only recognized value is selinux. The test may be negated by prepending - an exclamation mark. Finally, + an exclamation + mark. ConditionCapability= + may be used to check whether the given + capability exists in the capability + bounding set of the service manager + (i.e. this does not check whether + capability is actually available in + the permitted or effective sets, see + capabilities7 + for details). Pass a capability name + such as CAP_MKNOD, + possibly prefixed with an exclamation + mark to negate the check. Finally, ConditionNull= may be used to add a constant condition check value to the unit. It takes a @@ -932,7 +945,8 @@ systemd.target5, systemd.path5, systemd.timer5, - systemd.snapshot5 + systemd.snapshot5, + capabilities7 diff --git a/src/condition.c b/src/condition.c index 07624c84..f18c4542 100644 --- a/src/condition.c +++ b/src/condition.c @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef HAVE_SELINUX #include @@ -159,6 +160,36 @@ static bool test_security(const char *parameter) { return false; } +static bool test_capability(const char *parameter) { + cap_value_t value; + FILE *f; + char line[LINE_MAX]; + unsigned long long capabilities = (unsigned long long) -1; + + /* If it's an invalid capability, we don't have it */ + + if (cap_from_name(parameter, &value) < 0) + return false; + + /* If it's a valid capability we default to assume + * that we have it */ + + f = fopen("/proc/self/status", "re"); + if (!f) + return true; + + while (fgets(line, sizeof(line), f)) { + truncate_nl(line); + + if (startswith(line, "CapBnd:")) { + (void) sscanf(line+7, "%llx", &capabilities); + break; + } + } + + return !!(capabilities & (1ULL << value)); +} + bool condition_test(Condition *c) { assert(c); @@ -214,6 +245,9 @@ bool condition_test(Condition *c) { case CONDITION_SECURITY: return test_security(c->parameter) == !c->negate; + case CONDITION_CAPABILITY: + return test_capability(c->parameter) == !c->negate; + case CONDITION_NULL: return !c->negate; diff --git a/src/condition.h b/src/condition.h index dd65aa60..71b1c676 100644 --- a/src/condition.h +++ b/src/condition.h @@ -37,6 +37,7 @@ typedef enum ConditionType { CONDITION_KERNEL_COMMAND_LINE, CONDITION_VIRTUALIZATION, CONDITION_SECURITY, + CONDITION_CAPABILITY, CONDITION_NULL, _CONDITION_TYPE_MAX, _CONDITION_TYPE_INVALID = -1 diff --git a/src/load-fragment-gperf.gperf.m4 b/src/load-fragment-gperf.gperf.m4 index 7749b88d..41797d20 100644 --- a/src/load-fragment-gperf.gperf.m4 +++ b/src/load-fragment-gperf.gperf.m4 @@ -119,6 +119,7 @@ Unit.ConditionFileIsExecutable, config_parse_unit_condition_path, CONDITION_F Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, 0 Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, 0 Unit.ConditionSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, 0 +Unit.ConditionCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, 0 Unit.ConditionNull, config_parse_unit_condition_null, 0, 0 m4_dnl Service.PIDFile, config_parse_unit_path_printf, 0, offsetof(Service, pid_file)