]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect: add new --validate command
authorLennart Poettering <lennart@poettering.net>
Fri, 2 Dec 2022 14:00:44 +0000 (15:00 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 5 Apr 2023 18:49:06 +0000 (20:49 +0200)
This allows unprivileged validation of DDIs. Only superficial structure,
i.e. not mounting or so. This becomes particularly handy in the
integration tests, and to validate image policies.

man/systemd-dissect.xml
src/dissect/dissect.c

index 06c57a22ecdbd52ee6be31460be94682daa9bfeb..f388cde3c6522543cd22e954e692cf0da83aa836 100644 (file)
         on.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--validate</option></term>
+
+        <listitem><para>Validates the partition arrangement of a disk image (DDI), and ensures it matches the
+        image policy specified via <option>--image-policy=</option>, if one is specified. This parses the
+        partition table and probes the file systems in the image, but does not attempt to mount them (nor to
+        set up disk encryption/authentication via LUKS/Verity). It does this taking the configured image
+        dissection policy into account. Since this operation does not mount file systems, this command –
+        unlike all other commands implemented by this tool – requires no privileges other than the ability to
+        access the specified file. Prints "OK" and returns zero if the image appears to be in order and
+        matches the specified image dissection policy. Otherwise prints an error message and returns
+        non-zero.</para></listitem>
+      </varlistentry>
+
       <xi:include href="standard-options.xml" xpointer="help" />
       <xi:include href="standard-options.xml" xpointer="version" />
     </variablelist>
index b3f20e193e5ffdfe1c952e221ed81fb57d9ac8ac..f89a9dff2040cba5bcf1232864a9112c86bf6caa 100644 (file)
@@ -61,6 +61,7 @@ static enum {
         ACTION_COPY_FROM,
         ACTION_COPY_TO,
         ACTION_DISCOVER,
+        ACTION_VALIDATE,
 } arg_action = ACTION_DISSECT;
 static char *arg_image = NULL;
 static char *arg_path = NULL;
@@ -148,6 +149,7 @@ static int help(void) {
                "  -x --copy-from          Copy files from image to host\n"
                "  -a --copy-to            Copy files from host to image\n"
                "     --discover           Discover DDIs in well known directories\n"
+               "     --validate           Validate image and image policy\n"
                "\nSee the %2$s for details.\n",
                program_invocation_short_name,
                link,
@@ -225,6 +227,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_DETACH,
                 ARG_LOOP_REF,
                 ARG_IMAGE_POLICY,
+                ARG_VALIDATE,
         };
 
         static const struct option options[] = {
@@ -255,6 +258,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "discover",      no_argument,       NULL, ARG_DISCOVER      },
                 { "loop-ref",      required_argument, NULL, ARG_LOOP_REF      },
                 { "image-policy",  required_argument, NULL, ARG_IMAGE_POLICY  },
+                { "validate",      no_argument,       NULL, ARG_VALIDATE      },
                 {}
         };
 
@@ -474,6 +478,10 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
                 }
 
+                case ARG_VALIDATE:
+                        arg_action = ACTION_VALIDATE;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -610,7 +618,19 @@ static int parse_argv(int argc, char *argv[]) {
                 if (optind != argc)
                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                "Expected no argument.");
+                break;
+
+        case ACTION_VALIDATE:
+                if (optind + 1 != argc)
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "Expected an image file path as only argument.");
 
+                r = parse_path_argument(argv[optind], /* suppress_root= */ false, &arg_image);
+                if (r < 0)
+                        return r;
+
+                arg_flags |= DISSECT_IMAGE_READ_ONLY;
+                arg_flags &= ~(DISSECT_IMAGE_PIN_PARTITION_DEVICES|DISSECT_IMAGE_ADD_PARTITION_DEVICES);
                 break;
 
         default:
@@ -1706,6 +1726,31 @@ static int action_detach(const char *path) {
         return 0;
 }
 
+static int action_validate(void) {
+        int r;
+
+        r = dissect_image_file_and_warn(
+                        arg_image,
+                        &arg_verity_settings,
+                        NULL,
+                        arg_image_policy,
+                        arg_flags,
+                        NULL);
+        if (r < 0)
+                return r;
+
+        if (isatty(STDOUT_FILENO) && emoji_enabled())
+                printf("%s ", special_glyph(SPECIAL_GLYPH_SPARKLES));
+
+        printf("%sOK%s", ansi_highlight_green(), ansi_normal());
+
+        if (isatty(STDOUT_FILENO) && emoji_enabled())
+                printf(" %s", special_glyph(SPECIAL_GLYPH_SPARKLES));
+
+        putc('\n', stdout);
+        return 0;
+}
+
 static int run(int argc, char *argv[]) {
         _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
         _cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
@@ -1748,6 +1793,9 @@ static int run(int argc, char *argv[]) {
                                                                 * available we turn off partition table
                                                                 * support */
 
+        if (arg_action == ACTION_VALIDATE)
+                return action_validate();
+
         open_flags = FLAGS_SET(arg_flags, DISSECT_IMAGE_DEVICE_READ_ONLY) ? O_RDONLY : O_RDWR;
         loop_flags = FLAGS_SET(arg_flags, DISSECT_IMAGE_NO_PARTITION_TABLE) ? 0 : LO_FLAGS_PARTSCAN;