]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
stub: Correctly handle multi node file paths
authorJan Janssen <medhefgo@web.de>
Tue, 11 Oct 2022 09:19:04 +0000 (11:19 +0200)
committerJan Janssen <medhefgo@web.de>
Wed, 12 Oct 2022 11:19:34 +0000 (13:19 +0200)
Fixes: #24955
src/boot/efi/cpio.c

index 6497b05455d67f6e6e3ef1a716c74c6cd76ae976..1e814525bd61c130b0f97306749fe4f3ac0da51e 100644 (file)
@@ -341,6 +341,45 @@ static EFI_STATUS measure_cpio(
         return EFI_SUCCESS;
 }
 
+char16_t *get_dropin_dir(const EFI_DEVICE_PATH *file_path) {
+        if (!file_path)
+                return NULL;
+
+        /* A device path is allowed to have more than one file path node. If that is the case they are
+         * supposed to be concatenated. Unfortunately, the device path to text protocol simply converts the
+         * nodes individually and then combines those with the usual '/' for device path nodes. But this does
+         * not create a legal EFI file path that the file protocol can use. */
+
+        /* Make sure we really only got file paths. */
+        for (const EFI_DEVICE_PATH *node = file_path; !IsDevicePathEnd(node); node = NextDevicePathNode(node))
+                if (DevicePathType(node) != MEDIA_DEVICE_PATH || DevicePathSubType(node) != MEDIA_FILEPATH_DP)
+                        return NULL;
+
+        _cleanup_free_ char16_t *file_path_str = NULL;
+        if (device_path_to_str(file_path, &file_path_str) != EFI_SUCCESS)
+                return NULL;
+
+        for (char16_t *i = file_path_str, *fixed = i;; i++) {
+                if (*i == '\0') {
+                        *fixed = '\0';
+                        break;
+                }
+
+                /* Fix device path node separator. */
+                if (*i == '/')
+                        *i = '\\';
+
+                /* Double '\' is not allowed in EFI file paths. */
+                if (fixed != file_path_str && fixed[-1] == '\\' && *i == '\\')
+                        continue;
+
+                *fixed = *i;
+                fixed++;
+        }
+
+        return xpool_print(u"%s.extra.d", file_path_str);
+}
+
 EFI_STATUS pack_cpio(
                 EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
                 const char16_t *dropin_dir,
@@ -382,13 +421,8 @@ EFI_STATUS pack_cpio(
                 return log_error_status_stall(
                                 err, L"Unable to open root directory: %r", err);
 
-        if (!dropin_dir) {
-                _cleanup_free_ char16_t *file_path = NULL;
-                err = device_path_to_str(loaded_image->FilePath, &file_path);
-                if (err != EFI_SUCCESS)
-                        goto nothing;
-                dropin_dir = rel_dropin_dir = xpool_print(u"%s.extra.d", file_path);
-        }
+        if (!dropin_dir)
+                dropin_dir = rel_dropin_dir = get_dropin_dir(loaded_image->FilePath);
 
         err = open_directory(root, dropin_dir, &extra_dir);
         if (err == EFI_NOT_FOUND)