From aad0d11e7c6f1f7dcc7b00173140c74b8abf88cc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 9 Oct 2025 11:01:48 +0200 Subject: [PATCH] dissect-image: when autoprobing insist on vfat for XBOOTLDR Let's reduce our attack surface by insisting that XBOOTLDR is vfat when auto-probing, just like we do for the ESP. Given neither can realistically be integrity protected (because firmware needs to access them) let's insist on a vfat which has a much smaller attack surface, and one we have to accept (for now) anyway, given that the ESP must be VFAT. This only applies to auto-probing of course. If people mount things explicitly via fstab none of this matters. But we really shouldn't automount a btrfs/xfs/ext4 partition as XBOOTLDR just because it looks like one, as that would really defeat our otherwise possibly very strict image policies. This also introduces a new env var $SYSTEMD_DISSECT_FSTYPE_ environment variable that may override this hardcoding. This is in particular useful in our testcases, since various actually do use ext4 as XBOOTLDR case. The tests are updated to make use of the new env var, both as a mechanism to test this and to keep the tests working. --- docs/ENVIRONMENT.md | 9 ++++++++ src/shared/dissect-image.c | 24 ++++++++++++++++++++-- test/units/TEST-87-AUX-UTILS-VM.bootctl.sh | 4 ++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index 3a35c1b9aa0..6eda26c7d68 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -529,6 +529,15 @@ disk images with `--image=` or similar: systems that may be mounted for automatically dissected disk images. If not specified defaults to something like: `ext4:btrfs:xfs:vfat:erofs:squashfs` +* `$SYSTEMD_DISSECT_FSTYPE_=` – overrides the file system time to + use when mounting the partition of the indicated designator. The + `` string shall be one of `ROOT`, `USR`, `HOME`, `SRV`, `ESP`, + `XBOOTLDR`, `TMP`, `VAR` as per the [Discoverable Partitions + Specification](https://uapi-group.org/specifications/specs/discoverable_partitions_specification/). If + unspecified the image dissection logic will automatically probe the file + system type (subject to `$SYSTEMD_DISSECT_FILE_SYSTEMS`, see above), except + for ESP and XBOOTLDR where the file system type is set to VFAT. + * `$SYSTEMD_LOOP_DIRECT_IO` – takes a boolean, which controls whether to enable `LO_FLAGS_DIRECT_IO` (i.e. direct IO + asynchronous IO) on loopback block devices when opening them. Defaults to on, set this to "0" to disable this diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index e44c307bbf1..4cb84116fae 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -117,6 +117,17 @@ int dissect_fstype_ok(const char *fstype) { return false; } +static const char *getenv_fstype(PartitionDesignator d) { + + if (d < 0 || + partition_designator_is_verity(d) || + d == PARTITION_SWAP) + return NULL; + + char *v = strjoina("SYSTEMD_DISSECT_FSTYPE_", partition_designator_to_string(d)); + return secure_getenv(ascii_strupper(v)); +} + int probe_sector_size(int fd, uint32_t *ret) { /* Disk images might be for 512B or for 4096 sector sizes, let's try to auto-detect that by searching @@ -1032,7 +1043,7 @@ static int dissect_image( } if (is_gpt) { - const char *fstype = NULL, *label; + const char *label; sd_id128_t type_id, id; GptPartitionType type; bool rw = true, growfs = false; @@ -1085,6 +1096,8 @@ static int dissect_image( continue; } + const char *fstype = getenv_fstype(type.designator); + if (IN_SET(type.designator, PARTITION_HOME, PARTITION_SRV, @@ -1097,6 +1110,11 @@ static int dissect_image( rw = !(pflags & SD_GPT_FLAG_READ_ONLY); growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS); + /* XBOOTLDR cannot be integrity protected (since firmware needs to access + * it), hence be restrictive with the fs choice when dissecting. */ + if (type.designator == PARTITION_XBOOTLDR && !fstype) + fstype = "vfat"; + } else if (type.designator == PARTITION_ESP) { if (FLAGS_SET(pflags, SD_GPT_FLAG_NO_BLOCK_IO_PROTOCOL)) { @@ -1104,7 +1122,9 @@ static int dissect_image( continue; } - fstype = "vfat"; + /* Effectively the ESP has to be VFAT, let's enforce this */ + if (!fstype) + fstype = "vfat"; } else if (type.designator == PARTITION_ROOT) { diff --git a/test/units/TEST-87-AUX-UTILS-VM.bootctl.sh b/test/units/TEST-87-AUX-UTILS-VM.bootctl.sh index c6b4ea06552..c8e3da09cf6 100755 --- a/test/units/TEST-87-AUX-UTILS-VM.bootctl.sh +++ b/test/units/TEST-87-AUX-UTILS-VM.bootctl.sh @@ -158,6 +158,8 @@ EOF umount "${IMAGE_DIR}/root" + export SYSTEMD_DISSECT_FSTYPE_XBOOTLDR=ext4 + assert_eq "$(bootctl --image "${IMAGE_DIR}/image" --print-esp-path)" "/run/systemd/mount-rootfs/efi" assert_eq "$(bootctl --image "${IMAGE_DIR}/image" --print-esp-path --esp-path=/efi)" "/run/systemd/mount-rootfs/efi" assert_eq "$(bootctl --image "${IMAGE_DIR}/image" --print-boot-path)" "/run/systemd/mount-rootfs/boot" @@ -167,6 +169,8 @@ EOF bootctl --image "${IMAGE_DIR}/image" --print-root-device || : basic_tests --image "${IMAGE_DIR}/image" + + unset SYSTEMD_DISSECT_FSTYPE_XBOOTLDR } cleanup_raid() ( -- 2.47.3