unit: introduce ConditionCapability

This commit is contained in:
Lennart Poettering 2011-10-11 15:16:52 +02:00
parent 822b18599d
commit 62590f23c1
5 changed files with 56 additions and 6 deletions

2
TODO
View file

@ -19,7 +19,7 @@ Bugfixes:
Features: Features:
* ConditionCapability= * unset container= in PID1?
* if we can not get user quota for tmpfs, mount a separate tmpfs instance * 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 for every user in /run/user/$USER with a configured maximum size

View file

@ -673,6 +673,7 @@
<term><varname>ConditionKernelCommandLine=</varname></term> <term><varname>ConditionKernelCommandLine=</varname></term>
<term><varname>ConditionVirtualization=</varname></term> <term><varname>ConditionVirtualization=</varname></term>
<term><varname>ConditionSecurity=</varname></term> <term><varname>ConditionSecurity=</varname></term>
<term><varname>ConditionCapability=</varname></term>
<term><varname>ConditionNull=</varname></term> <term><varname>ConditionNull=</varname></term>
<listitem><para>Before starting a unit <listitem><para>Before starting a unit
@ -749,9 +750,9 @@
value to check if being executed in value to check if being executed in
any virtualized environment, or one of any virtualized environment, or one of
<varname>vm</varname> and <varname>vm</varname> and
<varname>container</varname> to test against <varname>container</varname> to test
a specific type of virtualization against a specific type of
solution, or one of virtualization solution, or one of
<varname>qemu</varname>, <varname>qemu</varname>,
<varname>kvm</varname>, <varname>kvm</varname>,
<varname>vmware</varname>, <varname>vmware</varname>,
@ -775,7 +776,19 @@
system. Currently the only recognized system. Currently the only recognized
value is <varname>selinux</varname>. value is <varname>selinux</varname>.
The test may be negated by prepending The test may be negated by prepending
an exclamation mark. Finally, an exclamation
mark. <varname>ConditionCapability=</varname>
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
<citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for details). Pass a capability name
such as <literal>CAP_MKNOD</literal>,
possibly prefixed with an exclamation
mark to negate the check. Finally,
<varname>ConditionNull=</varname> may <varname>ConditionNull=</varname> may
be used to add a constant condition be used to add a constant condition
check value to the unit. It takes a check value to the unit. It takes a
@ -932,7 +945,8 @@
<citerefentry><refentrytitle>systemd.target</refentrytitle><manvolnum>5</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd.target</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.path</refentrytitle><manvolnum>5</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd.path</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.snapshot</refentrytitle><manvolnum>5</manvolnum></citerefentry> <citerefentry><refentrytitle>systemd.snapshot</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
</para> </para>
</refsect1> </refsect1>

View file

@ -23,6 +23,7 @@
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/capability.h>
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
#include <selinux/selinux.h> #include <selinux/selinux.h>
@ -159,6 +160,36 @@ static bool test_security(const char *parameter) {
return false; 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) { bool condition_test(Condition *c) {
assert(c); assert(c);
@ -214,6 +245,9 @@ bool condition_test(Condition *c) {
case CONDITION_SECURITY: case CONDITION_SECURITY:
return test_security(c->parameter) == !c->negate; return test_security(c->parameter) == !c->negate;
case CONDITION_CAPABILITY:
return test_capability(c->parameter) == !c->negate;
case CONDITION_NULL: case CONDITION_NULL:
return !c->negate; return !c->negate;

View file

@ -37,6 +37,7 @@ typedef enum ConditionType {
CONDITION_KERNEL_COMMAND_LINE, CONDITION_KERNEL_COMMAND_LINE,
CONDITION_VIRTUALIZATION, CONDITION_VIRTUALIZATION,
CONDITION_SECURITY, CONDITION_SECURITY,
CONDITION_CAPABILITY,
CONDITION_NULL, CONDITION_NULL,
_CONDITION_TYPE_MAX, _CONDITION_TYPE_MAX,
_CONDITION_TYPE_INVALID = -1 _CONDITION_TYPE_INVALID = -1

View file

@ -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.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, 0
Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, 0 Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, 0
Unit.ConditionSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, 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 Unit.ConditionNull, config_parse_unit_condition_null, 0, 0
m4_dnl m4_dnl
Service.PIDFile, config_parse_unit_path_printf, 0, offsetof(Service, pid_file) Service.PIDFile, config_parse_unit_path_printf, 0, offsetof(Service, pid_file)