]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/shared/condition.c
Merge pull request #11827 from keszybz/pkgconfig-variables
[thirdparty/systemd.git] / src / shared / condition.c
index d4bbaf3c65d22e58936a377e9227b5690899e7ac..fb77966264e41a85f475f0d0a5d941a7918111c4 100644 (file)
@@ -1,22 +1,4 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
-/***
-  This file is part of systemd.
-
-  Copyright 2010 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
 
 #include <errno.h>
 #include <fcntl.h>
@@ -26,6 +8,7 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/utsname.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -38,6 +21,7 @@
 #include "cap-list.h"
 #include "cgroup-util.h"
 #include "condition.h"
+#include "efivars.h"
 #include "extract-word.h"
 #include "fd-util.h"
 #include "fileio.h"
@@ -46,7 +30,8 @@
 #include "ima-util.h"
 #include "list.h"
 #include "macro.h"
-#include "mount-util.h"
+#include "mountpoint-util.h"
+#include "env-file.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "proc-cmdline.h"
@@ -115,7 +100,7 @@ static int condition_test_kernel_command_line(Condition *c) {
         if (r < 0)
                 return r;
 
-        equal = !!strchr(c->parameter, '=');
+        equal = strchr(c->parameter, '=');
 
         for (p = line;;) {
                 _cleanup_free_ char *word = NULL;
@@ -143,6 +128,70 @@ static int condition_test_kernel_command_line(Condition *c) {
         return false;
 }
 
+static int condition_test_kernel_version(Condition *c) {
+        enum {
+                /* Listed in order of checking. Note that some comparators are prefixes of others, hence the longest
+                 * should be listed first. */
+                LOWER_OR_EQUAL,
+                GREATER_OR_EQUAL,
+                LOWER,
+                GREATER,
+                EQUAL,
+                _ORDER_MAX,
+        };
+
+        static const char *const prefix[_ORDER_MAX] = {
+                [LOWER_OR_EQUAL] = "<=",
+                [GREATER_OR_EQUAL] = ">=",
+                [LOWER] = "<",
+                [GREATER] = ">",
+                [EQUAL] = "=",
+        };
+        const char *p = NULL;
+        struct utsname u;
+        size_t i;
+        int k;
+
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_KERNEL_VERSION);
+
+        assert_se(uname(&u) >= 0);
+
+        for (i = 0; i < _ORDER_MAX; i++) {
+                p = startswith(c->parameter, prefix[i]);
+                if (p)
+                        break;
+        }
+
+        /* No prefix? Then treat as glob string */
+        if (!p)
+                return fnmatch(skip_leading_chars(c->parameter, NULL), u.release, 0) == 0;
+
+        k = str_verscmp(u.release, skip_leading_chars(p, NULL));
+
+        switch (i) {
+
+        case LOWER:
+                return k < 0;
+
+        case LOWER_OR_EQUAL:
+                return k <= 0;
+
+        case EQUAL:
+                return k == 0;
+
+        case GREATER_OR_EQUAL:
+                return k >= 0;
+
+        case GREATER:
+                return k > 0;
+
+        default:
+                assert_not_reached("Can't compare");
+        }
+}
+
 static int condition_test_user(Condition *c) {
         uid_t id;
         int r;
@@ -171,7 +220,7 @@ static int condition_test_user(Condition *c) {
                 return streq(c->parameter, "root");
 
         u = c->parameter;
-        r = get_user_creds(&u, &id, NULL, NULL, NULL);
+        r = get_user_creds(&u, &id, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING);
         if (r < 0)
                 return 0;
 
@@ -199,7 +248,7 @@ static int condition_test_control_group_controller(Condition *c) {
                 return 1;
         }
 
-        return (system_mask & wanted_mask) == wanted_mask;
+        return FLAGS_SET(system_mask, wanted_mask);
 }
 
 static int condition_test_group(Condition *c) {
@@ -329,15 +378,16 @@ static int condition_test_security(Condition *c) {
                 return use_ima();
         if (streq(c->parameter, "tomoyo"))
                 return mac_tomoyo_use();
+        if (streq(c->parameter, "uefi-secureboot"))
+                return is_efi_secure_boot();
 
         return false;
 }
 
 static int condition_test_capability(Condition *c) {
+        unsigned long long capabilities = (unsigned long long) -1;
         _cleanup_fclose_ FILE *f = NULL;
-        int value;
-        char line[LINE_MAX];
-        unsigned long long capabilities = -1;
+        int value, r;
 
         assert(c);
         assert(c->parameter);
@@ -355,11 +405,21 @@ static int condition_test_capability(Condition *c) {
         if (!f)
                 return -errno;
 
-        while (fgets(line, sizeof(line), f)) {
-                truncate_nl(line);
+        for (;;) {
+                _cleanup_free_ char *line = NULL;
+                const char *p;
+
+                r = read_line(f, LONG_LINE_MAX, &line);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                p = startswith(line, "CapBnd:");
+                if (p) {
+                        if (sscanf(line+7, "%llx", &capabilities) != 1)
+                                return -EIO;
 
-                if (startswith(line, "CapBnd:")) {
-                        (void) sscanf(line+7, "%llx", &capabilities);
                         break;
                 }
         }
@@ -412,7 +472,7 @@ static int condition_test_needs_update(Condition *c) {
                 uint64_t timestamp;
                 int r;
 
-                r = parse_env_file(p, NULL, "TIMESTAMP_NSEC", &timestamp_str, NULL);
+                r = parse_env_file(NULL, p, "TIMESTAMP_NSEC", &timestamp_str);
                 if (r < 0) {
                         log_error_errno(r, "Failed to parse timestamp file '%s', using mtime: %m", p);
                         return true;
@@ -552,6 +612,7 @@ int condition_test(Condition *c) {
                 [CONDITION_FILE_NOT_EMPTY] = condition_test_file_not_empty,
                 [CONDITION_FILE_IS_EXECUTABLE] = condition_test_file_is_executable,
                 [CONDITION_KERNEL_COMMAND_LINE] = condition_test_kernel_command_line,
+                [CONDITION_KERNEL_VERSION] = condition_test_kernel_version,
                 [CONDITION_VIRTUALIZATION] = condition_test_virtualization,
                 [CONDITION_SECURITY] = condition_test_security,
                 [CONDITION_CAPABILITY] = condition_test_capability,
@@ -587,8 +648,7 @@ void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_
         assert(c);
         assert(f);
 
-        if (!prefix)
-                prefix = "";
+        prefix = strempty(prefix);
 
         fprintf(f,
                 "%s\t%s: %s%s%s %s\n",
@@ -612,6 +672,7 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
         [CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
         [CONDITION_HOST] = "ConditionHost",
         [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
+        [CONDITION_KERNEL_VERSION] = "ConditionKernelVersion",
         [CONDITION_SECURITY] = "ConditionSecurity",
         [CONDITION_CAPABILITY] = "ConditionCapability",
         [CONDITION_AC_POWER] = "ConditionACPower",
@@ -639,6 +700,7 @@ static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
         [CONDITION_VIRTUALIZATION] = "AssertVirtualization",
         [CONDITION_HOST] = "AssertHost",
         [CONDITION_KERNEL_COMMAND_LINE] = "AssertKernelCommandLine",
+        [CONDITION_KERNEL_VERSION] = "AssertKernelVersion",
         [CONDITION_SECURITY] = "AssertSecurity",
         [CONDITION_CAPABILITY] = "AssertCapability",
         [CONDITION_AC_POWER] = "AssertACPower",