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_<DESIGNATOR>
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.
This commit is contained in:
Lennart Poettering
2025-10-09 11:01:48 +02:00
parent 2fbfbfc5fa
commit aad0d11e7c
3 changed files with 35 additions and 2 deletions

View File

@@ -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_<DESIGNATOR>=` overrides the file system time to
use when mounting the partition of the indicated designator. The
`<DESIGNATOR>` 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

View File

@@ -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) {

View File

@@ -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() (