chiark / gitweb /
condition: properly allow passing back errors from condition checks
[elogind.git] / src / core / condition.c
index 410fb36797808757f39bcf71fca52af994a6629f..32135ec5b2b83242a5a9c918c40b8356b2ca0128 100644 (file)
 #include "apparmor-util.h"
 #include "ima-util.h"
 #include "selinux-util.h"
+#include "audit.h"
 
-static bool condition_test_security(Condition *c) {
+static int condition_test_security(Condition *c) {
         assert(c);
         assert(c->parameter);
         assert(c->type == CONDITION_SECURITY);
 
         if (streq(c->parameter, "selinux"))
-                return use_selinux() == !c->negate;
+                return mac_selinux_use() == !c->negate;
+        if (streq(c->parameter, "smack"))
+                return mac_smack_use() == !c->negate;
         if (streq(c->parameter, "apparmor"))
-                return use_apparmor() == !c->negate;
+                return mac_apparmor_use() == !c->negate;
+        if (streq(c->parameter, "audit"))
+                return use_audit() == !c->negate;
         if (streq(c->parameter, "ima"))
                 return use_ima() == !c->negate;
-        if (streq(c->parameter, "smack"))
-                return use_smack() == !c->negate;
 
         return c->negate;
 }
 
-static bool condition_test_capability(Condition *c) {
+static int condition_test_capability(Condition *c) {
         _cleanup_fclose_ FILE *f = NULL;
         cap_value_t value;
         char line[LINE_MAX];
@@ -69,14 +72,14 @@ static bool condition_test_capability(Condition *c) {
         /* If it's an invalid capability, we don't have it */
 
         if (cap_from_name(c->parameter, &value) < 0)
-                return c->negate;
+                return -EINVAL;
 
         /* If it's a valid capability we default to assume
          * that we have it */
 
         f = fopen("/proc/self/status", "re");
         if (!f)
-                return !c->negate;
+                return -errno;
 
         while (fgets(line, sizeof(line), f)) {
                 truncate_nl(line);
@@ -120,7 +123,21 @@ static bool condition_test_needs_update(Condition *c) {
                 (usr.st_mtim.tv_sec == other.st_mtim.tv_sec && usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec)) == !c->negate;
 }
 
-static bool condition_test(Condition *c) {
+static bool condition_test_first_boot(Condition *c) {
+        int r;
+
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_FIRST_BOOT);
+
+        r = parse_boolean(c->parameter);
+        if (r < 0)
+                return r;
+
+        return ((access("/run/systemd/first-boot", F_OK) >= 0) == !!r) == !c->negate;
+}
+
+static int condition_test(Condition *c) {
         assert(c);
 
         switch(c->type) {
@@ -202,6 +219,9 @@ static bool condition_test(Condition *c) {
         case CONDITION_NEEDS_UPDATE:
                 return condition_test_needs_update(c);
 
+        case CONDITION_FIRST_BOOT:
+                return condition_test_first_boot(c);
+
         case CONDITION_NULL:
                 return !c->negate;
 
@@ -222,25 +242,35 @@ bool condition_test_list(const char *unit, Condition *first) {
          * if any of the trigger conditions apply (unless there are
          * none) we return true */
         LIST_FOREACH(conditions, c, first) {
-                bool b;
-
-                b = condition_test(c);
-                if (unit)
+                int r;
+
+                r = condition_test(c);
+                if (r < 0)
+                        log_warning_unit(unit,
+                                         "Couldn't determine result for %s=%s%s%s for %s, assuming failed: %s",
+                                         condition_type_to_string(c->type),
+                                         c->trigger ? "|" : "",
+                                         c->negate ? "!" : "",
+                                         c->parameter,
+                                         unit,
+                                         strerror(-r));
+                else
                         log_debug_unit(unit,
                                        "%s=%s%s%s %s for %s.",
                                        condition_type_to_string(c->type),
                                        c->trigger ? "|" : "",
                                        c->negate ? "!" : "",
                                        c->parameter,
-                                       b ? "succeeded" : "failed",
+                                       r > 0 ? "succeeded" : "failed",
                                        unit);
-                c->state = b ? 1 : -1;
 
-                if (!c->trigger && !b)
+                c->state = r > 0 ? CONDITION_STATE_SUCCEEDED : CONDITION_STATE_FAILED;
+
+                if (!c->trigger && r <= 0)
                         return false;
 
                 if (c->trigger && triggered <= 0)
-                        triggered = b;
+                        triggered = r > 0;
         }
 
         return triggered != 0;