summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2022-11-30 18:43:18 +0100
committerLennart Poettering <lennart@poettering.net>2023-04-05 20:45:30 +0200
commit84be0c710d9d562f6d2cf986cc2a8ff4c98a138b (patch)
treeb374ebea1d604154fa0e004560f428c7f111352c
parentd452335aa47fb1f1b11dc75bc462697431e64af3 (diff)
downloadsystemd-84be0c710d9d562f6d2cf986cc2a8ff4c98a138b.tar.gz
tree-wide: hook up image dissection policy logic everywhere
-rw-r--r--man/org.freedesktop.systemd1.xml72
-rw-r--r--src/analyze/analyze.c18
-rw-r--r--src/analyze/analyze.h1
-rw-r--r--src/boot/bootctl.c19
-rw-r--r--src/boot/bootctl.h2
-rw-r--r--src/core/dbus-execute.c61
-rw-r--r--src/core/dbus-service.c24
-rw-r--r--src/core/execute.c71
-rw-r--r--src/core/execute.h2
-rw-r--r--src/core/load-fragment-gperf.gperf.in3
-rw-r--r--src/core/load-fragment.c39
-rw-r--r--src/core/load-fragment.h1
-rw-r--r--src/core/namespace.c36
-rw-r--r--src/core/namespace.h3
-rw-r--r--src/coredump/coredumpctl.c54
-rw-r--r--src/dissect/dissect.c20
-rw-r--r--src/firstboot/firstboot.c19
-rw-r--r--src/gpt-auto-generator/gpt-auto-generator.c22
-rw-r--r--src/journal/journalctl.c20
-rw-r--r--src/machine-id-setup/machine-id-setup-main.c41
-rw-r--r--src/machine/image-dbus.c8
-rw-r--r--src/nspawn/nspawn.c20
-rw-r--r--src/partition/repart.c20
-rw-r--r--src/portable/portable.c30
-rw-r--r--src/portable/portable.h5
-rw-r--r--src/portable/portabled-image-bus.c5
-rw-r--r--src/shared/bus-unit-util.c5
-rw-r--r--src/shared/discover-image.c6
-rw-r--r--src/shared/discover-image.h3
-rw-r--r--src/shared/dissect-image.c22
-rw-r--r--src/shared/dissect-image.h19
-rw-r--r--src/shared/mount-util.c10
-rw-r--r--src/shared/mount-util.h2
-rw-r--r--src/sysext/sysext.c36
-rw-r--r--src/systemctl/systemctl.c21
-rw-r--r--src/systemctl/systemctl.h2
-rw-r--r--src/sysupdate/sysupdate.c24
-rw-r--r--src/sysusers/sysusers.c35
-rw-r--r--src/test/test-loop-block.c10
-rw-r--r--src/test/test-namespace.c3
-rw-r--r--src/test/test-ns.c3
-rw-r--r--src/tmpfiles/tmpfiles.c17
42 files changed, 691 insertions, 143 deletions
diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml
index 50680e6b37..05c8b3770e 100644
--- a/man/org.freedesktop.systemd1.xml
+++ b/man/org.freedesktop.systemd1.xml
@@ -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"/>
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 0246da4b45..8bc533b20d 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -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,
diff --git a/src/analyze/analyze.h b/src/analyze/analyze.h
index 2f623e3201..84575cd9a9 100644
--- a/src/analyze/analyze.h
+++ b/src/analyze/analyze.h
@@ -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);
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index 82c7e498ba..b9d034d550 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -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,
diff --git a/src/boot/bootctl.h b/src/boot/bootctl.h
index c87d43694f..dd98b959c2 100644
--- a/src/boot/bootctl.h
+++ b/src/boot/bootctl.h
@@ -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 */
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index d5ef796e52..d77842bdab 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -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;
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
index 0f6e315233..6041a37e56 100644
--- a/src/core/dbus-service.c
+++ b/src/core/dbus-service.c
@@ -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);
diff --git a/src/core/execute.c b/src/core/execute.c
index aff07e7b74..cd11683407 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -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) {
diff --git a/src/core/execute.h b/src/core/execute.h
index 254a1ee2d1..123fc1ec60 100644
--- a/src/core/execute.h
+++ b/src/core/execute.h
@@ -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) {
diff --git a/src/core/load-fragment-gperf.gperf.in b/src/core/load-fragment-gperf.gperf.in
index 50ff57a9f8..f35c743655 100644
--- a/src/core/load-fragment-gperf.gperf.in
+++ b/src/core/load-fragment-gperf.gperf.in
@@ -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)
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 533c09f72e..99d40b7490 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -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,
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index 91dc917458..ab682ee23e 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -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);
diff --git a/src/core/namespace.c b/src/core/namespace.c
index 8b141a2484..2668bca1bb 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -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;
diff --git a/src/core/namespace.h b/src/core/namespace.h
index 1cd4fdd921..39b510f41d 100644
--- a/src/core/namespace.h
+++ b/src/core/namespace.h
@@ -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,
diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c
index 60da536d4e..076b35f098 100644
--- a/src/coredump/coredumpctl.c
+++ b/src/coredump/coredumpctl.c
@@ -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 |
diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c
index ff00c4f567..b3f20e193e 100644
--- a/src/dissect/dissect.c
+++ b/src/dissect/dissect.c
@@ -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)
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 3e68ed1cb0..54c72eceaf 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -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 |
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index 9ccd78af65..09c63a31b2 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -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;
}
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 97e9c1aafc..abacbb0306 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -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 |
diff --git a/src/machine-id-setup/machine-id-setup-main.c b/src/machine-id-setup/machine-id-setup-main.c
index 223164ea1b..c5b22d5d76 100644
--- a/src/machine-id-setup/machine-id-setup-main.c
+++ b/src/machine-id-setup/machine-id-setup-main.c
@@ -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 |
diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c
index bf65eecfdd..336b42b7e5 100644
--- a/src/machine/image-dbus.c
+++ b/src/machine/image-dbus.c
@@ -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");
}
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 8abb016791..6b74a3df13 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -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) {
diff --git a/src/partition/repart.c b/src/partition/repart.c
index e4ae8a2c89..bc3bfa15fb 100644
--- a/src/partition/repart.c
+++ b/src/partition/repart.c
@@ -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 |
diff --git a/src/portable/portable.c b/src/portable/portable.c
index adfd846bab..23420abab2 100644
--- a/src/portable/portable.c
+++ b/src/portable/portable.c
@@ -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,
diff --git a/src/portable/portable.h b/src/portable/portable.h
index 1a33f30944..c61d65fed3 100644
--- a/src/portable/portable.h
+++ b/src/portable/portable.h
@@ -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);
diff --git a/src/portable/portabled-image-bus.c b/src/portable/portabled-image-bus.c
index 6c4cb6ec9d..262518d15c 100644
--- a/src/portable/portabled-image-bus.c
+++ b/src/portable/portabled-image-bus.c
@@ -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,
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
index 6966cfd838..81eef8b058 100644
--- a/src/shared/bus-unit-util.c
+++ b/src/shared/bus-unit-util.c
@@ -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",
diff --git a/src/shared/discover-image.c b/src/shared/discover-image.c
index eed0a5629e..86ff5d6d93 100644
--- a/src/shared/discover-image.c
+++ b/src/shared/discover-image.c
@@ -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 |
diff --git a/src/shared/discover-image.h b/src/shared/discover-image.h
index 3c6928619c..c423132a62 100644
--- a/src/shared/discover-image.h
+++ b/src/shared/discover-image.h
@@ -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);
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index 6000af0ce0..83b0581ff1 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -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)
diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h
index 2e741e8267..3af0c439bc 100644
--- a/src/shared/dissect-image.h
+++ b/src/shared/dissect-image.h
@@ -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);
diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c
index 1eac51b81e..edf01fe092 100644
--- a/src/shared/mount-util.c
+++ b/src/shared/mount-util.c
@@ -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) {
diff --git a/src/shared/mount-util.h b/src/shared/mount-util.h
index 84ea4b6392..f52687828a 100644
--- a/src/shared/mount-util.h
+++ b/src/shared/mount-util.h
@@ -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);
diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c
index 5632b72f3d..ce076f665a 100644
--- a/src/sysext/sysext.c
+++ b/src/sysext/sysext.c
@@ -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;
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 1a5beabc72..df4cf68435 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -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 |
diff --git a/src/systemctl/systemctl.h b/src/systemctl/systemctl.h
index 8c96ee0b4f..03645624ee 100644
--- a/src/systemctl/systemctl.h
+++ b/src/systemctl/systemctl.h
@@ -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";
diff --git a/src/sysupdate/sysupdate.c b/src/sysupdate/sysupdate.c
index 6cb09dae50..f62e193056 100644
--- a/src/sysupdate/sysupdate.c
+++ b/src/sysupdate/sysupdate.c
@@ -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;
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index f9f694bd54..a2d62121e0 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -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 |
diff --git a/src/test/test-loop-block.c b/src/test/test-loop-block.c
index 97c2f66ac9..d8f48798cb 100644
--- a/src/test/test-loop-block.c
+++ b/src/test/test-loop-block.c
@@ -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);
diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c
index 72155127c1..82be09dd6a 100644
--- a/src/test/test-namespace.c
+++ b/src/test/test-namespace.c
@@ -178,6 +178,7 @@ TEST(protect_kernel_logs) {
r = setup_namespace(NULL,
NULL,
NULL,
+ NULL,
&ns_info,
NULL,
NULL,
@@ -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);
diff --git a/src/test/test-ns.c b/src/test/test-ns.c
index 7eb29d109d..485069670b 100644
--- a/src/test/test-ns.c
+++ b/src/test/test-ns.c
@@ -79,6 +79,7 @@ int main(int argc, char *argv[]) {
r = setup_namespace(root_directory,
NULL,
NULL,
+ NULL,
&ns_info,
(char **) writable,
(char **) readonly,
@@ -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");
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 6cd76e8df8..fdabd7d2c5 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -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 |