]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
systemd-analyze: support discrete images for 'verify' verb
authorMaanya Goenka <t-magoenka@microsoft.com>
Wed, 30 Jun 2021 17:02:51 +0000 (10:02 -0700)
committerMaanya Goenka <t-magoenka@microsoft.com>
Tue, 10 Aug 2021 09:41:12 +0000 (02:41 -0700)
Adding --image parameter for verify verb using the dissect image functionality

-----------------------------------------------------------------------------------
Example Run:

I created a unit service file testrun.service with an invalid key-value pairing
(foo = bar) and a squashfs image run.raw to test the code.

maanya-goenka@debian:~/systemd (img-support)$ cat <<EOF>img/usr/lib/systemd/system/testrun.service
> [Unit]
> foo = bar
>
> [Service]
> ExecStart = /opt/script0.sh
> EOF

maanya-goenka@debian:~/systemd (img-support)$ mksquashfs img/ run.raw
Parallel mksquashfs: Using 4 processors
Creating 4.0 filesystem on run.raw, block size 131072.
[==============================================================================================================================|] 6/6 100%

Exportable Squashfs 4.0 filesystem, gzip compressed, data block size 131072
        compressed data, compressed metadata, compressed fragments, compressed xattrs
        duplicates are removed
Filesystem size 0.60 Kbytes (0.00 Mbytes)
        52.32% of uncompressed filesystem size (1.14 Kbytes)
Inode table size 166 bytes (0.16 Kbytes)
        43.01% of uncompressed inode table size (386 bytes)
Directory table size 153 bytes (0.15 Kbytes)
        58.40% of uncompressed directory table size (262 bytes)
Number of duplicate files found 1
Number of inodes 12
Number of files 6
Number of fragments 1
Number of symbolic links  0
Number of device nodes 0
Number of fifo nodes 0
Number of socket nodes 0
Number of directories 6
Number of ids (unique uids + gids) 1
Number of uids 1
        maanya-goenka (1000)
Number of gids 1
        maanya-goenka (1000)
maanya-goenka@debian:~/systemd (img-support)$ sudo build/systemd-analyze verify --image=run.raw testrun.service
/tmp/.#systemd-analyzec71c7297a936b91c/usr/lib/systemd/system/testrun.service:2: Unknown key name 'foo' in section 'Unit', ignoring.
testrun.service: Failed to create testrun.service/start: Unit sysinit.target not found.

The 'Unit sysinit.target not found' error that we see here is due to recursive dependency searching during
unit loading and has been addressed in a different PR:
systemd-analyze: add option to return an error value when unit verification fails #20233

man/systemd-analyze.xml
shell-completion/bash/systemd-analyze
shell-completion/zsh/_systemd-analyze
src/analyze/analyze.c

index 21e2e928cf8b69cbae9612e61a39e9098e2cc5df..dc93ac4e72e6fabcd4deebc4e9dd366928035c7a 100644 (file)
@@ -751,6 +751,13 @@ Service b@0.service not loaded, b.socket cannot be started.
         operate on files underneath the specified root path <replaceable>PATH</replaceable>.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--image=<replaceable>PATH</replaceable></option></term>
+
+        <listitem><para>With <command>cat-files</command> and <command>verify</command>,
+        operate on files inside the specified image path <replaceable>PATH</replaceable>.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--iterations=<replaceable>NUMBER</replaceable></option></term>
 
index e0a9ef5d15a162d94b3744085a4ac70a7b6e5d22..872518add0d3f6f72f94fbc70bad887ec22bfcc1 100644 (file)
@@ -125,7 +125,7 @@ _systemd_analyze() {
 
     elif __contains_word "$verb" ${VERBS[VERIFY]}; then
         if [[ $cur = -* ]]; then
-            comps='--help --version --system --user --global --man=no --generators=yes --root'
+            comps='--help --version --system --user --global --man=no --generators=yes --root --image'
         else
             comps=$( compgen -A file -- "$cur" )
             compopt -o filenames
index 921b6cb27d9b6e668869811175304b2e2459659e..88a09d84b9d5f2d2473647d554ae5e145c0db382 100644 (file)
@@ -88,6 +88,7 @@ _arguments \
     '--user[Operate on user systemd instance]' \
     '--global[Show global user instance config]' \
     '--root=[Add support for root argument]:PATH' \
+    '--image=[Add support for discrete images]:PATH' \
     '--no-pager[Do not pipe output into a pager]' \
     '--man=[Do (not) check for existence of man pages]:boolean:(1 0)' \
     '--order[When generating graph for dot, show only order]' \
index f5ce2c3ad3012c2fa61f7c8f149ae923eab3b14b..8d637ff8de9e44be9f1a9c98b178bf634510372b 100644 (file)
@@ -34,6 +34,7 @@
 #include "locale-util.h"
 #include "log.h"
 #include "main-func.h"
+#include "mount-util.h"
 #include "nulstr-util.h"
 #include "pager.h"
 #include "parse-argument.h"
@@ -87,12 +88,14 @@ static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
 static bool arg_man = true;
 static bool arg_generators = false;
 static char *arg_root = NULL;
+static char *arg_image = NULL;
 static unsigned arg_iterations = 1;
 static usec_t arg_base_time = USEC_INFINITY;
 
 STATIC_DESTRUCTOR_REGISTER(arg_dot_from_patterns, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_dot_to_patterns, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
 
 typedef struct BootTimes {
         usec_t firmware_time;
@@ -2232,6 +2235,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_ORDER,
                 ARG_REQUIRE,
                 ARG_ROOT,
+                ARG_IMAGE,
                 ARG_SYSTEM,
                 ARG_USER,
                 ARG_GLOBAL,
@@ -2251,6 +2255,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "order",        no_argument,       NULL, ARG_ORDER            },
                 { "require",      no_argument,       NULL, ARG_REQUIRE          },
                 { "root",         required_argument, NULL, ARG_ROOT             },
+                { "image",        required_argument, NULL, ARG_IMAGE            },
                 { "system",       no_argument,       NULL, ARG_SYSTEM           },
                 { "user",         no_argument,       NULL, ARG_USER             },
                 { "global",       no_argument,       NULL, ARG_GLOBAL           },
@@ -2287,6 +2292,12 @@ static int parse_argv(int argc, char *argv[]) {
                                 return r;
                         break;
 
+                case ARG_IMAGE:
+                        r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
+                        if (r < 0)
+                                return r;
+                        break;
+
                 case ARG_SYSTEM:
                         arg_scope = UNIT_FILE_SYSTEM;
                         break;
@@ -2381,14 +2392,21 @@ static int parse_argv(int argc, char *argv[]) {
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "Option --user is not supported for cat-config right now.");
 
-        if (arg_root && !STRPTR_IN_SET(argv[optind], "cat-config", "verify"))
+        if ((arg_root || arg_image) && !STRPTR_IN_SET(argv[optind], "cat-config", "verify"))
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "Option --root is only supported for cat-config and verify right now.");
+                                       "Options --root= and --image= are only supported for cat-config and verify right now.");
+
+        /* Having both an image and a root is not supported by the code */
+        if (arg_root && arg_image)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported.");
 
         return 1; /* work to do */
 }
 
 static int run(int argc, char *argv[]) {
+        _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
+        _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
+        _cleanup_(umount_and_rmdir_and_freep) char *unlink_dir = NULL;
 
         static const Verb verbs[] = {
                 { "help",              VERB_ANY, VERB_ANY, 0,            help                   },
@@ -2432,6 +2450,26 @@ static int run(int argc, char *argv[]) {
         if (r <= 0)
                 return r;
 
+        /* Open up and mount the image */
+        if (arg_image) {
+                assert(!arg_root);
+
+                r = mount_image_privately_interactively(
+                                arg_image,
+                                DISSECT_IMAGE_GENERIC_ROOT |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
+                                DISSECT_IMAGE_READ_ONLY,
+                                &unlink_dir,
+                                &loop_device,
+                                &decrypted_image);
+                if (r < 0)
+                        return r;
+
+                arg_root = strdup(unlink_dir);
+                if (!arg_root)
+                        return log_oom();
+        }
+
         return dispatch_verb(argc, argv, verbs, NULL);
 }