]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
analyze: add 'image-policy' tool for analyzing image dissection policies
authorLennart Poettering <lennart@poettering.net>
Tue, 6 Dec 2022 20:15:06 +0000 (21:15 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 5 Apr 2023 18:51:31 +0000 (20:51 +0200)
src/analyze/analyze-image-policy.c [new file with mode: 0644]
src/analyze/analyze-image-policy.h [new file with mode: 0644]
src/analyze/analyze.c
src/analyze/meson.build
test/units/testsuite-65.sh

diff --git a/src/analyze/analyze-image-policy.c b/src/analyze/analyze-image-policy.c
new file mode 100644 (file)
index 0000000..e670fe5
--- /dev/null
@@ -0,0 +1,152 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "analyze-image-policy.h"
+#include "analyze.h"
+#include "format-table.h"
+#include "terminal-util.h"
+
+static int table_add_designator_line(Table *table, PartitionDesignator d, PartitionPolicyFlags f) {
+        _cleanup_free_ char *q = NULL;
+        const char *color;
+        int r;
+
+        assert(table);
+        assert(f >= 0);
+
+        if (partition_policy_flags_to_string(f & _PARTITION_POLICY_USE_MASK, /* simplify= */ true, &q) < 0)
+                return log_oom();
+
+        color = (f & _PARTITION_POLICY_USE_MASK) == PARTITION_POLICY_IGNORE ? ansi_grey() :
+                ((f & (PARTITION_POLICY_UNPROTECTED|PARTITION_POLICY_ENCRYPTED|PARTITION_POLICY_VERITY|PARTITION_POLICY_SIGNED|PARTITION_POLICY_ABSENT)) ==
+                   (PARTITION_POLICY_UNPROTECTED|PARTITION_POLICY_ENCRYPTED|PARTITION_POLICY_VERITY|PARTITION_POLICY_SIGNED|PARTITION_POLICY_ABSENT)) ? ansi_highlight_yellow() :
+                (f & _PARTITION_POLICY_USE_MASK) == PARTITION_POLICY_ABSENT ? ansi_highlight_red() :
+                !(f & PARTITION_POLICY_UNPROTECTED) ? ansi_highlight_green() : NULL;
+
+        if (d < 0)
+                r = table_add_many(table,
+                                   TABLE_STRING, "default",
+                                   TABLE_SET_COLOR, ansi_highlight_green(),
+                                   TABLE_STRING, q,
+                                   TABLE_SET_COLOR, color);
+        else
+                r = table_add_many(table,
+                                   TABLE_STRING, partition_designator_to_string(d),
+                                   TABLE_SET_COLOR, ansi_normal(),
+                                   TABLE_STRING, q,
+                                   TABLE_SET_COLOR, color);
+        if (r < 0)
+                return table_log_add_error(r);
+
+        switch (f & _PARTITION_POLICY_READ_ONLY_MASK) {
+
+        case PARTITION_POLICY_READ_ONLY_ON:
+                r = table_add_many(table, TABLE_BOOLEAN, true);
+                break;
+
+        case PARTITION_POLICY_READ_ONLY_OFF:
+                r = table_add_many(table, TABLE_BOOLEAN, false);
+                break;
+
+        default:
+                r = table_add_many(table, TABLE_EMPTY);
+                break;
+        }
+        if (r < 0)
+                return table_log_add_error(r);
+
+        switch (f & _PARTITION_POLICY_GROWFS_MASK) {
+
+        case PARTITION_POLICY_GROWFS_ON:
+                r = table_add_many(table, TABLE_BOOLEAN, true);
+                break;
+
+        case PARTITION_POLICY_GROWFS_OFF:
+                r = table_add_many(table, TABLE_BOOLEAN, false);
+                break;
+
+        default:
+                r = table_add_many(table, TABLE_EMPTY);
+                break;
+        }
+
+        if (r < 0)
+                return table_log_add_error(r);
+
+        return 0;
+}
+
+int verb_image_policy(int argc, char *argv[], void *userdata) {
+        int r;
+
+        for (int i = 1; i < argc; i++) {
+                _cleanup_(table_unrefp) Table *table = NULL;
+                _cleanup_(image_policy_freep) ImagePolicy *pbuf = NULL;
+                _cleanup_free_ char *as_string = NULL, *as_string_simplified = NULL;
+                const ImagePolicy *p;
+
+                /* NB: The magic '@' strings are not officially documented for now, since we might change
+                 * around defaults (and in particular where precisely to reuse policy). We should document
+                 * them once the dust has settled a bit. For now it's just useful for debugging and
+                 * introspect our own defaults without guaranteeing API safety. */
+                if (streq(argv[i], "@sysext"))
+                        p = &image_policy_sysext;
+                else if (streq(argv[i], "@container"))
+                        p = &image_policy_container;
+                else if (streq(argv[i], "@service"))
+                        p = &image_policy_service;
+                else if (streq(argv[i], "@host"))
+                        p = &image_policy_host;
+                else {
+                        r = image_policy_from_string(argv[i], &pbuf);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse image policy '%s': %m", argv[i]);
+
+                        p = pbuf;
+                }
+
+                r = image_policy_to_string(p, /* simplify= */ false, &as_string);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to format policy '%s' as string: %m", argv[i]);
+
+                r = image_policy_to_string(p, /* simplify= */ true, &as_string_simplified);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to format policy '%s' as string: %m", argv[i]);
+
+                pager_open(arg_pager_flags);
+
+                if (streq(as_string, as_string_simplified))
+                        printf("Analyzing policy: %s%s%s\n", ansi_highlight_magenta_underline(), as_string, ansi_normal());
+                else
+                        printf("Analyzing policy: %s%s%s\n"
+                               "       Long form: %s%s%s\n",
+                               ansi_highlight(), as_string_simplified, ansi_normal(),
+                               ansi_grey(), as_string, ansi_normal());
+
+                table = table_new("partition", "mode", "read-only", "growfs");
+                if (!table)
+                        return log_oom();
+
+                (void) table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
+
+                for (PartitionDesignator d = 0; d < _PARTITION_DESIGNATOR_MAX; d++) {
+                        PartitionPolicyFlags f = image_policy_get_exhaustively(p, d);
+                        assert(f >= 0);
+
+                        r = table_add_designator_line(table, d, f);
+                        if (r < 0)
+                                return r;
+                }
+
+                r = table_add_designator_line(table, _PARTITION_DESIGNATOR_INVALID, image_policy_default(p));
+                if (r < 0)
+                        return r;
+
+                putc('\n', stdout);
+
+                r = table_print(table, NULL);
+                if (r < 0)
+                        return r;
+        }
+
+        return EXIT_SUCCESS;
+}
diff --git a/src/analyze/analyze-image-policy.h b/src/analyze/analyze-image-policy.h
new file mode 100644 (file)
index 0000000..fa08447
--- /dev/null
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+int verb_image_policy(int argc, char *argv[], void *userdata);
index 8bc533b20d860434bf181c55e417e1a24b8fe286..ddc71b98b073ad9d6ac472f2d97d7ed914e84150 100644 (file)
@@ -39,6 +39,7 @@
 #include "analyze-unit-files.h"
 #include "analyze-unit-paths.h"
 #include "analyze-verify.h"
+#include "analyze-image-policy.h"
 #include "build.h"
 #include "bus-error.h"
 #include "bus-locator.h"
@@ -640,6 +641,7 @@ static int run(int argc, char *argv[]) {
                 { "inspect-elf",       2,        VERB_ANY, 0,            verb_elf_inspection    },
                 { "malloc",            VERB_ANY, VERB_ANY, 0,            verb_malloc            },
                 { "fdstore",           2,        VERB_ANY, 0,            verb_fdstore           },
+                { "image-policy",      2,        2,        0,            verb_image_policy      },
                 {}
         };
 
index 695089a0beda7da92d29915db365807fd7e62f0e..c50c35f09f6e0907df5e40f4e114753ad10baa0c 100644 (file)
@@ -13,6 +13,7 @@ systemd_analyze_sources = files(
         'analyze-exit-status.c',
         'analyze-fdstore.c',
         'analyze-filesystems.c',
+        'analyze-image-policy.c',
         'analyze-inspect-elf.c',
         'analyze-log-control.c',
         'analyze-malloc.c',
index edaf667107156686c7036b4422224f2793b44ed0..f28edf275e5a20986e7647a5d428d2f8b61e5f37 100755 (executable)
@@ -816,6 +816,18 @@ name=$(echo "$output" | awk '{ print $4 }')
 check deny yes /run/systemd/transient/"$name"
 check deny no "$name"
 
+# Let's also test the "image-policy" verb
+
+systemd-analyze image-policy '*' 2>&1 | grep -q -F "Long form: =verity+signed+encrypted+unprotected+unused+absent"
+systemd-analyze image-policy '-' 2>&1 | grep -q -F "Long form: =unused+absent"
+systemd-analyze image-policy 'home=encrypted:usr=verity' 2>&1 | grep -q -F "Long form: usr=verity:home=encrypted:=unused+absent"
+systemd-analyze image-policy 'home=encrypted:usr=verity' 2>&1 | grep -q -e '^home \+encrypted \+'
+systemd-analyze image-policy 'home=encrypted:usr=verity' 2>&1 | grep -q -e '^usr \+verity \+'
+systemd-analyze image-policy 'home=encrypted:usr=verity' 2>&1 | grep -q -e '^root \+ignore \+'
+systemd-analyze image-policy 'home=encrypted:usr=verity' 2>&1 | grep -q -e '^usr-verity \+unprotected \+'
+
+(! systemd-analyze image-policy 'doedel' )
+
 systemd-analyze log-level info
 
 echo OK >/testok