efivarfs: Request at most 512 bytes for variable names
authorTim Schumacher <timschumi@gmx.de>
Fri, 26 Jan 2024 16:25:23 +0000 (17:25 +0100)
committerArd Biesheuvel <ardb@kernel.org>
Sun, 25 Feb 2024 08:42:24 +0000 (09:42 +0100)
Work around a quirk in a few old (2011-ish) UEFI implementations, where
a call to `GetNextVariableName` with a buffer size larger than 512 bytes
will always return EFI_INVALID_PARAMETER.

There is some lore around EFI variable names being up to 1024 bytes in
size, but this has no basis in the UEFI specification, and the upper
bounds are typically platform specific, and apply to the entire variable
(name plus payload).

Given that Linux does not permit creating files with names longer than
NAME_MAX (255) bytes, 512 bytes (== 256 UTF-16 characters) is a
reasonable limit.

Cc: <stable@vger.kernel.org> # 6.1+
Signed-off-by: Tim Schumacher <timschumi@gmx.de>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
fs/efivarfs/vars.c

index 114ff0fd4e55732e2ebe0cdc8b20d82436571abf..2ad377818d0f30544a220c5705518c073f5dddd7 100644 (file)
@@ -373,7 +373,7 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *,
                            struct list_head *),
                void *data, bool duplicates, struct list_head *head)
 {
-       unsigned long variable_name_size = 1024;
+       unsigned long variable_name_size = 512;
        efi_char16_t *variable_name;
        efi_status_t status;
        efi_guid_t vendor_guid;
@@ -390,12 +390,13 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *,
                goto free;
 
        /*
-        * Per EFI spec, the maximum storage allocated for both
-        * the variable name and variable data is 1024 bytes.
+        * A small set of old UEFI implementations reject sizes
+        * above a certain threshold, the lowest seen in the wild
+        * is 512.
         */
 
        do {
-               variable_name_size = 1024;
+               variable_name_size = 512;
 
                status = efivar_get_next_variable(&variable_name_size,
                                                  variable_name,
@@ -432,9 +433,13 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *,
                        break;
                case EFI_NOT_FOUND:
                        break;
+               case EFI_BUFFER_TOO_SMALL:
+                       pr_warn("efivars: Variable name size exceeds maximum (%lu > 512)\n",
+                               variable_name_size);
+                       status = EFI_NOT_FOUND;
+                       break;
                default:
-                       printk(KERN_WARNING "efivars: get_next_variable: status=%lx\n",
-                               status);
+                       pr_warn("efivars: get_next_variable: status=%lx\n", status);
                        status = EFI_NOT_FOUND;
                        break;
                }