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
This commit is contained in:
Lennart Poettering
2026-06-01 11:01:14 +02:00
parent c0e7046c17
commit 14b39a0816
5 changed files with 46 additions and 0 deletions
+1
View File
@@ -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)
+11
View File
@@ -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
+11
View File
@@ -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);
+22
View File
@@ -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,
+1
View File
@@ -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);