chiark / gitweb /
unit: introduce ConditionCapability
authorLennart Poettering <lennart@poettering.net>
Tue, 11 Oct 2011 13:16:52 +0000 (15:16 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 11 Oct 2011 13:16:52 +0000 (15:16 +0200)
TODO
man/systemd.unit.xml
src/condition.c
src/condition.h
src/load-fragment-gperf.gperf.m4

diff --git a/TODO b/TODO
index 99e026e3c1d0f0493d1b3aeaf31f3d73343bdf78..91490181342da379bbf4b1e84a59f713364e6a1d 100644 (file)
--- 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
index e47c14679e36c5c296bb881e1369b64d0694aeb4..897f99f24cd64fe434ee8481907208a2a2005f4a 100644 (file)
                                 <term><varname>ConditionKernelCommandLine=</varname></term>
                                 <term><varname>ConditionVirtualization=</varname></term>
                                 <term><varname>ConditionSecurity=</varname></term>
+                                <term><varname>ConditionCapability=</varname></term>
                                 <term><varname>ConditionNull=</varname></term>
 
                                 <listitem><para>Before starting a unit
                                 value to check if being executed in
                                 any virtualized environment, or one of
                                 <varname>vm</varname> and
-                                <varname>container</varname> to test against
-                                a specific type of virtualization
-                                solution, or one of
+                                <varname>container</varname> to test
+                                against a specific type of
+                                virtualization solution, or one of
                                 <varname>qemu</varname>,
                                 <varname>kvm</varname>,
                                 <varname>vmware</varname>,
                                 system.  Currently the only recognized
                                 value is <varname>selinux</varname>.
                                 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
                                 be used to add a constant condition
                                 check value to the unit. It takes a
                         <citerefentry><refentrytitle>systemd.target</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.snapshot</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+                        <citerefentry><refentrytitle>systemd.snapshot</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+                        <citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
                 </para>
         </refsect1>
 
index 07624c841daf2b20f38bb7f3e431ae568d7b57c4..f18c45421a08bf935f542ebad22312ae58a92c45 100644 (file)
@@ -23,6 +23,7 @@
 #include <errno.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/capability.h>
 
 #ifdef HAVE_SELINUX
 #include <selinux/selinux.h>
@@ -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;
 
index dd65aa60543895ce327475a8dfb7fb3afdb766e7..71b1c6761e58d14a54d56d6ff79a26b6e7e6116c 100644 (file)
@@ -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
index 7749b88dfb2c4ae2bcc36d596a1e763cbf8c7775..41797d20c0f095d27a9007b6e4d33d5888af97bc 100644 (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.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)