From: Lennart Poettering Date: Fri, 29 May 2026 10:30:19 +0000 (+0200) Subject: boot: before starting the random seed logic, let's check if the backing volume is r/o X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=14b39a0816bf0322b2b15fc22eb9d6cf56e3cbcd;p=thirdparty%2Fsystemd.git boot: before starting the random seed logic, let's check if the backing volume is r/o This is an attempt to fix #42307, but should be a good thing anyway. Related: #42307 --- diff --git a/src/boot/efi.h b/src/boot/efi.h index c518a0253ff..6f08bacb2db 100644 --- a/src/boot/efi.h +++ b/src/boot/efi.h @@ -132,6 +132,7 @@ typedef uint64_t EFI_PHYSICAL_ADDRESS; * keep the GUID definitions in line with the UEFI spec. */ #define EFI_GLOBAL_VARIABLE_GUID EFI_GLOBAL_VARIABLE #define EFI_FILE_INFO_GUID EFI_FILE_INFO_ID +#define EFI_FILE_SYSTEM_INFO_GUID EFI_FILE_SYSTEM_INFO_ID #define EFI_CUSTOM_MODE_ENABLE_GUID \ GUID_DEF(0xc076ec0c, 0x7028, 0x4399, 0xa0, 0x72, 0x71, 0xee, 0x5c, 0x44, 0x8b, 0x9f) diff --git a/src/boot/proto/file-io.h b/src/boot/proto/file-io.h index 001ad486752..f8dddd94df3 100644 --- a/src/boot/proto/file-io.h +++ b/src/boot/proto/file-io.h @@ -7,6 +7,8 @@ GUID_DEF(0x0964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) #define EFI_FILE_INFO_ID \ GUID_DEF(0x009576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) +#define EFI_FILE_SYSTEM_INFO_ID \ + GUID_DEF(0x009576e93, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) #define EFI_FILE_MODE_READ 0x0000000000000001U #define EFI_FILE_MODE_WRITE 0x0000000000000002U @@ -31,6 +33,15 @@ typedef struct { char16_t FileName[]; } EFI_FILE_INFO; +typedef struct { + uint64_t Size; + bool ReadOnly; + uint64_t VolumeSize; + uint64_t FreeSpace; + uint32_t BlockSize; + char16_t VolumeLabel[]; +} EFI_FILE_SYSTEM_INFO; + /* Some broken firmware violates the EFI spec by still advancing the readdir * position when returning EFI_BUFFER_TOO_SMALL, effectively skipping over any files when * the buffer was too small. Therefore, we always start with a buffer that should handle FAT32 diff --git a/src/boot/random-seed.c b/src/boot/random-seed.c index 4dc5a2b275a..d2ed63f0e35 100644 --- a/src/boot/random-seed.c +++ b/src/boot/random-seed.c @@ -132,6 +132,17 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) { validate_sha256(); + /* If the volume is read-only we cannot update the random seed, but if we cannot update it, then we + * really don't want to use it since it would be the same on every boot. */ + bool volume_ro; + err = get_volume_ro(root_dir, &volume_ro); + if (err != EFI_SUCCESS) + log_debug_status(err, "Failed to determine if volume is read-only, assuming not: %m"); + else if (volume_ro) { + log_debug("Volume is read-only, not updating random seed."); + return EFI_SUCCESS; + } + /* hash = LABEL || sizeof(input1) || input1 || ... || sizeof(inputN) || inputN */ sha256_init_ctx(&hash); diff --git a/src/boot/util.c b/src/boot/util.c index e0d2788c202..436716c27fb 100644 --- a/src/boot/util.c +++ b/src/boot/util.c @@ -298,6 +298,28 @@ EFI_STATUS get_file_info(EFI_FILE *handle, EFI_FILE_INFO **ret, size_t *ret_size return EFI_SUCCESS; } +EFI_STATUS get_volume_ro(EFI_FILE *handle, bool *ret) { + size_t size = offsetof(EFI_FILE_SYSTEM_INFO, VolumeLabel) + 256U * sizeof(char16_t); + _cleanup_free_ EFI_FILE_SYSTEM_INFO *fsi = NULL; + EFI_STATUS err; + + assert(handle); + assert(ret); + + fsi = xmalloc(size); + err = handle->GetInfo(handle, MAKE_GUID_PTR(EFI_FILE_SYSTEM_INFO), &size, fsi); + if (err == EFI_BUFFER_TOO_SMALL) { + free(fsi); + fsi = xmalloc(size); /* GetInfo tells us the required size, let's use that now */ + err = handle->GetInfo(handle, MAKE_GUID_PTR(EFI_FILE_SYSTEM_INFO), &size, fsi); + } + if (err != EFI_SUCCESS) + return err; + + *ret = fsi->ReadOnly; + return EFI_SUCCESS; +} + EFI_STATUS readdir( EFI_FILE *handle, EFI_FILE_INFO **buffer, diff --git a/src/boot/util.h b/src/boot/util.h index 207904d759b..1c0a0412492 100644 --- a/src/boot/util.h +++ b/src/boot/util.h @@ -168,6 +168,7 @@ typedef int (*compare_pointer_func_t)(const void *a, const void *b); void sort_pointer_array(void **array, size_t n_members, compare_pointer_func_t compare); EFI_STATUS get_file_info(EFI_FILE *handle, EFI_FILE_INFO **ret, size_t *ret_size); +EFI_STATUS get_volume_ro(EFI_FILE *handle, bool *ret); EFI_STATUS readdir(EFI_FILE *handle, EFI_FILE_INFO **buffer, size_t *buffer_size); bool is_ascii(const char16_t *f);