[systemd-commits] TODO man/systemd.unit.xml src/condition.c src/condition.h src/load-fragment-gperf.gperf.m4

Lennart Poettering lennart at kemper.freedesktop.org
Tue Oct 11 06:16:59 PDT 2011


 TODO                             |    2 +-
 man/systemd.unit.xml             |   24 +++++++++++++++++++-----
 src/condition.c                  |   34 ++++++++++++++++++++++++++++++++++
 src/condition.h                  |    1 +
 src/load-fragment-gperf.gperf.m4 |    1 +
 5 files changed, 56 insertions(+), 6 deletions(-)

New commits:
commit 62590f23c14d06e33bb1712a5e3cf04f12f189cb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Oct 11 15:16:52 2011 +0200

    unit: introduce ConditionCapability

diff --git a/TODO b/TODO
index 99e026e..9149018 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 e47c146..897f99f 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -673,6 +673,7 @@
                                 <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
@@ -749,9 +750,9 @@
                                 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>,
@@ -775,7 +776,19 @@
                                 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
@@ -932,7 +945,8 @@
                         <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>
 
diff --git a/src/condition.c b/src/condition.c
index 07624c8..f18c454 100644
--- a/src/condition.c
+++ b/src/condition.c
@@ -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;
 
diff --git a/src/condition.h b/src/condition.h
index dd65aa6..71b1c67 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 7749b88..41797d2 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)



More information about the systemd-commits mailing list