diff options
author | Luca Boccassi <bluca@debian.org> | 2024-06-04 17:00:03 +0200 |
---|---|---|
committer | Luca Boccassi <bluca@debian.org> | 2024-06-28 15:37:58 +0200 |
commit | a1a40297dbfa5bcd926d1a19320deb73c033c6f5 (patch) | |
tree | 5170b3d7b0c134d68ea823604fc5b18028ab0b80 /src/shared | |
parent | man/varlinkctl: add `list-methods` command to synopsis and fix typo (diff) | |
download | systemd-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.c | 31 | ||||
-rw-r--r-- | src/shared/dissect-image.h | 2 | ||||
-rw-r--r-- | src/shared/mount-util.c | 2 |
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( |