summaryrefslogtreecommitdiffstats
path: root/src/shared
diff options
context:
space:
mode:
authorLuca Boccassi <bluca@debian.org>2024-06-04 17:00:03 +0200
committerLuca Boccassi <bluca@debian.org>2024-06-28 15:37:58 +0200
commita1a40297dbfa5bcd926d1a19320deb73c033c6f5 (patch)
tree5170b3d7b0c134d68ea823604fc5b18028ab0b80 /src/shared
parentman/varlinkctl: add `list-methods` command to synopsis and fix typo (diff)
downloadsystemd-a1a40297dbfa5bcd926d1a19320deb73c033c6f5.tar.xz
systemd-a1a40297dbfa5bcd926d1a19320deb73c033c6f5.zip
core: deduplicate identical dm-verity ExtensionImages=
It turns out OverlayFS doesn't handle gracefully when the same source is specified multiple times in lowerdir= and it fails with ELOOP: Failed to mount overlay (type overlay) on /run/systemd/mount-rootfs/opt (MS_RDONLY "lowerdir=/run/systemd/unit-extensions/1/opt:/run/systemd/unit-extensions/0/opt:/run/systemd/mount-rootfs/opt"): Too many levels of symbolic links This happens even if we mount each image in a different internal mount path, as OverlayFS will resolve it and look for the backing device, which will be the same device mapper entity, and return a hard error. This error does not appear if dm-verity is not used, so it is very confusing for users, and unnecessary. When mounting ExtensionImages, check if an image is dm-veritied, and drop duplicates if the root hashes match, to avoid this user-unfriendly hard error.
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/dissect-image.c31
-rw-r--r--src/shared/dissect-image.h2
-rw-r--r--src/shared/mount-util.c2
3 files changed, 22 insertions, 13 deletions
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index 0d23e51931..1a3ed0cf7f 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -4034,11 +4034,12 @@ int verity_dissect_and_mount(
const char *required_host_os_release_sysext_level,
const char *required_host_os_release_confext_level,
const char *required_sysext_scope,
+ VeritySettings *verity,
DissectedImage **ret_image) {
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
- _cleanup_(verity_settings_done) VeritySettings verity = VERITY_SETTINGS_DEFAULT;
+ _cleanup_(verity_settings_done) VeritySettings local_verity = VERITY_SETTINGS_DEFAULT;
DissectImageFlags dissect_image_flags;
bool relax_extension_release_check;
int r;
@@ -4050,13 +4051,19 @@ int verity_dissect_and_mount(
relax_extension_release_check = mount_options_relax_extension_release_checks(options);
- /* We might get an FD for the image, but we use the original path to look for the dm-verity files */
- r = verity_settings_load(&verity, src, NULL, NULL);
- if (r < 0)
- return log_debug_errno(r, "Failed to load root hash: %m");
+ /* We might get an FD for the image, but we use the original path to look for the dm-verity files.
+ * The caller might also give us a pre-loaded VeritySettings, in which case we just use it. It will
+ * also be extended, as dissected_image_load_verity_sig_partition() is invoked. */
+ if (!verity) {
+ r = verity_settings_load(&local_verity, src, NULL, NULL);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to load root hash: %m");
+
+ verity = &local_verity;
+ }
dissect_image_flags =
- (verity.data_path ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0) |
+ (verity->data_path ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0) |
(relax_extension_release_check ? DISSECT_IMAGE_RELAX_EXTENSION_CHECK : 0) |
DISSECT_IMAGE_ADD_PARTITION_DEVICES |
DISSECT_IMAGE_PIN_PARTITION_DEVICES |
@@ -4068,7 +4075,7 @@ int verity_dissect_and_mount(
src_fd >= 0 ? FORMAT_PROC_FD_PATH(src_fd) : src,
/* open_flags= */ -1,
/* sector_size= */ UINT32_MAX,
- verity.data_path ? 0 : LO_FLAGS_PARTSCAN,
+ verity->data_path ? 0 : LO_FLAGS_PARTSCAN,
LOCK_SH,
&loop_device);
if (r < 0)
@@ -4076,16 +4083,16 @@ int verity_dissect_and_mount(
r = dissect_loop_device(
loop_device,
- &verity,
+ verity,
options,
image_policy,
dissect_image_flags,
&dissected_image);
/* No partition table? Might be a single-filesystem image, try again */
- if (!verity.data_path && r == -ENOPKG)
+ if (!verity->data_path && r == -ENOPKG)
r = dissect_loop_device(
loop_device,
- &verity,
+ verity,
options,
image_policy,
dissect_image_flags | DISSECT_IMAGE_NO_PARTITION_TABLE,
@@ -4093,14 +4100,14 @@ int verity_dissect_and_mount(
if (r < 0)
return log_debug_errno(r, "Failed to dissect image: %m");
- r = dissected_image_load_verity_sig_partition(dissected_image, loop_device->fd, &verity);
+ r = dissected_image_load_verity_sig_partition(dissected_image, loop_device->fd, verity);
if (r < 0)
return r;
r = dissected_image_decrypt(
dissected_image,
NULL,
- &verity,
+ verity,
dissect_image_flags);
if (r < 0)
return log_debug_errno(r, "Failed to decrypt dissected image: %m");
diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h
index 02aa2d5734..2c118b97ef 100644
--- a/src/shared/dissect-image.h
+++ b/src/shared/dissect-image.h
@@ -226,7 +226,7 @@ bool dissected_image_verity_sig_ready(const DissectedImage *image, PartitionDesi
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 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_host_os_release_confext_level, const char *required_sysext_scope, DissectedImage **ret_image);
+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_host_os_release_confext_level, const char *required_sysext_scope, VeritySettings *verity, DissectedImage **ret_image);
int dissect_fstype_ok(const char *fstype);
diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c
index 4ddfb9a82a..a1f4bee77e 100644
--- a/src/shared/mount-util.c
+++ b/src/shared/mount-util.c
@@ -941,6 +941,7 @@ static int mount_in_namespace_legacy(
/* required_host_os_release_sysext_level= */ NULL,
/* required_host_os_release_confext_level= */ NULL,
/* required_sysext_scope= */ NULL,
+ /* verity= */ NULL,
/* ret_image= */ NULL);
else
r = mount_follow_verbose(LOG_DEBUG, FORMAT_PROC_FD_PATH(chased_src_fd), mount_tmp, NULL, MS_BIND, NULL);
@@ -1166,6 +1167,7 @@ static int mount_in_namespace(
/* required_host_os_release_sysext_level= */ NULL,
/* required_host_os_release_confext_level= */ NULL,
/* required_sysext_scope= */ NULL,
+ /* verity= */ NULL,
&img);
if (r < 0)
return log_debug_errno(