]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
stub: check load options a little more carefully
authorThomas Mühlbacher <tmuehlbacher@posteo.net>
Thu, 16 Oct 2025 12:56:52 +0000 (14:56 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 20 Oct 2025 08:28:41 +0000 (10:28 +0200)
This can lead to booting with a completely garbled command line with characters
being interpreted as miscellaneous CJK or symbols.

According to the UEFI spec, the optional data of the load option is just a
binary data buffer.

src/boot/stub.c

index 575b4a982c6dbe2f208ca2d8b58d3651077f2a67..654913c43d8858753c2ca3e4a33188fe578e50c0 100644 (file)
@@ -257,11 +257,21 @@ static void process_arguments(
         EFI_SHELL_PARAMETERS_PROTOCOL *shell;
         if (BS->HandleProtocol(stub_image, MAKE_GUID_PTR(EFI_SHELL_PARAMETERS_PROTOCOL), (void **) &shell) != EFI_SUCCESS) {
 
-                /* We also do a superficial check whether first character of passed command line
-                 * is printable character (for compat with some Dell systems which fill in garbage?). */
-                if (loaded_image->LoadOptionsSize < sizeof(char16_t) || ((const char16_t *) loaded_image->LoadOptions)[0] <= 0x1F)
+                if (loaded_image->LoadOptionsSize < sizeof(char16_t))
                         goto nothing;
 
+                /* Superficial check to ensure the load options data looks like it might be a printable
+                 * string. Some Dell and other systems fill in binary data in UEFI entries that are generated
+                 * by the firmware. The UEFI specification allows this. See
+                 * https://uefi.org/specs/UEFI/2.10/03_Boot_Manager.html#load-options */
+                for (size_t i = 0; i < loaded_image->LoadOptionsSize / sizeof(char16_t); i++) {
+                        char16_t c = ((const char16_t *) loaded_image->LoadOptions)[i];
+                        if (c == L'\0')
+                                break;
+                        if (c <= 0x1F)
+                                goto nothing;
+                }
+
                 /* Not running from EFI shell, use entire LoadOptions. Note that LoadOptions is a void*, so
                  * it could actually be anything! */
                 char16_t *c = xstrndup16(loaded_image->LoadOptions, loaded_image->LoadOptionsSize / sizeof(char16_t));