]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tree-wide: hook up image dissection policy logic everywhere
authorLennart Poettering <lennart@poettering.net>
Wed, 30 Nov 2022 17:43:18 +0000 (18:43 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 5 Apr 2023 18:45:30 +0000 (20:45 +0200)
42 files changed:
man/org.freedesktop.systemd1.xml
src/analyze/analyze.c
src/analyze/analyze.h
src/boot/bootctl.c
src/boot/bootctl.h
src/core/dbus-execute.c
src/core/dbus-service.c
src/core/execute.c
src/core/execute.h
src/core/load-fragment-gperf.gperf.in
src/core/load-fragment.c
src/core/load-fragment.h
src/core/namespace.c
src/core/namespace.h
src/coredump/coredumpctl.c
src/dissect/dissect.c
src/firstboot/firstboot.c
src/gpt-auto-generator/gpt-auto-generator.c
src/journal/journalctl.c
src/machine-id-setup/machine-id-setup-main.c
src/machine/image-dbus.c
src/nspawn/nspawn.c
src/partition/repart.c
src/portable/portable.c
src/portable/portable.h
src/portable/portabled-image-bus.c
src/shared/bus-unit-util.c
src/shared/discover-image.c
src/shared/discover-image.h
src/shared/dissect-image.c
src/shared/dissect-image.h
src/shared/mount-util.c
src/shared/mount-util.h
src/sysext/sysext.c
src/systemctl/systemctl.c
src/systemctl/systemctl.h
src/sysupdate/sysupdate.c
src/sysusers/sysusers.c
src/test/test-loop-block.c
src/test/test-namespace.c
src/test/test-ns.c
src/tmpfiles/tmpfiles.c

index 50680e6b37af8b8a8324084e087c44bfc001295c..05c8b3770e2bede96bf962112b085c7b3ceb3c3a 100644 (file)
@@ -3167,6 +3167,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s IPCNamespacePath = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s RootImagePolicy = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s MountImagePolicy = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s ExtensionImagePolicy = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s KillMode = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly i KillSignal = ...;
@@ -3724,6 +3730,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <!--property IPCNamespacePath is not documented!-->
 
+    <!--property RootImagePolicy is not documented!-->
+
+    <!--property MountImagePolicy is not documented!-->
+
+    <!--property ExtensionImagePolicy is not documented!-->
+
     <!--property KillMode is not documented!-->
 
     <!--property KillSignal is not documented!-->
@@ -4380,6 +4392,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <variablelist class="dbus-property" generated="True" extra-ref="IPCNamespacePath"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="RootImagePolicy"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="MountImagePolicy"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="ExtensionImagePolicy"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>
@@ -5147,6 +5165,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s IPCNamespacePath = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s RootImagePolicy = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s MountImagePolicy = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s ExtensionImagePolicy = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s KillMode = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly i KillSignal = ...;
@@ -5718,6 +5742,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
 
     <!--property IPCNamespacePath is not documented!-->
 
+    <!--property RootImagePolicy is not documented!-->
+
+    <!--property MountImagePolicy is not documented!-->
+
+    <!--property ExtensionImagePolicy is not documented!-->
+
     <!--property KillMode is not documented!-->
 
     <!--property KillSignal is not documented!-->
@@ -6356,6 +6386,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
 
     <variablelist class="dbus-property" generated="True" extra-ref="IPCNamespacePath"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="RootImagePolicy"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="MountImagePolicy"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="ExtensionImagePolicy"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>
@@ -7002,6 +7038,12 @@ node /org/freedesktop/systemd1/unit/home_2emount {
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s IPCNamespacePath = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s RootImagePolicy = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s MountImagePolicy = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s ExtensionImagePolicy = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s KillMode = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly i KillSignal = ...;
@@ -7501,6 +7543,12 @@ node /org/freedesktop/systemd1/unit/home_2emount {
 
     <!--property IPCNamespacePath is not documented!-->
 
+    <!--property RootImagePolicy is not documented!-->
+
+    <!--property MountImagePolicy is not documented!-->
+
+    <!--property ExtensionImagePolicy is not documented!-->
+
     <!--property KillMode is not documented!-->
 
     <!--property KillSignal is not documented!-->
@@ -8057,6 +8105,12 @@ node /org/freedesktop/systemd1/unit/home_2emount {
 
     <variablelist class="dbus-property" generated="True" extra-ref="IPCNamespacePath"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="RootImagePolicy"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="MountImagePolicy"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="ExtensionImagePolicy"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>
@@ -8830,6 +8884,12 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s IPCNamespacePath = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s RootImagePolicy = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s MountImagePolicy = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s ExtensionImagePolicy = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s KillMode = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly i KillSignal = ...;
@@ -9315,6 +9375,12 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
 
     <!--property IPCNamespacePath is not documented!-->
 
+    <!--property RootImagePolicy is not documented!-->
+
+    <!--property MountImagePolicy is not documented!-->
+
+    <!--property ExtensionImagePolicy is not documented!-->
+
     <!--property KillMode is not documented!-->
 
     <!--property KillSignal is not documented!-->
@@ -9857,6 +9923,12 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
 
     <variablelist class="dbus-property" generated="True" extra-ref="IPCNamespacePath"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="RootImagePolicy"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="MountImagePolicy"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="ExtensionImagePolicy"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>
index 0246da4b45dae0d2602140f223f9b893b54ca37d..8bc533b20d860434bf181c55e417e1a24b8fe286 100644 (file)
@@ -109,6 +109,7 @@ bool arg_quiet = false;
 char *arg_profile = NULL;
 bool arg_legend = true;
 bool arg_table = false;
+ImagePolicy *arg_image_policy = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_dot_from_patterns, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_dot_to_patterns, strv_freep);
@@ -117,6 +118,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_security_policy, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_unit, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_profile, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
 
 int acquire_bus(sd_bus **bus, bool *use_full_bus) {
         int r;
@@ -268,6 +270,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "  -q --quiet                 Do not emit hints\n"
                "     --root=PATH             Operate on an alternate filesystem root\n"
                "     --image=PATH            Operate on disk image as filesystem root\n"
+               "     --image-policy=POLICY   Specify disk image dissection policy\n"
                "\nSee the %s for details.\n",
                program_invocation_short_name,
                ansi_highlight(),
@@ -307,6 +310,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_PROFILE,
                 ARG_TABLE,
                 ARG_NO_LEGEND,
+                ARG_IMAGE_POLICY,
         };
 
         static const struct option options[] = {
@@ -339,6 +343,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "profile",          required_argument, NULL, ARG_PROFILE          },
                 { "table",            optional_argument, NULL, ARG_TABLE            },
                 { "no-legend",        optional_argument, NULL, ARG_NO_LEGEND        },
+                { "image-policy",     required_argument, NULL, ARG_IMAGE_POLICY     },
                 {}
         };
 
@@ -522,6 +527,18 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_legend = false;
                         break;
 
+                case ARG_IMAGE_POLICY: {
+                        _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
+
+                        r = image_policy_from_string(optarg, &p);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse image policy: %s", optarg);
+
+                        image_policy_free(arg_image_policy);
+                        arg_image_policy = TAKE_PTR(p);
+                        break;
+                }
+
                 case '?':
                         return -EINVAL;
 
@@ -643,6 +660,7 @@ static int run(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
+                                arg_image_policy,
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_RELAX_VAR_CHECK |
                                 DISSECT_IMAGE_READ_ONLY,
index 2f623e3201256b99fa29fc85d1a1430ea18760f8..84575cd9a9d258f4cf2de7a66b4d2fd5396dd53b 100644 (file)
@@ -38,6 +38,7 @@ extern bool arg_quiet;
 extern char *arg_profile;
 extern bool arg_legend;
 extern bool arg_table;
+extern ImagePolicy *arg_image_policy;
 
 int acquire_bus(sd_bus **bus, bool *use_full_bus);
 
index 82c7e498ba608e49b9bc883cd6aa1d4551b19dc6..b9d034d55033ede10ed9ca67a200f1a06365a42e 100644 (file)
@@ -52,6 +52,7 @@ char *arg_image = NULL;
 InstallSource arg_install_source = ARG_INSTALL_SOURCE_AUTO;
 char *arg_efi_boot_option_description = NULL;
 bool arg_dry_run = false;
+ImagePolicy *arg_image_policy = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep);
@@ -60,6 +61,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_entry_token, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_efi_boot_option_description, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
 
 int acquire_esp(
                 bool unprivileged_mode,
@@ -168,6 +170,8 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --boot-path=PATH  Path to the $BOOT partition\n"
                "     --root=PATH       Operate on an alternate filesystem root\n"
                "     --image=PATH      Operate on disk image as filesystem root\n"
+               "     --image-policy=POLICY\n"
+               "                       Specify disk image dissection policy\n"
                "     --install-source=auto|image|host\n"
                "                       Where to pick files when using --root=/--image=\n"
                "  -p --print-esp-path  Print path to the EFI System Partition mount point\n"
@@ -218,6 +222,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_ARCH_ALL,
                 ARG_EFI_BOOT_OPTION_DESCRIPTION,
                 ARG_DRY_RUN,
+                ARG_IMAGE_POLICY,
         };
 
         static const struct option options[] = {
@@ -244,6 +249,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "all-architectures",           no_argument,       NULL, ARG_ARCH_ALL                    },
                 { "efi-boot-option-description", required_argument, NULL, ARG_EFI_BOOT_OPTION_DESCRIPTION },
                 { "dry-run",                     no_argument,       NULL, ARG_DRY_RUN                     },
+                { "image-policy",                required_argument, NULL, ARG_IMAGE_POLICY                },
                 {}
         };
 
@@ -376,6 +382,18 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_dry_run = true;
                         break;
 
+                case ARG_IMAGE_POLICY: {
+                        _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
+
+                        r = image_policy_from_string(optarg, &p);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse image policy: %s", optarg);
+
+                        image_policy_free(arg_image_policy);
+                        arg_image_policy = TAKE_PTR(p);
+                        break;
+                }
+
                 case '?':
                         return -EINVAL;
 
@@ -478,6 +496,7 @@ static int run(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
+                                arg_image_policy,
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_RELAX_VAR_CHECK,
                                 &unlink_dir,
index c87d43694f809b1273de36a9a1309e25bbf02331..dd98b959c2964869e49bdc1b399cf0fd78eca06c 100644 (file)
@@ -4,6 +4,7 @@
 #include "sd-id128.h"
 
 #include "boot-entry.h"
+#include "image-policy.h"
 #include "json.h"
 #include "pager.h"
 
@@ -34,6 +35,7 @@ extern char *arg_image;
 extern InstallSource arg_install_source;
 extern char *arg_efi_boot_option_description;
 extern bool arg_dry_run;
+extern ImagePolicy *arg_image_policy;
 
 static inline const char *arg_dollar_boot_path(void) {
         /* $BOOT shall be the XBOOTLDR partition if it exists, and otherwise the ESP */
index d5ef796e522082fa7264b96d1c1bf0e87fe5e284..d77842bdabd480f1bc8cd6dcafa8f176e9edc636 100644 (file)
@@ -1156,6 +1156,30 @@ static int bus_property_get_exec_dir_symlink(
         return sd_bus_message_close_container(reply);
 }
 
+static int property_get_image_policy(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        ImagePolicy **pp = ASSERT_PTR(userdata);
+        _cleanup_free_ char *s = NULL;
+        int r;
+
+        assert(bus);
+        assert(property);
+        assert(reply);
+
+        r = image_policy_to_string(*pp ?: &image_policy_service, /* simplify= */ true, &s);
+        if (r < 0)
+                return r;
+
+        return sd_bus_message_append(reply, "s", s);
+}
+
 const sd_bus_vtable bus_exec_vtable[] = {
         SD_BUS_VTABLE_START(0),
         SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -1324,6 +1348,9 @@ const sd_bus_vtable bus_exec_vtable[] = {
         SD_BUS_PROPERTY("ProtectHostname", "b", bus_property_get_bool, offsetof(ExecContext, protect_hostname), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("NetworkNamespacePath", "s", NULL, offsetof(ExecContext, network_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("IPCNamespacePath", "s", NULL, offsetof(ExecContext, ipc_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("RootImagePolicy", "s", property_get_image_policy, offsetof(ExecContext, root_image_policy), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("MountImagePolicy", "s", property_get_image_policy, offsetof(ExecContext, mount_image_policy), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("ExtensionImagePolicy", "s", property_get_image_policy, offsetof(ExecContext, extension_image_policy), SD_BUS_VTABLE_PROPERTY_CONST),
 
         /* Obsolete/redundant properties: */
         SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
@@ -3900,6 +3927,40 @@ int bus_exec_context_set_transient_property(
 
                 return 1;
 
+        } else if (STR_IN_SET(name, "RootImagePolicy", "MountImagePolicy", "ExtensionImagePolicy")) {
+                _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
+                const char *s;
+
+                r = sd_bus_message_read(message, "s", &s);
+                if (r < 0)
+                        return r;
+
+                r = image_policy_from_string(s, &p);
+                if (r < 0)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse image policy string: %s", s);
+
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+                        _cleanup_free_ char *t = NULL;
+                        ImagePolicy **pp =
+                                streq(name, "RootImagePolicy")  ? &c->root_image_policy :
+                                streq(name, "MountImagePolicy") ? &c->mount_image_policy :
+                                                                  &c->extension_image_policy;
+
+                        r = image_policy_to_string(p, /* simplify= */ true, &t);
+                        if (r < 0)
+                                return r;
+
+                        image_policy_free(*pp);
+                        *pp = TAKE_PTR(p);
+
+                        unit_write_settingf(
+                                        u, flags, name,
+                                        "%s=%s",
+                                        name,
+                                        t); /* no escaping necessary */
+                }
+
+                return 1;
         }
 
         return 0;
index 0f6e3152330d07ba9624250247567312f6b92937..6041a37e5603cd4efeaa8ff9c54bc2bd53b66490 100644 (file)
@@ -197,15 +197,23 @@ static int bus_service_method_mount(sd_bus_message *message, void *userdata, sd_
 
         propagate_directory = strjoina("/run/systemd/propagate/", u->id);
         if (is_image)
-                r = mount_image_in_namespace(unit_pid,
-                                             propagate_directory,
-                                             "/run/systemd/incoming/",
-                                             src, dest, read_only, make_file_or_directory, options);
+                r = mount_image_in_namespace(
+                                unit_pid,
+                                propagate_directory,
+                                "/run/systemd/incoming/",
+                                src, dest,
+                                read_only,
+                                make_file_or_directory,
+                                options,
+                                c->mount_image_policy ?: &image_policy_service);
         else
-                r = bind_mount_in_namespace(unit_pid,
-                                            propagate_directory,
-                                            "/run/systemd/incoming/",
-                                            src, dest, read_only, make_file_or_directory);
+                r = bind_mount_in_namespace(
+                                unit_pid,
+                                propagate_directory,
+                                "/run/systemd/incoming/",
+                                src, dest,
+                                read_only,
+                                make_file_or_directory);
         if (r < 0)
                 return sd_bus_error_set_errnof(error, r, "Failed to mount %s on %s in unit's namespace: %m", src, dest);
 
index aff07e7b74427df75ba616af098b80c897d0199a..cd11683407edbfe890dfc689d12941ed0667da61 100644 (file)
@@ -3823,36 +3823,43 @@ static int apply_mount_namespace(
                         goto finalize;
                 }
 
-        r = setup_namespace(root_dir, root_image, context->root_image_options,
-                            &ns_info, read_write_paths,
-                            needs_sandboxing ? context->read_only_paths : NULL,
-                            needs_sandboxing ? context->inaccessible_paths : NULL,
-                            needs_sandboxing ? context->exec_paths : NULL,
-                            needs_sandboxing ? context->no_exec_paths : NULL,
-                            empty_directories,
-                            symlinks,
-                            bind_mounts,
-                            n_bind_mounts,
-                            context->temporary_filesystems,
-                            context->n_temporary_filesystems,
-                            context->mount_images,
-                            context->n_mount_images,
-                            tmp_dir,
-                            var_tmp_dir,
-                            creds_path,
-                            context->log_namespace,
-                            context->mount_propagation_flag,
-                            context->root_hash, context->root_hash_size, context->root_hash_path,
-                            context->root_hash_sig, context->root_hash_sig_size, context->root_hash_sig_path,
-                            context->root_verity,
-                            context->extension_images,
-                            context->n_extension_images,
-                            context->extension_directories,
-                            propagate_dir,
-                            incoming_dir,
-                            extension_dir,
-                            root_dir || root_image ? params->notify_socket : NULL,
-                            error_path);
+        r = setup_namespace(
+                        root_dir,
+                        root_image,
+                        context->root_image_options,
+                        context->root_image_policy ?: &image_policy_service,
+                        &ns_info,
+                        read_write_paths,
+                        needs_sandboxing ? context->read_only_paths : NULL,
+                        needs_sandboxing ? context->inaccessible_paths : NULL,
+                        needs_sandboxing ? context->exec_paths : NULL,
+                        needs_sandboxing ? context->no_exec_paths : NULL,
+                        empty_directories,
+                        symlinks,
+                        bind_mounts,
+                        n_bind_mounts,
+                        context->temporary_filesystems,
+                        context->n_temporary_filesystems,
+                        context->mount_images,
+                        context->n_mount_images,
+                        context->mount_image_policy ?: &image_policy_service,
+                        tmp_dir,
+                        var_tmp_dir,
+                        creds_path,
+                        context->log_namespace,
+                        context->mount_propagation_flag,
+                        context->root_hash, context->root_hash_size, context->root_hash_path,
+                        context->root_hash_sig, context->root_hash_sig_size, context->root_hash_sig_path,
+                        context->root_verity,
+                        context->extension_images,
+                        context->n_extension_images,
+                        context->extension_image_policy ?: &image_policy_sysext,
+                        context->extension_directories,
+                        propagate_dir,
+                        incoming_dir,
+                        extension_dir,
+                        root_dir || root_image ? params->notify_socket : NULL,
+                        error_path);
 
         /* If we couldn't set up the namespace this is probably due to a missing capability. setup_namespace() reports
          * that with a special, recognizable error ENOANO. In this case, silently proceed, but only if exclusively
@@ -5789,6 +5796,10 @@ void exec_context_done(ExecContext *c) {
 
         c->load_credentials = hashmap_free(c->load_credentials);
         c->set_credentials = hashmap_free(c->set_credentials);
+
+        c->root_image_policy = image_policy_free(c->root_image_policy);
+        c->mount_image_policy = image_policy_free(c->mount_image_policy);
+        c->extension_image_policy = image_policy_free(c->extension_image_policy);
 }
 
 int exec_context_destroy_runtime_directory(const ExecContext *c, const char *runtime_prefix) {
index 254a1ee2d13a5eafc14c8fde9b0d1dd323ac8455..123fc1ec604dec47ff9943aa7ab9c3394545c704 100644 (file)
@@ -359,6 +359,8 @@ struct ExecContext {
 
         Hashmap *set_credentials; /* output id â†’ ExecSetCredential */
         Hashmap *load_credentials; /* output id â†’ ExecLoadCredential */
+
+        ImagePolicy *root_image_policy, *mount_image_policy, *extension_image_policy;
 };
 
 static inline bool exec_context_restrict_namespaces_set(const ExecContext *c) {
index 50ff57a9f8d689b543fa21453c67a6fe403cd477..f35c7436550924124d038f35400612316270f0b8 100644 (file)
@@ -6,12 +6,15 @@
 {{type}}.RootDirectory,                    config_parse_unit_path_printf,               true,                               offsetof({{type}}, exec_context.root_directory)
 {{type}}.RootImage,                        config_parse_unit_path_printf,               true,                               offsetof({{type}}, exec_context.root_image)
 {{type}}.RootImageOptions,                 config_parse_root_image_options,             0,                                  offsetof({{type}}, exec_context)
+{{type}}.RootImagePolicy,                  config_parse_image_policy,                   0,                                  offsetof({{type}}, exec_context.root_image_policy)
 {{type}}.RootHash,                         config_parse_exec_root_hash,                 0,                                  offsetof({{type}}, exec_context)
 {{type}}.RootHashSignature,                config_parse_exec_root_hash_sig,             0,                                  offsetof({{type}}, exec_context)
 {{type}}.RootVerity,                       config_parse_unit_path_printf,               true,                               offsetof({{type}}, exec_context.root_verity)
 {{type}}.ExtensionDirectories,             config_parse_namespace_path_strv,            0,                                  offsetof({{type}}, exec_context.extension_directories)
 {{type}}.ExtensionImages,                  config_parse_extension_images,               0,                                  offsetof({{type}}, exec_context)
+{{type}}.ExtensionImagePolicy,             config_parse_image_policy,                   0,                                  offsetof({{type}}, exec_context.extension_image_policy)
 {{type}}.MountImages,                      config_parse_mount_images,                   0,                                  offsetof({{type}}, exec_context)
+{{type}}.MountImagePolicy,                 config_parse_image_policy,                   0,                                  offsetof({{type}}, exec_context.mount_image_policy)
 {{type}}.User,                             config_parse_user_group_compat,              0,                                  offsetof({{type}}, exec_context.user)
 {{type}}.Group,                            config_parse_user_group_compat,              0,                                  offsetof({{type}}, exec_context.group)
 {{type}}.SupplementaryGroups,              config_parse_user_group_strv_compat,         0,                                  offsetof({{type}}, exec_context.supplementary_groups)
index 533c09f72eab79eede6f4a2db551f6a9b832ef09..99d40b74908d2c390d490e0d26ee954e681268dc 100644 (file)
@@ -1705,6 +1705,45 @@ int config_parse_root_image_options(
         return 0;
 }
 
+int config_parse_image_policy(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        _cleanup_(image_policy_freep) ImagePolicy *np = NULL;
+        ImagePolicy **p = ASSERT_PTR(data);
+        int r;
+
+        assert(rvalue);
+
+        if (isempty(rvalue)) {
+                *p = image_policy_free(*p);
+                return 0;
+        }
+
+        r = image_policy_from_string(rvalue, &np);
+        if (r == -ENOTUNIQ)
+                return log_syntax(unit, LOG_ERR, filename, line, r, "Duplicate rule in image policy, refusing: %s", rvalue);
+        if (r == -EBADSLT)
+                return log_syntax(unit, LOG_ERR, filename, line, r, "Unknown partition type in image policy, refusing: %s", rvalue);
+        if (r == -EBADRQC)
+                return log_syntax(unit, LOG_ERR, filename, line, r, "Unknown partition policy flag in image policy, refusing: %s", rvalue);
+        if (r < 0)
+                return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse image policy, refusing: %s", rvalue);
+
+        image_policy_free(*p);
+        *p = TAKE_PTR(np);
+
+        return 0;
+}
+
 int config_parse_exec_root_hash(
                 const char *unit,
                 const char *filename,
index 91dc91745848f2864ec904d98cb078b453ab5a07..ab682ee23e73fe71ed27b3f9b82677312c43f112 100644 (file)
@@ -52,6 +52,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_affinity);
 CONFIG_PARSER_PROTOTYPE(config_parse_exec_mount_apivfs);
 CONFIG_PARSER_PROTOTYPE(config_parse_exec_secure_bits);
 CONFIG_PARSER_PROTOTYPE(config_parse_root_image_options);
+CONFIG_PARSER_PROTOTYPE(config_parse_image_policy);
 CONFIG_PARSER_PROTOTYPE(config_parse_exec_root_hash);
 CONFIG_PARSER_PROTOTYPE(config_parse_exec_root_hash_sig);
 CONFIG_PARSER_PROTOTYPE(config_parse_capability_set);
index 8b141a24848c74734782c85c29b6c7eee4580099..2668bca1bb1d60a3c6dc51e005ec2db52ed72872 100644 (file)
@@ -1240,7 +1240,10 @@ static int mount_mqueuefs(const MountEntry *m) {
         return 0;
 }
 
-static int mount_image(const MountEntry *m, const char *root_directory) {
+static int mount_image(
+                const MountEntry *m,
+                const char *root_directory,
+                const ImagePolicy *image_policy) {
 
         _cleanup_free_ char *host_os_release_id = NULL, *host_os_release_version_id = NULL,
                             *host_os_release_sysext_level = NULL;
@@ -1262,8 +1265,15 @@ static int mount_image(const MountEntry *m, const char *root_directory) {
         }
 
         r = verity_dissect_and_mount(
-                        /* src_fd= */ -1, mount_entry_source(m), mount_entry_path(m), m->image_options,
-                        host_os_release_id, host_os_release_version_id, host_os_release_sysext_level, NULL);
+                        /* src_fd= */ -1,
+                        mount_entry_source(m),
+                        mount_entry_path(m),
+                        m->image_options,
+                        image_policy,
+                        host_os_release_id,
+                        host_os_release_version_id,
+                        host_os_release_sysext_level,
+                        NULL);
         if (r == -ENOENT && m->ignore)
                 return 0;
         if (r == -ESTALE && host_os_release_id)
@@ -1336,6 +1346,8 @@ static int follow_symlink(
 static int apply_one_mount(
                 const char *root_directory,
                 MountEntry *m,
+                const ImagePolicy *mount_image_policy,
+                const ImagePolicy *extension_image_policy,
                 const NamespaceInfo *ns_info) {
 
         _cleanup_free_ char *inaccessible = NULL;
@@ -1505,10 +1517,10 @@ static int apply_one_mount(
                 return mount_mqueuefs(m);
 
         case MOUNT_IMAGES:
-                return mount_image(m, NULL);
+                return mount_image(m, NULL, mount_image_policy);
 
         case EXTENSION_IMAGES:
-                return mount_image(m, root_directory);
+                return mount_image(m, root_directory, extension_image_policy);
 
         case OVERLAY_MOUNT:
                 return mount_overlay(m);
@@ -1778,6 +1790,8 @@ static int create_symlinks_from_tuples(const char *root, char **strv_symlinks) {
 
 static int apply_mounts(
                 const char *root,
+                const ImagePolicy *mount_image_policy,
+                const ImagePolicy *extension_image_policy,
                 const NamespaceInfo *ns_info,
                 MountEntry *mounts,
                 size_t *n_mounts,
@@ -1832,7 +1846,7 @@ static int apply_mounts(
                                 break;
                         }
 
-                        r = apply_one_mount(root, m, ns_info);
+                        r = apply_one_mount(root, m, mount_image_policy, extension_image_policy, ns_info);
                         if (r < 0) {
                                 if (error_path && mount_entry_path(m))
                                         *error_path = strdup(mount_entry_path(m));
@@ -2011,7 +2025,8 @@ static int verity_settings_prepare(
 int setup_namespace(
                 const char* root_directory,
                 const char* root_image,
-                const MountOptions *root_image_options,
+                const MountOptions *root_image_mount_options,
+                const ImagePolicy *root_image_policy,
                 const NamespaceInfo *ns_info,
                 char** read_write_paths,
                 char** read_only_paths,
@@ -2026,6 +2041,7 @@ int setup_namespace(
                 size_t n_temporary_filesystems,
                 const MountImage *mount_images,
                 size_t n_mount_images,
+                const ImagePolicy *mount_image_policy,
                 const char* tmp_dir,
                 const char* var_tmp_dir,
                 const char *creds_path,
@@ -2040,6 +2056,7 @@ int setup_namespace(
                 const char *verity_data_path,
                 const MountImage *extension_images,
                 size_t n_extension_images,
+                const ImagePolicy *extension_image_policy,
                 char **extension_directories,
                 const char *propagate_dir,
                 const char *incoming_dir,
@@ -2113,7 +2130,8 @@ int setup_namespace(
                 r = dissect_loop_device(
                                 loop_device,
                                 &verity,
-                                root_image_options,
+                                root_image_mount_options,
+                                root_image_policy,
                                 dissect_image_flags,
                                 &dissected_image);
                 if (r < 0)
@@ -2501,7 +2519,7 @@ int setup_namespace(
                 (void) base_filesystem_create(root, UID_INVALID, GID_INVALID);
 
         /* Now make the magic happen */
-        r = apply_mounts(root, ns_info, mounts, &n_mounts, exec_dir_symlinks, error_path);
+        r = apply_mounts(root, mount_image_policy, extension_image_policy, ns_info, mounts, &n_mounts, exec_dir_symlinks, error_path);
         if (r < 0)
                 goto finish;
 
index 1cd4fdd921332509d58560221f85c3cc6ad5ae49..39b510f41d9723c87f90820d1639ea45f815daef 100644 (file)
@@ -103,6 +103,7 @@ int setup_namespace(
                 const char *root_directory,
                 const char *root_image,
                 const MountOptions *root_image_options,
+                const ImagePolicy *root_image_policy,
                 const NamespaceInfo *ns_info,
                 char **read_write_paths,
                 char **read_only_paths,
@@ -117,6 +118,7 @@ int setup_namespace(
                 size_t n_temporary_filesystems,
                 const MountImage *mount_images,
                 size_t n_mount_images,
+                const ImagePolicy *mount_image_policy,
                 const char *tmp_dir,
                 const char *var_tmp_dir,
                 const char *creds_path,
@@ -131,6 +133,7 @@ int setup_namespace(
                 const char *root_verity,
                 const MountImage *extension_images,
                 size_t n_extension_images,
+                const ImagePolicy *extension_image_policy,
                 char **extension_directories,
                 const char *propagate_dir,
                 const char *incoming_dir,
index 60da536d4eb2a01fc0e675fb324ab0e94a4d435b..076b35f0987760612c87fd4c6c4950f779f53a01 100644 (file)
@@ -64,9 +64,11 @@ static const char* arg_output = NULL;
 static bool arg_reverse = false;
 static bool arg_quiet = false;
 static bool arg_all = false;
+static ImagePolicy *arg_image_policy = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_debugger_args, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_file, strv_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
 
 static int add_match(sd_journal *j, const char *match) {
         _cleanup_free_ char *p = NULL;
@@ -198,6 +200,7 @@ static int verb_help(int argc, char **argv, void *userdata) {
                "     --all                     Look at all journal files instead of local ones\n"
                "     --root=PATH               Operate on an alternate filesystem root\n"
                "     --image=PATH              Operate on disk image as filesystem root\n"
+               "     --image-policy=POLICY     Specify disk image dissection policy\n"
                "\nSee the %2$s for details.\n",
                program_invocation_short_name,
                link,
@@ -220,29 +223,31 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_ROOT,
                 ARG_IMAGE,
                 ARG_ALL,
+                ARG_IMAGE_POLICY,
         };
 
         int c, r;
 
         static const struct option options[] = {
-                { "help",               no_argument,       NULL, 'h'           },
-                { "version" ,           no_argument,       NULL, ARG_VERSION   },
-                { "no-pager",           no_argument,       NULL, ARG_NO_PAGER  },
-                { "no-legend",          no_argument,       NULL, ARG_NO_LEGEND },
-                { "debugger",           required_argument, NULL, ARG_DEBUGGER  },
-                { "debugger-arguments", required_argument, NULL, 'A'           },
-                { "output",             required_argument, NULL, 'o'           },
-                { "field",              required_argument, NULL, 'F'           },
-                { "file",               required_argument, NULL, ARG_FILE      },
-                { "directory",          required_argument, NULL, 'D'           },
-                { "reverse",            no_argument,       NULL, 'r'           },
-                { "since",              required_argument, NULL, 'S'           },
-                { "until",              required_argument, NULL, 'U'           },
-                { "quiet",              no_argument,       NULL, 'q'           },
-                { "json",               required_argument, NULL, ARG_JSON      },
-                { "root",               required_argument, NULL, ARG_ROOT      },
-                { "image",              required_argument, NULL, ARG_IMAGE     },
-                { "all",                no_argument,       NULL, ARG_ALL       },
+                { "help",               no_argument,       NULL, 'h'              },
+                { "version" ,           no_argument,       NULL, ARG_VERSION      },
+                { "no-pager",           no_argument,       NULL, ARG_NO_PAGER     },
+                { "no-legend",          no_argument,       NULL, ARG_NO_LEGEND    },
+                { "debugger",           required_argument, NULL, ARG_DEBUGGER     },
+                { "debugger-arguments", required_argument, NULL, 'A'              },
+                { "output",             required_argument, NULL, 'o'              },
+                { "field",              required_argument, NULL, 'F'              },
+                { "file",               required_argument, NULL, ARG_FILE         },
+                { "directory",          required_argument, NULL, 'D'              },
+                { "reverse",            no_argument,       NULL, 'r'              },
+                { "since",              required_argument, NULL, 'S'              },
+                { "until",              required_argument, NULL, 'U'              },
+                { "quiet",              no_argument,       NULL, 'q'              },
+                { "json",               required_argument, NULL, ARG_JSON         },
+                { "root",               required_argument, NULL, ARG_ROOT         },
+                { "image",              required_argument, NULL, ARG_IMAGE        },
+                { "all",                no_argument,       NULL, ARG_ALL          },
+                { "image-policy",       required_argument, NULL, ARG_IMAGE_POLICY },
                 {}
         };
 
@@ -363,6 +368,18 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_all = true;
                         break;
 
+                case ARG_IMAGE_POLICY: {
+                        _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
+
+                        r = image_policy_from_string(optarg, &p);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse image policy: %s", optarg);
+
+                        image_policy_free(arg_image_policy);
+                        arg_image_policy = TAKE_PTR(p);
+                        break;
+                }
+
                 case '?':
                         return -EINVAL;
 
@@ -1361,6 +1378,7 @@ static int run(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
+                                arg_image_policy,
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_REQUIRE_ROOT |
                                 DISSECT_IMAGE_RELAX_VAR_CHECK |
index ff00c4f567dcb7378fbe36323d7e870d8c9ebea4..b3f20e193e5ffdfe1c952e221ed81fb57d9ac8ac 100644 (file)
@@ -83,6 +83,7 @@ static bool arg_rmdir = false;
 static bool arg_in_memory = false;
 static char **arg_argv = NULL;
 static char *arg_loop_ref = NULL;
+static ImagePolicy* arg_image_policy = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_path, freep);
@@ -126,6 +127,8 @@ static int help(void) {
                "                          'base64:'\n"
                "     --verity-data=PATH   Specify data file with hash tree for verity if it is\n"
                "                          not embedded in IMAGE\n"
+               "     --image-policy=POLICY\n"
+               "                          Specify image dissection policy\n"
                "     --json=pretty|short|off\n"
                "                          Generate JSON output\n"
                "     --loop-ref=NAME      Set reference string for loopback device\n"
@@ -221,6 +224,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_ATTACH,
                 ARG_DETACH,
                 ARG_LOOP_REF,
+                ARG_IMAGE_POLICY,
         };
 
         static const struct option options[] = {
@@ -250,6 +254,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "json",          required_argument, NULL, ARG_JSON          },
                 { "discover",      no_argument,       NULL, ARG_DISCOVER      },
                 { "loop-ref",      required_argument, NULL, ARG_LOOP_REF      },
+                { "image-policy",  required_argument, NULL, ARG_IMAGE_POLICY  },
                 {}
         };
 
@@ -457,6 +462,18 @@ static int parse_argv(int argc, char *argv[]) {
                                 return r;
                         break;
 
+                case ARG_IMAGE_POLICY: {
+                        _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
+
+                        r = image_policy_from_string(optarg, &p);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse image policy: %s", optarg);
+
+                        image_policy_free(arg_image_policy);
+                        arg_image_policy = TAKE_PTR(p);
+                        break;
+                }
+
                 case '?':
                         return -EINVAL;
 
@@ -1750,7 +1767,8 @@ static int run(int argc, char *argv[]) {
         r = dissect_loop_device_and_warn(
                         d,
                         &arg_verity_settings,
-                        NULL,
+                        /* mount_options= */ NULL,
+                        arg_image_policy,
                         arg_flags,
                         &m);
         if (r < 0)
index 3e68ed1cb029c3e2889ba422fc1e5f4bc6cf53b9..54c72eceaf5b4edb672e2c7e3ccfb71ac1afb350 100644 (file)
@@ -73,6 +73,7 @@ static bool arg_delete_root_password = false;
 static bool arg_root_password_is_hashed = false;
 static bool arg_welcome = true;
 static bool arg_reset = false;
+static ImagePolicy *arg_image_policy = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
@@ -82,6 +83,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_keymap, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_timezone, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_hostname, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_root_password, erase_and_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
 
 static bool press_any_key(void) {
         char k = 0;
@@ -1145,7 +1147,8 @@ static int help(void) {
                "  -h --help                       Show this help\n"
                "     --version                    Show package version\n"
                "     --root=PATH                  Operate on an alternate filesystem root\n"
-               "     --image=PATH                 Operate on an alternate filesystem image\n"
+               "     --image=PATH                 Operate on disk image as filesystem root\n"
+               "     --image-policy=POLICY        Specify disk image dissection policy\n"
                "     --locale=LOCALE              Set primary locale (LANG=)\n"
                "     --locale-messages=LOCALE     Set message locale (LC_MESSAGES=)\n"
                "     --keymap=KEYMAP              Set keymap\n"
@@ -1216,6 +1219,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_DELETE_ROOT_PASSWORD,
                 ARG_WELCOME,
                 ARG_RESET,
+                ARG_IMAGE_POLICY,
         };
 
         static const struct option options[] = {
@@ -1252,6 +1256,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "delete-root-password",    no_argument,       NULL, ARG_DELETE_ROOT_PASSWORD    },
                 { "welcome",                 required_argument, NULL, ARG_WELCOME                 },
                 { "reset",                   no_argument,       NULL, ARG_RESET                   },
+                { "image-policy",            required_argument, NULL, ARG_IMAGE_POLICY            },
                 {}
         };
 
@@ -1458,6 +1463,17 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_reset = true;
                         break;
 
+                case ARG_IMAGE_POLICY: {
+                        _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
+
+                        r = image_policy_from_string(optarg, &p);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse image policy: %s", optarg);
+
+                        image_policy_free(arg_image_policy);
+                        arg_image_policy = TAKE_PTR(p);
+                        break;
+                }
                 case '?':
                         return -EINVAL;
 
@@ -1518,6 +1534,7 @@ static int run(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
+                                arg_image_policy,
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_REQUIRE_ROOT |
                                 DISSECT_IMAGE_VALIDATE_OS |
index 9ccd78af658e11a636a0514dc777f4c6cedeff1d..09c63a31b2f77eb805ad1daba8eb12a21b510925 100644 (file)
@@ -23,6 +23,7 @@
 #include "fstab-util.h"
 #include "generator.h"
 #include "gpt.h"
+#include "image-policy.h"
 #include "initrd-util.h"
 #include "mkdir.h"
 #include "mountpoint-util.h"
@@ -43,6 +44,9 @@ static bool arg_root_enabled = true;
 static char *arg_root_fstype = NULL;
 static char *arg_root_options = NULL;
 static int arg_root_rw = -1;
+static ImagePolicy *arg_image_policy = NULL;
+
+STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
 
 STATIC_DESTRUCTOR_REGISTER(arg_root_fstype, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_root_options, freep);
@@ -744,7 +748,9 @@ static int enumerate_partitions(dev_t devnum) {
 
         r = dissect_loop_device(
                         loop,
-                        NULL, NULL,
+                        /* verity= */ NULL,
+                        /* mount_options= */ NULL,
+                        arg_image_policy ?: &image_policy_host,
                         DISSECT_IMAGE_GPT_ONLY|
                         DISSECT_IMAGE_USR_NO_ROOT|
                         DISSECT_IMAGE_DISKSEQ_DEVNODE,
@@ -882,6 +888,20 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
                 arg_root_rw = true;
         else if (proc_cmdline_key_streq(key, "ro") && !value)
                 arg_root_rw = false;
+        else if (proc_cmdline_key_streq(key, "systemd.image_policy")) {
+                _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
+
+                if (proc_cmdline_value_missing(key, value))
+                        return 0;
+
+                r = image_policy_from_string(value, &p);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to parse image policy: %s", value);
+
+                image_policy_free(arg_image_policy);
+                arg_image_policy = TAKE_PTR(p);
+                return 0;
+        }
 
         return 0;
 }
index 97e9c1aafc4a6522362a2b2cbc244611b1979d87..abacbb03066f82fe864c2cd15e134f2ad54f63be 100644 (file)
@@ -134,6 +134,7 @@ static Set *arg_output_fields = NULL;
 static const char *arg_pattern = NULL;
 static pcre2_code *arg_compiled_pattern = NULL;
 static PatternCompileCase arg_case = PATTERN_COMPILE_CASE_AUTO;
+ImagePolicy *arg_image_policy = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_file, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_facilities, set_freep);
@@ -145,6 +146,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_output_fields, set_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_compiled_pattern, pattern_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
 
 static enum {
         ACTION_SHOW,
@@ -326,8 +328,9 @@ static int help(void) {
                "  -m --merge                 Show entries from all available journals\n"
                "  -D --directory=PATH        Show journal files from directory\n"
                "     --file=PATH             Show journal file\n"
-               "     --root=ROOT             Operate on files below a root directory\n"
-               "     --image=IMAGE           Operate on files in filesystem image\n"
+               "     --root=PATH             Operate on an alternate filesystem root\n"
+               "     --image=PATH            Operate on disk image as filesystem root\n"
+               "     --image-policy=POLICY   Specify disk image dissection policy\n"
                "     --namespace=NAMESPACE   Show journal data from specified journal namespace\n"
                "\n%3$sFiltering Options:%4$s\n"
                "  -S --since=DATE            Show entries not older than the specified date\n"
@@ -444,6 +447,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_NO_HOSTNAME,
                 ARG_OUTPUT_FIELDS,
                 ARG_NAMESPACE,
+                ARG_IMAGE_POLICY,
         };
 
         static const struct option options[] = {
@@ -511,6 +515,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "no-hostname",          no_argument,       NULL, ARG_NO_HOSTNAME          },
                 { "output-fields",        required_argument, NULL, ARG_OUTPUT_FIELDS        },
                 { "namespace",            required_argument, NULL, ARG_NAMESPACE            },
+                { "image-policy",         required_argument, NULL, ARG_IMAGE_POLICY         },
                 {}
         };
 
@@ -1033,7 +1038,17 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
                 }
+                case ARG_IMAGE_POLICY: {
+                        _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
 
+                        r = image_policy_from_string(optarg, &p);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse image policy: %s", optarg);
+
+                        image_policy_free(arg_image_policy);
+                        arg_image_policy = TAKE_PTR(p);
+                        break;
+                }
                 case '?':
                         return -EINVAL;
 
@@ -2126,6 +2141,7 @@ static int run(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
+                                arg_image_policy,
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_REQUIRE_ROOT |
                                 DISSECT_IMAGE_VALIDATE_OS |
index 223164ea1bd25510ae147f5680962802c48c203a..c5b22d5d768aaedde72c5117b372ec486d334035 100644 (file)
@@ -22,9 +22,11 @@ static char *arg_root = NULL;
 static char *arg_image = NULL;
 static bool arg_commit = false;
 static bool arg_print = false;
+static ImagePolicy *arg_image_policy = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
 
 static int help(void) {
         _cleanup_free_ char *link = NULL;
@@ -36,12 +38,13 @@ static int help(void) {
 
         printf("%s [OPTIONS...]\n"
                "\n%sInitialize /etc/machine-id from a random source.%s\n\n"
-               "  -h --help             Show this help\n"
-               "     --version          Show package version\n"
-               "     --root=PATH        Operate relative to root path\n"
-               "     --image=PATH       Operate relative to image file\n"
-               "     --commit           Commit transient ID\n"
-               "     --print            Print used machine ID\n"
+               "  -h --help                 Show this help\n"
+               "     --version              Show package version\n"
+               "     --root=PATH            Operate on an alternate filesystem root\n"
+               "     --image=PATH           Operate on disk image as filesystem root\n"
+               "     --image-policy=POLICY  Specify disk image dissection policy\n"
+               "     --commit               Commit transient ID\n"
+               "     --print                Print used machine ID\n"
                "\nSee the %s for details.\n",
                program_invocation_short_name,
                ansi_highlight(),
@@ -59,15 +62,17 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_IMAGE,
                 ARG_COMMIT,
                 ARG_PRINT,
+                ARG_IMAGE_POLICY,
         };
 
         static const struct option options[] = {
-                { "help",      no_argument,       NULL, 'h'           },
-                { "version",   no_argument,       NULL, ARG_VERSION   },
-                { "root",      required_argument, NULL, ARG_ROOT      },
-                { "image",     required_argument, NULL, ARG_IMAGE     },
-                { "commit",    no_argument,       NULL, ARG_COMMIT    },
-                { "print",     no_argument,       NULL, ARG_PRINT     },
+                { "help",         no_argument,       NULL, 'h'              },
+                { "version",      no_argument,       NULL, ARG_VERSION      },
+                { "root",         required_argument, NULL, ARG_ROOT         },
+                { "image",        required_argument, NULL, ARG_IMAGE        },
+                { "commit",       no_argument,       NULL, ARG_COMMIT       },
+                { "print",        no_argument,       NULL, ARG_PRINT        },
+                { "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
                 {}
         };
 
@@ -106,6 +111,17 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_print = true;
                         break;
 
+                case ARG_IMAGE_POLICY: {
+                        _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
+
+                        r = image_policy_from_string(optarg, &p);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse image policy: %s", optarg);
+
+                        image_policy_free(arg_image_policy);
+                        arg_image_policy = TAKE_PTR(p);
+                        break;
+                }
                 case '?':
                         return -EINVAL;
 
@@ -141,6 +157,7 @@ static int run(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
+                                arg_image_policy,
                                 DISSECT_IMAGE_REQUIRE_ROOT |
                                 DISSECT_IMAGE_VALIDATE_OS |
                                 DISSECT_IMAGE_RELAX_VAR_CHECK |
index bf65eecfdd4232f19132efc045ebb4326207df92..336b42b7e5156b1f86a015d5539747cccf6797b0 100644 (file)
@@ -313,7 +313,7 @@ int bus_image_method_get_hostname(
         int r;
 
         if (!image->metadata_valid) {
-                r = image_read_metadata(image);
+                r = image_read_metadata(image, &image_policy_container);
                 if (r < 0)
                         return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
         }
@@ -331,7 +331,7 @@ int bus_image_method_get_machine_id(
         int r;
 
         if (!image->metadata_valid) {
-                r = image_read_metadata(image);
+                r = image_read_metadata(image, &image_policy_container);
                 if (r < 0)
                         return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
         }
@@ -359,7 +359,7 @@ int bus_image_method_get_machine_info(
         int r;
 
         if (!image->metadata_valid) {
-                r = image_read_metadata(image);
+                r = image_read_metadata(image, &image_policy_container);
                 if (r < 0)
                         return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
         }
@@ -376,7 +376,7 @@ int bus_image_method_get_os_release(
         int r;
 
         if (!image->metadata_valid) {
-                r = image_read_metadata(image);
+                r = image_read_metadata(image, &image_policy_container);
                 if (r < 0)
                         return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
         }
index 8abb01679101625e92e7aacbf7989bc9a7294fc0..6b74a3df1314aefb60980d0fad9cf48c096361a5 100644 (file)
@@ -234,6 +234,7 @@ static char **arg_bind_user = NULL;
 static bool arg_suppress_sync = false;
 static char *arg_settings_filename = NULL;
 static Architecture arg_architecture = _ARCHITECTURE_INVALID;
+static ImagePolicy *arg_image_policy = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_directory, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_template, freep);
@@ -268,6 +269,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_cpu_set, cpu_set_reset);
 STATIC_DESTRUCTOR_REGISTER(arg_sysctl, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_bind_user, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_settings_filename, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
 
 static int handle_arg_console(const char *arg) {
         if (streq(arg, "help")) {
@@ -330,6 +332,7 @@ static int help(void) {
                "                            remove it after exit\n"
                "  -i --image=PATH           Root file system disk image (or device node) for\n"
                "                            the container\n"
+               "     --image-policy=POLICY  Specify disk image dissection policy\n"
                "     --oci-bundle=PATH      OCI bundle directory\n"
                "     --read-only            Mount the root directory read-only\n"
                "     --volatile[=MODE]      Run the system in volatile mode\n"
@@ -732,6 +735,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_LOAD_CREDENTIAL,
                 ARG_BIND_USER,
                 ARG_SUPPRESS_SYNC,
+                ARG_IMAGE_POLICY,
         };
 
         static const struct option options[] = {
@@ -805,6 +809,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "load-credential",        required_argument, NULL, ARG_LOAD_CREDENTIAL        },
                 { "bind-user",              required_argument, NULL, ARG_BIND_USER              },
                 { "suppress-sync",          required_argument, NULL, ARG_SUPPRESS_SYNC          },
+                { "image-policy",           required_argument, NULL, ARG_IMAGE_POLICY           },
                 {}
         };
 
@@ -1696,6 +1701,18 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_settings_mask |= SETTING_SUPPRESS_SYNC;
                         break;
 
+                case ARG_IMAGE_POLICY: {
+                        _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
+
+                        r = image_policy_from_string(optarg, &p);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse image policy: %s", optarg);
+
+                        image_policy_free(arg_image_policy);
+                        arg_image_policy = TAKE_PTR(p);
+                        break;
+                }
+
                 case '?':
                         return -EINVAL;
 
@@ -5755,7 +5772,8 @@ static int run(int argc, char *argv[]) {
                 r = dissect_loop_device_and_warn(
                                 loop,
                                 &arg_verity_settings,
-                                NULL,
+                                /* mount_options=*/ NULL,
+                                arg_image_policy ?: &image_policy_container,
                                 dissect_image_flags,
                                 &dissected_image);
                 if (r == -ENOPKG) {
index e4ae8a2c89fa23c0fa574d7a021e704fe58fc361..bc3bfa15fb69d383fa1bb103e464cea7580be0ff 100644 (file)
@@ -148,6 +148,7 @@ static FilterPartitionsType arg_filter_partitions_type = FILTER_PARTITIONS_NONE;
 static sd_id128_t *arg_defer_partitions = NULL;
 static size_t arg_n_defer_partitions = 0;
 static uint64_t arg_sector_size = 0;
+static ImagePolicy *arg_image_policy = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
@@ -158,6 +159,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_certificate, X509_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_filter_partitions, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
 
 typedef struct FreeArea FreeArea;
 
@@ -5632,6 +5634,8 @@ static int help(void) {
                "     --can-factory-reset  Test whether factory reset is defined\n"
                "     --root=PATH          Operate relative to root path\n"
                "     --image=PATH         Operate relative to image file\n"
+               "     --image-policy=POLICY\n"
+               "                          Specify disk image dissection policy\n"
                "     --definitions=DIR    Find partition definitions in specified directory\n"
                "     --key-file=PATH      Key to use when encrypting partitions\n"
                "     --private-key=PATH   Private key to use when generating verity roothash\n"
@@ -5697,6 +5701,8 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_EXCLUDE_PARTITIONS,
                 ARG_DEFER_PARTITIONS,
                 ARG_SECTOR_SIZE,
+                ARG_SKIP_PARTITIONS,
+                ARG_IMAGE_POLICY,
         };
 
         static const struct option options[] = {
@@ -5728,6 +5734,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "exclude-partitions",   required_argument, NULL, ARG_EXCLUDE_PARTITIONS   },
                 { "defer-partitions",     required_argument, NULL, ARG_DEFER_PARTITIONS     },
                 { "sector-size",          required_argument, NULL, ARG_SECTOR_SIZE          },
+                { "image-policy",         required_argument, NULL, ARG_IMAGE_POLICY         },
                 {}
         };
 
@@ -6022,6 +6029,18 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case ARG_IMAGE_POLICY: {
+                        _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
+
+                        r = image_policy_from_string(optarg, &p);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse image policy: %s", optarg);
+
+                        image_policy_free(arg_image_policy);
+                        arg_image_policy = TAKE_PTR(p);
+                        break;
+                }
+
                 case '?':
                         return -EINVAL;
 
@@ -6522,6 +6541,7 @@ static int run(int argc, char *argv[]) {
                  * systems */
                 r = mount_image_privately_interactively(
                                 arg_image,
+                                arg_image_policy,
                                 DISSECT_IMAGE_MOUNT_READ_ONLY |
                                 (arg_node ? DISSECT_IMAGE_DEVICE_READ_ONLY : 0) | /* If a different node to make changes to is specified let's open the device in read-only mode) */
                                 DISSECT_IMAGE_GPT_ONLY |
index adfd846bab79789586b29713dde463b732eacdb6..23420abab25da81d232f695164a24c328824c989 100644 (file)
@@ -324,6 +324,7 @@ static int portable_extract_by_path(
                 bool path_is_extension,
                 bool relax_extension_release_check,
                 char **matches,
+                const ImagePolicy *image_policy,
                 PortableMetadata **ret_os_release,
                 Hashmap **ret_unit_files,
                 sd_bus_error *error) {
@@ -369,7 +370,9 @@ static int portable_extract_by_path(
 
                 r = dissect_loop_device(
                                 d,
-                                NULL, NULL,
+                                /* verity= */ NULL,
+                                /* mount_options= */ NULL,
+                                image_policy,
                                 DISSECT_IMAGE_READ_ONLY |
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_REQUIRE_ROOT |
@@ -510,6 +513,7 @@ static int extract_image_and_extensions(
                 char **extension_image_paths,
                 bool validate_sysext,
                 bool relax_extension_release_check,
+                const ImagePolicy *image_policy,
                 Image **ret_image,
                 OrderedHashmap **ret_extension_images,
                 OrderedHashmap **ret_extension_releases,
@@ -558,7 +562,15 @@ static int extract_image_and_extensions(
                 }
         }
 
-        r = portable_extract_by_path(image->path, /* path_is_extension= */ false, /* relax_extension_release_check= */ false, matches, &os_release, &unit_files, error);
+        r = portable_extract_by_path(
+                        image->path,
+                        /* path_is_extension= */ false,
+                        /* relax_extension_release_check= */ false,
+                        matches,
+                        image_policy,
+                        &os_release,
+                        &unit_files,
+                        error);
         if (r < 0)
                 return r;
 
@@ -591,7 +603,15 @@ static int extract_image_and_extensions(
                 _cleanup_strv_free_ char **extension_release = NULL;
                 const char *e;
 
-                r = portable_extract_by_path(ext->path, /* path_is_extension= */ true, relax_extension_release_check, matches, &extension_release_meta, &extra_unit_files, error);
+                r = portable_extract_by_path(
+                                ext->path,
+                                /* path_is_extension= */ true,
+                                relax_extension_release_check,
+                                matches,
+                                image_policy,
+                                &extension_release_meta,
+                                &extra_unit_files,
+                                error);
                 if (r < 0)
                         return r;
 
@@ -657,6 +677,7 @@ int portable_extract(
                 const char *name_or_path,
                 char **matches,
                 char **extension_image_paths,
+                const ImagePolicy *image_policy,
                 PortableFlags flags,
                 PortableMetadata **ret_os_release,
                 OrderedHashmap **ret_extension_releases,
@@ -679,6 +700,7 @@ int portable_extract(
                         extension_image_paths,
                         /* validate_sysext= */ false,
                         /* relax_extension_release_check= */ FLAGS_SET(flags, PORTABLE_FORCE_SYSEXT),
+                        image_policy,
                         &image,
                         &extension_images,
                         &extension_releases,
@@ -1392,6 +1414,7 @@ int portable_attach(
                 char **matches,
                 const char *profile,
                 char **extension_image_paths,
+                const ImagePolicy *image_policy,
                 PortableFlags flags,
                 PortableChange **changes,
                 size_t *n_changes,
@@ -1412,6 +1435,7 @@ int portable_attach(
                         extension_image_paths,
                         /* validate_sysext= */ true,
                         /* relax_extension_release_check= */ FLAGS_SET(flags, PORTABLE_FORCE_SYSEXT),
+                        image_policy,
                         &image,
                         &extension_images,
                         &extension_releases,
index 1a33f30944c24cc3065897f880e424f4d9414c31..c61d65fed3500f94874d415ac658bbe37da1eb39 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "sd-bus.h"
 
+#include "dissect-image.h"
 #include "hashmap.h"
 #include "macro.h"
 #include "set.h"
@@ -67,9 +68,9 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(PortableMetadata*, portable_metadata_unref);
 
 int portable_metadata_hashmap_to_sorted_array(Hashmap *unit_files, PortableMetadata ***ret);
 
-int portable_extract(const char *image, char **matches, char **extension_image_paths, PortableFlags flags, PortableMetadata **ret_os_release, OrderedHashmap **ret_extension_releases, Hashmap **ret_unit_files, char ***ret_valid_prefixes, sd_bus_error *error);
+int portable_extract(const char *image, char **matches, char **extension_image_paths, const ImagePolicy *image_policy, PortableFlags flags, PortableMetadata **ret_os_release, OrderedHashmap **ret_extension_releases, Hashmap **ret_unit_files, char ***ret_valid_prefixes, sd_bus_error *error);
 
-int portable_attach(sd_bus *bus, const char *name_or_path, char **matches, const char *profile, char **extension_images, PortableFlags flags, PortableChange **changes, size_t *n_changes, sd_bus_error *error);
+int portable_attach(sd_bus *bus, const char *name_or_path, char **matches, const char *profile, char **extension_images, const ImagePolicy* image_policy, PortableFlags flags, PortableChange **changes, size_t *n_changes, sd_bus_error *error);
 int portable_detach(sd_bus *bus, const char *name_or_path, char **extension_image_paths, PortableFlags flags, PortableChange **changes, size_t *n_changes, sd_bus_error *error);
 
 int portable_get_state(sd_bus *bus, const char *name_or_path, char **extension_image_paths, PortableFlags flags, PortableState *ret, sd_bus_error *error);
index 6c4cb6ec9de8acf96011a71a1a5326a92730f294..262518d15cc38e5f3c0f1209a160bdf2b2ac13d6 100644 (file)
@@ -60,7 +60,7 @@ int bus_image_common_get_os_release(
                 return 1;
 
         if (!image->metadata_valid) {
-                r = image_read_metadata(image);
+                r = image_read_metadata(image, &image_policy_service);
                 if (r < 0)
                         return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
         }
@@ -163,6 +163,7 @@ int bus_image_common_get_metadata(
                         image->path,
                         matches,
                         extension_images,
+                        /* image_policy= */ NULL,
                         flags,
                         &os_release,
                         &extension_releases,
@@ -385,6 +386,7 @@ int bus_image_common_attach(
                         matches,
                         profile,
                         extension_images,
+                        /* image_policy= */ NULL,
                         flags,
                         &changes,
                         &n_changes,
@@ -729,6 +731,7 @@ int bus_image_common_reattach(
                         matches,
                         profile,
                         extension_images,
+                        /* image_policy= */ NULL,
                         flags,
                         &changes_attached,
                         &n_changes_attached,
index 6966cfd8389372abde0011a6f57c1e3c417abc42..81eef8b058362cabd43c3fd3549c15647b72015d 100644 (file)
@@ -959,7 +959,10 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
                               "ProcSubset",
                               "NetworkNamespacePath",
                               "IPCNamespacePath",
-                              "LogNamespace"))
+                              "LogNamespace",
+                              "RootImagePolicy",
+                              "MountImagePolicy",
+                              "ExtensionImagePolicy"))
                 return bus_append_string(m, field, eq);
 
         if (STR_IN_SET(field, "IgnoreSIGPIPE",
index eed0a5629e49097bb3415763f7aeefef021a3ac8..86ff5d6d93a3eec0b2c91cd26406b1c05ad6e9ba 100644 (file)
@@ -1133,7 +1133,7 @@ int image_set_limit(Image *i, uint64_t referenced_max) {
         return btrfs_subvol_set_subtree_quota_limit(i->path, 0, referenced_max);
 }
 
-int image_read_metadata(Image *i) {
+int image_read_metadata(Image *i, const ImagePolicy *image_policy) {
         _cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
         int r;
 
@@ -1214,7 +1214,9 @@ int image_read_metadata(Image *i) {
 
                 r = dissect_loop_device(
                                 d,
-                                NULL, NULL,
+                                /* verity= */ NULL,
+                                /* mount_options= */ NULL,
+                                image_policy,
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_REQUIRE_ROOT |
                                 DISSECT_IMAGE_RELAX_VAR_CHECK |
index 3c6928619c0eb02d579f250379284bfcc5883093..c423132a62b3855cc17b89f2f2bfa5d855b9bfb7 100644 (file)
@@ -7,6 +7,7 @@
 #include "sd-id128.h"
 
 #include "hashmap.h"
+#include "image-policy.h"
 #include "lock-util.h"
 #include "macro.h"
 #include "path-util.h"
@@ -85,7 +86,7 @@ int image_name_lock(const char *name, int operation, LockFile *ret);
 
 int image_set_limit(Image *i, uint64_t referenced_max);
 
-int image_read_metadata(Image *i);
+int image_read_metadata(Image *i, const ImagePolicy *image_policy);
 
 bool image_in_search_path(ImageClass class, const char *root, const char *image);
 
index 6000af0ce05a9b78926856279fb941baf60c6788..83b0581ff1a68319485ee6cc9a13a2671dc78be6 100644 (file)
@@ -543,6 +543,7 @@ static int dissect_image(
                 const char *devname,
                 const VeritySettings *verity,
                 const MountOptions *mount_options,
+                const ImagePolicy *policy,
                 DissectImageFlags flags) {
 
         sd_id128_t root_uuid = SD_ID128_NULL, root_verity_uuid = SD_ID128_NULL;
@@ -1331,6 +1332,7 @@ int dissect_image_file(
                 const char *path,
                 const VeritySettings *verity,
                 const MountOptions *mount_options,
+                const ImagePolicy *image_policy,
                 DissectImageFlags flags,
                 DissectedImage **ret) {
 
@@ -1358,7 +1360,7 @@ int dissect_image_file(
         if (r < 0)
                 return r;
 
-        r = dissect_image(m, fd, path, verity, mount_options, flags);
+        r = dissect_image(m, fd, path, verity, mount_options, image_policy, flags);
         if (r < 0)
                 return r;
 
@@ -3250,6 +3252,7 @@ int dissect_loop_device(
                 LoopDevice *loop,
                 const VeritySettings *verity,
                 const MountOptions *mount_options,
+                const ImagePolicy *image_policy,
                 DissectImageFlags flags,
                 DissectedImage **ret) {
 
@@ -3267,7 +3270,7 @@ int dissect_loop_device(
         m->loop = loop_device_ref(loop);
         m->sector_size = m->loop->sector_size;
 
-        r = dissect_image(m, loop->fd, loop->node, verity, mount_options, flags);
+        r = dissect_image(m, loop->fd, loop->node, verity, mount_options, image_policy, flags);
         if (r < 0)
                 return r;
 
@@ -3282,6 +3285,7 @@ int dissect_loop_device_and_warn(
                 LoopDevice *loop,
                 const VeritySettings *verity,
                 const MountOptions *mount_options,
+                const ImagePolicy *image_policy,
                 DissectImageFlags flags,
                 DissectedImage **ret) {
 
@@ -3293,7 +3297,7 @@ int dissect_loop_device_and_warn(
 
         name = ASSERT_PTR(loop->backing_file ?: loop->node);
 
-        r = dissect_loop_device(loop, verity, mount_options, flags, ret);
+        r = dissect_loop_device(loop, verity, mount_options, image_policy, flags, ret);
         switch (r) {
 
         case -EOPNOTSUPP:
@@ -3407,6 +3411,7 @@ const char* mount_options_from_designator(const MountOptions *options, Partition
 
 int mount_image_privately_interactively(
                 const char *image,
+                const ImagePolicy *image_policy,
                 DissectImageFlags flags,
                 char **ret_directory,
                 int *ret_dir_fd,
@@ -3449,7 +3454,13 @@ int mount_image_privately_interactively(
         if (r < 0)
                 return log_error_errno(r, "Failed to set up loopback device for %s: %m", image);
 
-        r = dissect_loop_device_and_warn(d, &verity, NULL, flags, &dissected_image);
+        r = dissect_loop_device_and_warn(
+                        d,
+                        &verity,
+                        /* mount_options= */ NULL,
+                        image_policy,
+                        flags,
+                        &dissected_image);
         if (r < 0)
                 return r;
 
@@ -3513,6 +3524,7 @@ int verity_dissect_and_mount(
                 const char *src,
                 const char *dest,
                 const MountOptions *options,
+                const ImagePolicy *image_policy,
                 const char *required_host_os_release_id,
                 const char *required_host_os_release_version_id,
                 const char *required_host_os_release_sysext_level,
@@ -3556,6 +3568,7 @@ int verity_dissect_and_mount(
                         loop_device,
                         &verity,
                         options,
+                        image_policy,
                         dissect_image_flags,
                         &dissected_image);
         /* No partition table? Might be a single-filesystem image, try again */
@@ -3564,6 +3577,7 @@ int verity_dissect_and_mount(
                                 loop_device,
                                 &verity,
                                 options,
+                                image_policy,
                                 dissect_image_flags | DISSECT_IMAGE_NO_PARTITION_TABLE,
                                 &dissected_image);
         if (r < 0)
index 2e741e826764047efe138fb367c98855fa95d7b6..3af0c439bcfb64145f6878de3b14a3ed82b6138c 100644 (file)
@@ -133,6 +133,9 @@ struct VeritySettings {
                 .designator = _PARTITION_DESIGNATOR_INVALID     \
         }
 
+/* We include image-policy.h down here, since ImagePolicy wants a complete definition of PartitionDesignator first. */
+#include "image-policy.h"
+
 MountOptions* mount_options_free_all(MountOptions *options);
 DEFINE_TRIVIAL_CLEANUP_FUNC(MountOptions*, mount_options_free_all);
 const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator);
@@ -141,14 +144,10 @@ int probe_filesystem_full(int fd, const char *path, uint64_t offset, uint64_t si
 static inline int probe_filesystem(const char *path, char **ret_fstype) {
         return probe_filesystem_full(-1, path, 0, UINT64_MAX, ret_fstype);
 }
-int dissect_image_file(
-                const char *path,
-                const VeritySettings *verity,
-                const MountOptions *mount_options,
-                DissectImageFlags flags,
-                DissectedImage **ret);
-int dissect_loop_device(LoopDevice *loop, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret);
-int dissect_loop_device_and_warn(LoopDevice *loop, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret);
+
+int dissect_image_file(const char *path, const VeritySettings *verity, const MountOptions *mount_options, const ImagePolicy *image_policy, DissectImageFlags flags, DissectedImage **ret);
+int dissect_loop_device(LoopDevice *loop, const VeritySettings *verity, const MountOptions *mount_options, const ImagePolicy *image_policy, DissectImageFlags flags, DissectedImage **ret);
+int dissect_loop_device_and_warn(LoopDevice *loop, const VeritySettings *verity, const MountOptions *mount_options, const ImagePolicy *image_policy, DissectImageFlags flags, DissectedImage **ret);
 
 DissectedImage* dissected_image_unref(DissectedImage *m);
 DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref);
@@ -185,9 +184,9 @@ bool dissected_image_verity_candidate(const DissectedImage *image, PartitionDesi
 bool dissected_image_verity_ready(const DissectedImage *image, PartitionDesignator d);
 bool dissected_image_verity_sig_ready(const DissectedImage *image, PartitionDesignator d);
 
-int mount_image_privately_interactively(const char *path, DissectImageFlags flags, char **ret_directory, int *ret_dir_fd, LoopDevice **ret_loop_device);
+int mount_image_privately_interactively(const char *path, const ImagePolicy *image_policy, DissectImageFlags flags, char **ret_directory, int *ret_dir_fd, LoopDevice **ret_loop_device);
 
-int verity_dissect_and_mount(int src_fd, const char *src, const char *dest, const MountOptions *options, const char *required_host_os_release_id, const char *required_host_os_release_version_id, const char *required_host_os_release_sysext_level, const char *required_sysext_scope);
+int verity_dissect_and_mount(int src_fd, const char *src, const char *dest, const MountOptions *options, const ImagePolicy *image_policy, const char *required_host_os_release_id, const char *required_host_os_release_version_id, const char *required_host_os_release_sysext_level, const char *required_sysext_scope);
 
 int dissect_fstype_ok(const char *fstype);
 
index 1eac51b81eab9c457236835fefbb577eb6b78cb8..edf01fe0921ccf459f703104d1fc815d4d37350d 100644 (file)
@@ -805,6 +805,7 @@ static int mount_in_namespace(
                 bool read_only,
                 bool make_file_or_directory,
                 const MountOptions *options,
+                const ImagePolicy *image_policy,
                 bool is_image) {
 
         _cleanup_close_pair_ int errno_pipe_fd[2] = PIPE_EBADF;
@@ -892,7 +893,7 @@ static int mount_in_namespace(
         mount_tmp_created = true;
 
         if (is_image)
-                r = verity_dissect_and_mount(chased_src_fd, chased_src_path, mount_tmp, options, NULL, NULL, NULL, NULL);
+                r = verity_dissect_and_mount(chased_src_fd, chased_src_path, mount_tmp, options, image_policy, NULL, NULL, NULL, NULL);
         else
                 r = mount_follow_verbose(LOG_DEBUG, FORMAT_PROC_FD_PATH(chased_src_fd), mount_tmp, NULL, MS_BIND, NULL);
         if (r < 0)
@@ -1042,7 +1043,7 @@ int bind_mount_in_namespace(
                 bool read_only,
                 bool make_file_or_directory) {
 
-        return mount_in_namespace(target, propagate_path, incoming_path, src, dest, read_only, make_file_or_directory, NULL, false);
+        return mount_in_namespace(target, propagate_path, incoming_path, src, dest, read_only, make_file_or_directory, /* options= */ NULL, /* image_policy= */ NULL, /* is_image= */ false);
 }
 
 int mount_image_in_namespace(
@@ -1053,9 +1054,10 @@ int mount_image_in_namespace(
                 const char *dest,
                 bool read_only,
                 bool make_file_or_directory,
-                const MountOptions *options) {
+                const MountOptions *options,
+                const ImagePolicy *image_policy) {
 
-        return mount_in_namespace(target, propagate_path, incoming_path, src, dest, read_only, make_file_or_directory, options, true);
+        return mount_in_namespace(target, propagate_path, incoming_path, src, dest, read_only, make_file_or_directory, options, image_policy, /* is_image=*/ true);
 }
 
 int make_mount_point(const char *path) {
index 84ea4b6392773f388e132b7f0c5f877ccd1c9043..f52687828a6c7b9d6ad7ce33f05089eed1bb8c3e 100644 (file)
@@ -81,7 +81,7 @@ static inline char* umount_and_rmdir_and_free(char *p) {
 DEFINE_TRIVIAL_CLEANUP_FUNC(char*, umount_and_rmdir_and_free);
 
 int bind_mount_in_namespace(pid_t target, const char *propagate_path, const char *incoming_path, const char *src, const char *dest, bool read_only, bool make_file_or_directory);
-int mount_image_in_namespace(pid_t target, const char *propagate_path, const char *incoming_path, const char *src, const char *dest, bool read_only, bool make_file_or_directory, const MountOptions *options);
+int mount_image_in_namespace(pid_t target, const char *propagate_path, const char *incoming_path, const char *src, const char *dest, bool read_only, bool make_file_or_directory, const MountOptions *options, const ImagePolicy *image_policy);
 
 int make_mount_point(const char *path);
 
index 5632b72f3d2adee9024ec6e4dc97130b471237a7..ce076f665a6540ddc3f446b5c7fce8f498b7495a 100644 (file)
@@ -45,9 +45,11 @@ static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
 static PagerFlags arg_pager_flags = 0;
 static bool arg_legend = true;
 static bool arg_force = false;
+static ImagePolicy *arg_image_policy = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_hierarchies, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
 
 static int is_our_mount_point(const char *p) {
         _cleanup_free_ char *buf = NULL, *f = NULL;
@@ -523,7 +525,8 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
                         r = dissect_loop_device_and_warn(
                                         d,
                                         &verity_settings,
-                                        NULL,
+                                        /* mount_options= */ NULL,
+                                        arg_image_policy ?: &image_policy_sysext,
                                         flags,
                                         &m);
                         if (r < 0)
@@ -734,7 +737,7 @@ static int image_discover_and_read_metadata(Hashmap **ret_images) {
                 return log_error_errno(r, "Failed to discover extension images: %m");
 
         HASHMAP_FOREACH(img, images) {
-                r = image_read_metadata(img);
+                r = image_read_metadata(img, &image_policy_sysext);
                 if (r < 0)
                         return log_error_errno(r, "Failed to read metadata for image %s: %m", img->name);
         }
@@ -886,6 +889,8 @@ static int verb_help(int argc, char **argv, void *userdata) {
                "     --json=pretty|short|off\n"
                "                          Generate JSON output\n"
                "     --force              Ignore version incompatibilities\n"
+               "     --image-policy=POLICY\n"
+               "                          Specify disk image dissection policy\n"
                "\nSee the %2$s for details.\n",
                program_invocation_short_name,
                link,
@@ -906,16 +911,18 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_ROOT,
                 ARG_JSON,
                 ARG_FORCE,
+                ARG_IMAGE_POLICY,
         };
 
         static const struct option options[] = {
-                { "help",      no_argument,       NULL, 'h'           },
-                { "version",   no_argument,       NULL, ARG_VERSION   },
-                { "no-pager",  no_argument,       NULL, ARG_NO_PAGER  },
-                { "no-legend", no_argument,       NULL, ARG_NO_LEGEND },
-                { "root",      required_argument, NULL, ARG_ROOT      },
-                { "json",      required_argument, NULL, ARG_JSON      },
-                { "force",     no_argument,       NULL, ARG_FORCE     },
+                { "help",         no_argument,       NULL, 'h'              },
+                { "version",      no_argument,       NULL, ARG_VERSION      },
+                { "no-pager",     no_argument,       NULL, ARG_NO_PAGER     },
+                { "no-legend",    no_argument,       NULL, ARG_NO_LEGEND    },
+                { "root",         required_argument, NULL, ARG_ROOT         },
+                { "json",         required_argument, NULL, ARG_JSON         },
+                { "force",        no_argument,       NULL, ARG_FORCE        },
+                { "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
                 {}
         };
 
@@ -959,6 +966,17 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_force = true;
                         break;
 
+                case ARG_IMAGE_POLICY: {
+                        _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
+
+                        r = image_policy_from_string(optarg, &p);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse image policy: %s", optarg);
+
+                        image_policy_free(arg_image_policy);
+                        arg_image_policy = TAKE_PTR(p);
+                        break;
+                }
                 case '?':
                         return -EINVAL;
 
index 1a5beabc7221c2650a8f63442574f770bd814285..df4cf684355d753e5ce2ecb6dc9dbcedbb211a14 100644 (file)
@@ -121,6 +121,7 @@ bool arg_read_only = false;
 bool arg_mkdir = false;
 bool arg_marked = false;
 const char *arg_drop_in = NULL;
+ImagePolicy *arg_image_policy = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_types, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_states, strv_freep);
@@ -135,6 +136,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_host, unsetp);
 STATIC_DESTRUCTOR_REGISTER(arg_boot_loader_entry, unsetp);
 STATIC_DESTRUCTOR_REGISTER(arg_clean_what, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_drop_in, unsetp);
+STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
 
 static int systemctl_help(void) {
         _cleanup_free_ char *link = NULL;
@@ -305,7 +307,9 @@ static int systemctl_help(void) {
                "     --root=PATH         Edit/enable/disable/mask unit files in the specified\n"
                "                         root directory\n"
                "     --image=PATH        Edit/enable/disable/mask unit files in the specified\n"
-               "                         image\n"
+               "                         disk image\n"
+               "     --image-policy=POLICY\n"
+               "                         Specify disk image dissection policy\n"
                "  -n --lines=INTEGER     Number of journal entries to show\n"
                "  -o --output=STRING     Change journal output mode (short, short-precise,\n"
                "                             short-iso, short-iso-precise, short-full,\n"
@@ -450,6 +454,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_NO_WARN,
                 ARG_DROP_IN,
                 ARG_WHEN,
+                ARG_IMAGE_POLICY,
         };
 
         static const struct option options[] = {
@@ -515,6 +520,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 { "marked",              no_argument,       NULL, ARG_MARKED              },
                 { "drop-in",             required_argument, NULL, ARG_DROP_IN             },
                 { "when",                required_argument, NULL, ARG_WHEN                },
+                { "image-policy",        required_argument, NULL, ARG_IMAGE_POLICY        },
                 {}
         };
 
@@ -1003,6 +1009,18 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case ARG_IMAGE_POLICY: {
+                        _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
+
+                        r = image_policy_from_string(optarg, &p);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse image policy: %s", optarg);
+
+                        image_policy_free(arg_image_policy);
+                        arg_image_policy = TAKE_PTR(p);
+                        break;
+                }
+
                 case '.':
                         /* Output an error mimicking getopt, and print a hint afterwards */
                         log_error("%s: invalid option -- '.'", program_invocation_name);
@@ -1248,6 +1266,7 @@ static int run(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
+                                arg_image_policy,
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_REQUIRE_ROOT |
                                 DISSECT_IMAGE_RELAX_VAR_CHECK |
index 8c96ee0b4f0ed6f26e5fef02a1bef8140eaa8f7a..03645624ee82706630b6d1e058495f3091d3c043 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "bus-print-properties.h"
 #include "bus-util.h"
+#include "image-policy.h"
 #include "install.h"
 #include "output-mode.h"
 #include "pager.h"
@@ -100,6 +101,7 @@ extern bool arg_read_only;
 extern bool arg_mkdir;
 extern bool arg_marked;
 extern const char *arg_drop_in;
+extern ImagePolicy *arg_image_policy;
 
 static inline const char* arg_job_mode(void) {
         return _arg_job_mode ?: "replace";
index 6cb09dae50d657690db15a3c2d24e8eededbe870..f62e1930562ce4b9893213812d661d20e6fc8e0d 100644 (file)
@@ -46,11 +46,13 @@ static char *arg_image = NULL;
 static bool arg_reboot = false;
 static char *arg_component = NULL;
 static int arg_verify = -1;
+static ImagePolicy *arg_image_policy = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_definitions, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_component, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
 
 typedef struct Context {
         Transfer **transfers;
@@ -872,6 +874,7 @@ static int process_image(
 
         r = mount_image_privately_interactively(
                         arg_image,
+                        arg_image_policy,
                         (ro ? DISSECT_IMAGE_READ_ONLY : 0) |
                         DISSECT_IMAGE_FSCK |
                         DISSECT_IMAGE_MKDIR |
@@ -1022,7 +1025,7 @@ static int verb_pending_or_reboot(int argc, char **argv, void *userdata) {
 
         if (arg_image || arg_root)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "The --root=/--image switches may not be combined with the '%s' operation.", argv[0]);
+                                       "The --root=/--image= switches may not be combined with the '%s' operation.", argv[0]);
 
         r = context_make_offline(&context, NULL);
         if (r < 0)
@@ -1205,8 +1208,10 @@ static int verb_help(int argc, char **argv, void *userdata) {
                "\n%3$sOptions:%4$s\n"
                "  -C --component=NAME     Select component to update\n"
                "     --definitions=DIR    Find transfer definitions in specified directory\n"
-               "     --root=PATH          Operate relative to root path\n"
-               "     --image=PATH         Operate relative to image file\n"
+               "     --root=PATH          Operate on an alternate filesystem root\n"
+               "     --image=PATH         Operate on disk image as filesystem root\n"
+               "     --image-policy=POLICY\n"
+               "                          Specify disk image dissection policy\n"
                "  -m --instances-max=INT  How many instances to maintain\n"
                "     --sync=BOOL          Controls whether to sync data to disk\n"
                "     --verify=BOOL        Force signature verification on or off\n"
@@ -1238,6 +1243,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_IMAGE,
                 ARG_REBOOT,
                 ARG_VERIFY,
+                ARG_IMAGE_POLICY,
         };
 
         static const struct option options[] = {
@@ -1254,6 +1260,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "reboot",            no_argument,       NULL, ARG_REBOOT            },
                 { "component",         required_argument, NULL, 'C'                   },
                 { "verify",            required_argument, NULL, ARG_VERIFY            },
+                { "image-policy",      required_argument, NULL, ARG_IMAGE_POLICY      },
                 {}
         };
 
@@ -1351,6 +1358,17 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
                 }
 
+                case ARG_IMAGE_POLICY: {
+                        _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
+
+                        r = image_policy_from_string(optarg, &p);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse image policy: %s", optarg);
+
+                        image_policy_free(arg_image_policy);
+                        arg_image_policy = TAKE_PTR(p);
+                        break;
+                }
                 case '?':
                         return -EINVAL;
 
index f9f694bd5493e0eb4a4768d7923da943ffb0b55d..a2d62121e0b7289e6d7577ce6ca14e8547ae9803 100644 (file)
@@ -99,6 +99,7 @@ static const char *arg_replace = NULL;
 static bool arg_dry_run = false;
 static bool arg_inline = false;
 static PagerFlags arg_pager_flags = 0;
+static ImagePolicy *arg_image_policy = NULL;
 
 static OrderedHashmap *users = NULL, *groups = NULL;
 static OrderedHashmap *todo_uids = NULL, *todo_gids = NULL;
@@ -128,6 +129,7 @@ STATIC_DESTRUCTOR_REGISTER(database_groups, set_free_freep);
 STATIC_DESTRUCTOR_REGISTER(uid_range, uid_range_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
 
 static int errno_is_not_exists(int code) {
         /* See getpwnam(3) and getgrnam(3): those codes and others can be returned if the user or group are
@@ -1964,6 +1966,7 @@ static int help(void) {
                "     --cat-config           Show configuration files\n"
                "     --root=PATH            Operate on an alternate filesystem root\n"
                "     --image=PATH           Operate on disk image as filesystem root\n"
+               "     --image-policy=POLICY  Specify disk image dissection policy\n"
                "     --replace=PATH         Treat arguments as replacement for PATH\n"
                "     --dry-run              Just print what would be done\n"
                "     --inline               Treat arguments as configuration lines\n"
@@ -1986,18 +1989,20 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_DRY_RUN,
                 ARG_INLINE,
                 ARG_NO_PAGER,
+                ARG_IMAGE_POLICY,
         };
 
         static const struct option options[] = {
-                { "help",       no_argument,       NULL, 'h'            },
-                { "version",    no_argument,       NULL, ARG_VERSION    },
-                { "cat-config", no_argument,       NULL, ARG_CAT_CONFIG },
-                { "root",       required_argument, NULL, ARG_ROOT       },
-                { "image",      required_argument, NULL, ARG_IMAGE      },
-                { "replace",    required_argument, NULL, ARG_REPLACE    },
-                { "dry-run",    no_argument,       NULL, ARG_DRY_RUN    },
-                { "inline",     no_argument,       NULL, ARG_INLINE     },
-                { "no-pager",   no_argument,       NULL, ARG_NO_PAGER   },
+                { "help",         no_argument,       NULL, 'h'              },
+                { "version",      no_argument,       NULL, ARG_VERSION      },
+                { "cat-config",   no_argument,       NULL, ARG_CAT_CONFIG   },
+                { "root",         required_argument, NULL, ARG_ROOT         },
+                { "image",        required_argument, NULL, ARG_IMAGE        },
+                { "replace",      required_argument, NULL, ARG_REPLACE      },
+                { "dry-run",      no_argument,       NULL, ARG_DRY_RUN      },
+                { "inline",       no_argument,       NULL, ARG_INLINE       },
+                { "no-pager",     no_argument,       NULL, ARG_NO_PAGER     },
+                { "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
                 {}
         };
 
@@ -2058,6 +2063,17 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_pager_flags |= PAGER_DISABLE;
                         break;
 
+                case ARG_IMAGE_POLICY: {
+                        _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
+
+                        r = image_policy_from_string(optarg, &p);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse image policy: %s", optarg);
+
+                        image_policy_free(arg_image_policy);
+                        arg_image_policy = TAKE_PTR(p);
+                        break;
+                }
                 case '?':
                         return -EINVAL;
 
@@ -2173,6 +2189,7 @@ static int run(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
+                                arg_image_policy,
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_REQUIRE_ROOT |
                                 DISSECT_IMAGE_VALIDATE_OS |
index 97c2f66ac99f5fed4ef7ee2f242ecb7312190a82..d8f48798cb0dcb9cd1ccba0a3b1ce2d754ba4c17 100644 (file)
@@ -82,7 +82,7 @@ static void* thread_func(void *ptr) {
 
                 log_notice("Acquired loop device %s, will mount on %s", loop->node, mounted);
 
-                r = dissect_loop_device(loop, NULL, NULL, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_ADD_PARTITION_DEVICES|DISSECT_IMAGE_PIN_PARTITION_DEVICES, &dissected);
+                r = dissect_loop_device(loop, NULL, NULL, NULL, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_ADD_PARTITION_DEVICES|DISSECT_IMAGE_PIN_PARTITION_DEVICES, &dissected);
                 if (r < 0)
                         log_error_errno(r, "Failed dissect loopback device %s: %m", loop->node);
                 assert_se(r >= 0);
@@ -213,7 +213,7 @@ static int run(int argc, char *argv[]) {
         sfdisk = NULL;
 
 #if HAVE_BLKID
-        assert_se(dissect_image_file(p, NULL, NULL, 0, &dissected) >= 0);
+        assert_se(dissect_image_file(p, NULL, NULL, NULL, 0, &dissected) >= 0);
         verify_dissected_image(dissected);
         dissected = dissected_image_unref(dissected);
 #endif
@@ -231,7 +231,7 @@ static int run(int argc, char *argv[]) {
         assert_se(loop_device_make(fd, O_RDWR, 0, UINT64_MAX, 0, LO_FLAGS_PARTSCAN, LOCK_EX, &loop) >= 0);
 
 #if HAVE_BLKID
-        assert_se(dissect_loop_device(loop, NULL, NULL, DISSECT_IMAGE_ADD_PARTITION_DEVICES|DISSECT_IMAGE_PIN_PARTITION_DEVICES, &dissected) >= 0);
+        assert_se(dissect_loop_device(loop, NULL, NULL, NULL, DISSECT_IMAGE_ADD_PARTITION_DEVICES|DISSECT_IMAGE_PIN_PARTITION_DEVICES, &dissected) >= 0);
         verify_dissected_image(dissected);
 
         FOREACH_STRING(fs, "vfat", "ext4") {
@@ -267,12 +267,12 @@ static int run(int argc, char *argv[]) {
 
         /* Try to read once, without pinning or adding partitions, i.e. by only accessing the whole block
          * device. */
-        assert_se(dissect_loop_device(loop, NULL, NULL, 0, &dissected) >= 0);
+        assert_se(dissect_loop_device(loop, NULL, NULL, NULL, 0, &dissected) >= 0);
         verify_dissected_image_harder(dissected);
         dissected = dissected_image_unref(dissected);
 
         /* Now go via the loopback device after all, but this time add/pin, because now we want to mount it. */
-        assert_se(dissect_loop_device(loop, NULL, NULL, DISSECT_IMAGE_ADD_PARTITION_DEVICES|DISSECT_IMAGE_PIN_PARTITION_DEVICES, &dissected) >= 0);
+        assert_se(dissect_loop_device(loop, NULL, NULL, NULL, DISSECT_IMAGE_ADD_PARTITION_DEVICES|DISSECT_IMAGE_PIN_PARTITION_DEVICES, &dissected) >= 0);
         verify_dissected_image_harder(dissected);
 
         assert_se(mkdtemp_malloc(NULL, &mounted) >= 0);
index 72155127c1e90563378ee29a187d2cefe10f1c32..82be09dd6a6fe3db46f67d7a83eba8ffc38b753c 100644 (file)
@@ -176,6 +176,7 @@ TEST(protect_kernel_logs) {
                 assert_se(fd > 0);
 
                 r = setup_namespace(NULL,
+                                    NULL,
                                     NULL,
                                     NULL,
                                     &ns_info,
@@ -193,6 +194,7 @@ TEST(protect_kernel_logs) {
                                     NULL,
                                     NULL,
                                     NULL,
+                                    NULL,
                                     0,
                                     NULL,
                                     0,
@@ -208,6 +210,7 @@ TEST(protect_kernel_logs) {
                                     NULL,
                                     NULL,
                                     NULL,
+                                    NULL,
                                     NULL);
                 assert_se(r == 0);
 
index 7eb29d109d11ee28dc37a25a13543fe2de53bf6f..485069670b446516f7bc5eb9660591247f7da3c8 100644 (file)
@@ -77,6 +77,7 @@ int main(int argc, char *argv[]) {
                 log_info("Not chrooted");
 
         r = setup_namespace(root_directory,
+                            NULL,
                             NULL,
                             NULL,
                             &ns_info,
@@ -91,6 +92,7 @@ int main(int argc, char *argv[]) {
                             &(TemporaryFileSystem) { .path = (char*) "/var", .options = (char*) "ro" }, 1,
                             NULL,
                             0,
+                            NULL,
                             tmp_dir,
                             var_tmp_dir,
                             NULL,
@@ -110,6 +112,7 @@ int main(int argc, char *argv[]) {
                             NULL,
                             NULL,
                             NULL,
+                            NULL,
                             NULL);
         if (r < 0) {
                 log_error_errno(r, "Failed to set up namespace: %m");
index 6cd76e8df844af9503b87d8977ef83fa9fd17603..fdabd7d2c56597b9e1a07acaec7154e9ea6854e9 100644 (file)
@@ -206,6 +206,7 @@ static char **arg_exclude_prefixes = NULL;
 static char *arg_root = NULL;
 static char *arg_image = NULL;
 static char *arg_replace = NULL;
+static ImagePolicy *arg_image_policy = NULL;
 
 #define MAX_DEPTH 256
 
@@ -219,6 +220,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_include_prefixes, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_exclude_prefixes, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
 
 static const char *const creation_mode_verb_table[_CREATION_MODE_MAX] = {
         [CREATION_NORMAL]   = "Created",
@@ -3699,6 +3701,7 @@ static int help(void) {
                "  -E                        Ignore rules prefixed with /dev, /proc, /run, /sys\n"
                "     --root=PATH            Operate on an alternate filesystem root\n"
                "     --image=PATH           Operate on disk image as filesystem root\n"
+               "     --image-policy=POLICY  Specify disk image dissection policy\n"
                "     --replace=PATH         Treat arguments as replacement for PATH\n"
                "     --no-pager             Do not pipe output into a pager\n"
                "\nSee the %s for details.\n",
@@ -3726,6 +3729,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_IMAGE,
                 ARG_REPLACE,
                 ARG_NO_PAGER,
+                ARG_IMAGE_POLICY,
         };
 
         static const struct option options[] = {
@@ -3743,6 +3747,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "image",          required_argument,   NULL, ARG_IMAGE          },
                 { "replace",        required_argument,   NULL, ARG_REPLACE        },
                 { "no-pager",       no_argument,         NULL, ARG_NO_PAGER       },
+                { "image-policy",   required_argument,   NULL, ARG_IMAGE_POLICY   },
                 {}
         };
 
@@ -3833,6 +3838,17 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_pager_flags |= PAGER_DISABLE;
                         break;
 
+                case ARG_IMAGE_POLICY: {
+                        _cleanup_(image_policy_freep) ImagePolicy *p = NULL;
+
+                        r = image_policy_from_string(optarg, &p);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse image policy: %s", optarg);
+
+                        image_policy_free(arg_image_policy);
+                        arg_image_policy = TAKE_PTR(p);
+                        break;
+                }
                 case '?':
                         return -EINVAL;
 
@@ -4153,6 +4169,7 @@ static int run(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
+                                arg_image_policy,
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_REQUIRE_ROOT |
                                 DISSECT_IMAGE_VALIDATE_OS |