From a92a9efdc0ea632e4f7856038ea8ad5ac16546bd Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Tue, 20 Jan 2026 22:41:40 +0100 Subject: [PATCH] mountfsd: Add relaxExtensionReleaseChecks We currently pass this around as a mount option in pid1, which means privileges are required by mountfsd to mount images that make use of it. Add an explicit argument for it in varlink instead and remove it client side from the mount options to remove the need for privileges. --- src/mountfsd/mountwork.c | 27 ++++++++++--------- src/shared/dissect-image.c | 23 +++++++++++++++- .../varlink-io.systemd.MountFileSystem.c | 2 ++ 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/mountfsd/mountwork.c b/src/mountfsd/mountwork.c index bd5d7a197fc..d196c081b46 100644 --- a/src/mountfsd/mountwork.c +++ b/src/mountfsd/mountwork.c @@ -133,6 +133,7 @@ typedef struct MountImageParameters { char *password; ImagePolicy *image_policy; MountOptions *options; + bool relax_extension_release_check; bool verity_sharing; struct iovec verity_root_hash; struct iovec verity_root_hash_sig; @@ -369,17 +370,18 @@ static int vl_method_mount_image( void *userdata) { static const sd_json_dispatch_field dispatch_table[] = { - { "imageFileDescriptor", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint, offsetof(MountImageParameters, image_fd_idx), SD_JSON_MANDATORY }, - { "userNamespaceFileDescriptor", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint, offsetof(MountImageParameters, userns_fd_idx), 0 }, - { "readOnly", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_tristate, offsetof(MountImageParameters, read_only), 0 }, - { "growFileSystems", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_tristate, offsetof(MountImageParameters, growfs), 0 }, - { "password", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(MountImageParameters, password), 0 }, - { "imagePolicy", SD_JSON_VARIANT_STRING, json_dispatch_image_policy, offsetof(MountImageParameters, image_policy), 0 }, - { "mountOptions", SD_JSON_VARIANT_OBJECT, json_dispatch_image_options, offsetof(MountImageParameters, options), 0 }, - { "veritySharing", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(MountImageParameters, verity_sharing), 0 }, - { "verityDataFileDescriptor", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint, offsetof(MountImageParameters, verity_data_fd_idx), 0 }, - { "verityRootHash", SD_JSON_VARIANT_STRING, json_dispatch_unhex_iovec, offsetof(MountImageParameters, verity_root_hash), 0 }, - { "verityRootHashSignature", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(MountImageParameters, verity_root_hash_sig), 0 }, + { "imageFileDescriptor", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint, offsetof(MountImageParameters, image_fd_idx), SD_JSON_MANDATORY }, + { "userNamespaceFileDescriptor", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint, offsetof(MountImageParameters, userns_fd_idx), 0 }, + { "readOnly", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_tristate, offsetof(MountImageParameters, read_only), 0 }, + { "growFileSystems", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_tristate, offsetof(MountImageParameters, growfs), 0 }, + { "password", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(MountImageParameters, password), 0 }, + { "imagePolicy", SD_JSON_VARIANT_STRING, json_dispatch_image_policy, offsetof(MountImageParameters, image_policy), 0 }, + { "mountOptions", SD_JSON_VARIANT_OBJECT, json_dispatch_image_options, offsetof(MountImageParameters, options), 0 }, + { "relaxExtensionReleaseChecks", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(MountImageParameters, relax_extension_release_check), 0 }, + { "veritySharing", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(MountImageParameters, verity_sharing), 0 }, + { "verityDataFileDescriptor", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint, offsetof(MountImageParameters, verity_data_fd_idx), 0 }, + { "verityRootHash", SD_JSON_VARIANT_STRING, json_dispatch_unhex_iovec, offsetof(MountImageParameters, verity_root_hash), 0 }, + { "verityRootHashSignature", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(MountImageParameters, verity_root_hash_sig), 0 }, VARLINK_DISPATCH_POLKIT_FIELD, {} }; @@ -538,7 +540,8 @@ static int vl_method_mount_image( /* Maybe the image is a bare filesystem. Note that this requires privileges, as it is * classified by the policy as an 'unprotected' image and will be refused otherwise. */ DISSECT_IMAGE_NO_PARTITION_TABLE | - DISSECT_IMAGE_ALLOW_USERSPACE_VERITY; + DISSECT_IMAGE_ALLOW_USERSPACE_VERITY | + (p.relax_extension_release_check ? DISSECT_IMAGE_RELAX_EXTENSION_CHECK : 0); /* Let's see if we have acquired the privilege to mount untrusted images already */ bool polkit_have_untrusted_action = diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 667363cce7e..422f2b42bb7 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -40,6 +40,7 @@ #include "fileio.h" #include "format-util.h" #include "fsck-util.h" +#include "fstab-util.h" #include "gpt.h" #include "hash-funcs.h" #include "hexdecoct.h" @@ -5185,13 +5186,32 @@ int mountfsd_mount_image_fd( _cleanup_(sd_json_variant_unrefp) sd_json_variant *mount_options = NULL; for (PartitionDesignator i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { + _cleanup_free_ char *filtered = NULL; + const char *o = mount_options_from_designator(options, i); if (!o) continue; + /* We communicate relaxExtensionReleaseCheck separately via the varlink API, so filter it out + * from the mount options we pass to mountfsd. */ + if (IN_SET(i, PARTITION_ROOT, PARTITION_USR)) { + r = fstab_filter_options( + o, + "x-systemd.relax-extension-release-check\0", + /* ret_namefound= */ NULL, + /* ret_value= */ NULL, + /* ret_values= */ NULL, + &filtered); + if (r < 0) + return log_error_errno(r, "Failed to filter mount options: %m"); + + if (isempty(filtered)) + continue; + } + r = sd_json_variant_merge_objectbo( &mount_options, - SD_JSON_BUILD_PAIR_STRING(partition_designator_to_string(i), o)); + SD_JSON_BUILD_PAIR_STRING(partition_designator_to_string(i), filtered ?: o)); if (r < 0) return log_error_errno(r, "Failed to build mount options array: %m"); } @@ -5208,6 +5228,7 @@ int mountfsd_mount_image_fd( SD_JSON_BUILD_PAIR_BOOLEAN("growFileSystems", FLAGS_SET(flags, DISSECT_IMAGE_GROWFS)), SD_JSON_BUILD_PAIR_CONDITION(!!ps, "imagePolicy", SD_JSON_BUILD_STRING(ps)), JSON_BUILD_PAIR_VARIANT_NON_NULL("mountOptions", mount_options), + SD_JSON_BUILD_PAIR_BOOLEAN("relaxExtensionReleaseChecks", mount_options_relax_extension_release_checks(options)), SD_JSON_BUILD_PAIR_BOOLEAN("veritySharing", FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE)), SD_JSON_BUILD_PAIR_CONDITION(verity_data_fd >= 0, "verityDataFileDescriptor", SD_JSON_BUILD_UNSIGNED(userns_fd >= 0 ? 2 : 1)), SD_JSON_BUILD_PAIR_CONDITION(verity && iovec_is_set(&verity->root_hash), "verityRootHash", JSON_BUILD_IOVEC_HEX(&verity->root_hash)), diff --git a/src/shared/varlink-io.systemd.MountFileSystem.c b/src/shared/varlink-io.systemd.MountFileSystem.c index 121102164a8..619a09e333b 100644 --- a/src/shared/varlink-io.systemd.MountFileSystem.c +++ b/src/shared/varlink-io.systemd.MountFileSystem.c @@ -62,6 +62,8 @@ static SD_VARLINK_DEFINE_METHOD( SD_VARLINK_DEFINE_INPUT(imagePolicy, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("The mount options to be used for the partitions of the image, keyed by the partition designator. Requires elevated privileges via polkit if specified, the polkit request details will list them in the 'mount_options' field."), SD_VARLINK_DEFINE_INPUT(mountOptions, SD_VARLINK_STRING, SD_VARLINK_MAP|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Whether to relax the extension release checks when mounting the image."), + SD_VARLINK_DEFINE_INPUT(relaxExtensionReleaseChecks, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Whether to automatically reuse already set up dm-verity devices that share the same roothash."), SD_VARLINK_DEFINE_INPUT(veritySharing, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("File descriptor of the file containing the dm-verity data, if the image is a bare filesystem rather than a DDI."), -- 2.47.3