]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
boot: before starting the random seed logic, let's check if the backing volume is r/o 42379/head
authorLennart Poettering <lennart@amutable.com>
Fri, 29 May 2026 10:30:19 +0000 (12:30 +0200)
committerLennart Poettering <lennart@amutable.com>
Mon, 1 Jun 2026 09:01:14 +0000 (11:01 +0200)
This is an attempt to fix #42307, but should be a good thing anyway.

Related: #42307

src/boot/efi.h
src/boot/proto/file-io.h
src/boot/random-seed.c
src/boot/util.c
src/boot/util.h

index c518a0253ff8dd9e3349ea94ad2a57c2f209813b..6f08bacb2db623899e65c068ce5a895dd5d56659 100644 (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)
index 001ad48675296926831a2a7a59844879ac025c4c..f8dddd94df34cab7ee10b66150368aa8cd444d8c 100644 (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
index 4dc5a2b275a9d8b4cd92feccf9f90b7bfc8fc973..d2ed63f0e359ed7a412270d6332766fbbe869599 100644 (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);
 
index e0d2788c202330bae1a6adca8b0f0801d432d94e..436716c27fb38207a7ca373bdfd8aa6b7614e51f 100644 (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,
index 207904d759b7a7aa9950490e1f358dd4cc5ede77..1c0a0412492a6b424a1e5150ea9517c056d929e7 100644 (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);