diff options
author | Marta Rybczynska <rybczynska@gmail.com> | 2022-02-18 11:05:13 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2022-03-02 00:21:36 +0000 |
commit | 763007dff131cc8dc6a7d4dec533e37dad282bd7 (patch) | |
tree | c1e0ec905300b78154782df682fa17448291bf28 /meta/recipes-bsp | |
parent | ee33ef82427d9144258fac3423f4b199132d542b (diff) | |
download | poky-763007dff131cc8dc6a7d4dec533e37dad282bd7.tar.gz |
grub: add a fix for malformed device path handling
This change fixes the malformed device paths in EFI handling.
Device paths of length 4 or shorter could cause different
kinds of unexpected behaviours.
This patch is NOT a part of [1], but is a dependency of one
of the patches included in the series.
[1] https://lists.gnu.org/archive/html/grub-devel/2021-03/msg00007.html
(From OE-Core rev: 7f08d97fb6a0ff9c779f788df150b54de8af2708)
Signed-off-by: Marta Rybczynska <marta.rybczynska@huawei.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-bsp')
-rw-r--r-- | meta/recipes-bsp/grub/files/0005-efi-Fix-some-malformed-device-path-arithmetic-errors.patch | 235 | ||||
-rw-r--r-- | meta/recipes-bsp/grub/grub2.inc | 1 |
2 files changed, 236 insertions, 0 deletions
diff --git a/meta/recipes-bsp/grub/files/0005-efi-Fix-some-malformed-device-path-arithmetic-errors.patch b/meta/recipes-bsp/grub/files/0005-efi-Fix-some-malformed-device-path-arithmetic-errors.patch new file mode 100644 index 0000000000..04748befc8 --- /dev/null +++ b/meta/recipes-bsp/grub/files/0005-efi-Fix-some-malformed-device-path-arithmetic-errors.patch | |||
@@ -0,0 +1,235 @@ | |||
1 | From 16a4d739b19f8680cf93a3c8fa0ae9fc1b1c310b Mon Sep 17 00:00:00 2001 | ||
2 | From: Peter Jones <pjones@redhat.com> | ||
3 | Date: Sun, 19 Jul 2020 16:53:27 -0400 | ||
4 | Subject: [PATCH] efi: Fix some malformed device path arithmetic errors | ||
5 | |||
6 | Several places we take the length of a device path and subtract 4 from | ||
7 | it, without ever checking that it's >= 4. There are also cases where | ||
8 | this kind of malformation will result in unpredictable iteration, | ||
9 | including treating the length from one dp node as the type in the next | ||
10 | node. These are all errors, no matter where the data comes from. | ||
11 | |||
12 | This patch adds a checking macro, GRUB_EFI_DEVICE_PATH_VALID(), which | ||
13 | can be used in several places, and makes GRUB_EFI_NEXT_DEVICE_PATH() | ||
14 | return NULL and GRUB_EFI_END_ENTIRE_DEVICE_PATH() evaluate as true when | ||
15 | the length is too small. Additionally, it makes several places in the | ||
16 | code check for and return errors in these cases. | ||
17 | |||
18 | Signed-off-by: Peter Jones <pjones@redhat.com> | ||
19 | Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> | ||
20 | |||
21 | Upstream-Status: Backport [https://git.savannah.gnu.org/cgit/grub.git/commit/?id=d2cf823d0e31818d1b7a223daff6d5e006596543] | ||
22 | Signed-off-by: Marta Rybczynska <marta.rybczynska@huawei.com> | ||
23 | --- | ||
24 | grub-core/kern/efi/efi.c | 64 +++++++++++++++++++++++++----- | ||
25 | grub-core/loader/efi/chainloader.c | 13 +++++- | ||
26 | grub-core/loader/i386/xnu.c | 9 +++-- | ||
27 | include/grub/efi/api.h | 14 ++++--- | ||
28 | 4 files changed, 79 insertions(+), 21 deletions(-) | ||
29 | |||
30 | diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c | ||
31 | index ad170c7..6a38080 100644 | ||
32 | --- a/grub-core/kern/efi/efi.c | ||
33 | +++ b/grub-core/kern/efi/efi.c | ||
34 | @@ -360,7 +360,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0) | ||
35 | |||
36 | dp = dp0; | ||
37 | |||
38 | - while (1) | ||
39 | + while (dp) | ||
40 | { | ||
41 | grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); | ||
42 | grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); | ||
43 | @@ -370,9 +370,15 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0) | ||
44 | if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE | ||
45 | && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE) | ||
46 | { | ||
47 | - grub_efi_uint16_t len; | ||
48 | - len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4) | ||
49 | - / sizeof (grub_efi_char16_t)); | ||
50 | + grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp); | ||
51 | + | ||
52 | + if (len < 4) | ||
53 | + { | ||
54 | + grub_error (GRUB_ERR_OUT_OF_RANGE, | ||
55 | + "malformed EFI Device Path node has length=%d", len); | ||
56 | + return NULL; | ||
57 | + } | ||
58 | + len = (len - 4) / sizeof (grub_efi_char16_t); | ||
59 | filesize += GRUB_MAX_UTF8_PER_UTF16 * len + 2; | ||
60 | } | ||
61 | |||
62 | @@ -388,7 +394,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0) | ||
63 | if (!name) | ||
64 | return NULL; | ||
65 | |||
66 | - while (1) | ||
67 | + while (dp) | ||
68 | { | ||
69 | grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); | ||
70 | grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); | ||
71 | @@ -404,8 +410,15 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0) | ||
72 | |||
73 | *p++ = '/'; | ||
74 | |||
75 | - len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4) | ||
76 | - / sizeof (grub_efi_char16_t)); | ||
77 | + len = GRUB_EFI_DEVICE_PATH_LENGTH (dp); | ||
78 | + if (len < 4) | ||
79 | + { | ||
80 | + grub_error (GRUB_ERR_OUT_OF_RANGE, | ||
81 | + "malformed EFI Device Path node has length=%d", len); | ||
82 | + return NULL; | ||
83 | + } | ||
84 | + | ||
85 | + len = (len - 4) / sizeof (grub_efi_char16_t); | ||
86 | fp = (grub_efi_file_path_device_path_t *) dp; | ||
87 | /* According to EFI spec Path Name is NULL terminated */ | ||
88 | while (len > 0 && fp->path_name[len - 1] == 0) | ||
89 | @@ -480,7 +493,26 @@ grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp) | ||
90 | ; | ||
91 | p = GRUB_EFI_NEXT_DEVICE_PATH (p)) | ||
92 | { | ||
93 | - total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p); | ||
94 | + grub_size_t len = GRUB_EFI_DEVICE_PATH_LENGTH (p); | ||
95 | + | ||
96 | + /* | ||
97 | + * In the event that we find a node that's completely garbage, for | ||
98 | + * example if we get to 0x7f 0x01 0x02 0x00 ... (EndInstance with a size | ||
99 | + * of 2), GRUB_EFI_END_ENTIRE_DEVICE_PATH() will be true and | ||
100 | + * GRUB_EFI_NEXT_DEVICE_PATH() will return NULL, so we won't continue, | ||
101 | + * and neither should our consumers, but there won't be any error raised | ||
102 | + * even though the device path is junk. | ||
103 | + * | ||
104 | + * This keeps us from passing junk down back to our caller. | ||
105 | + */ | ||
106 | + if (len < 4) | ||
107 | + { | ||
108 | + grub_error (GRUB_ERR_OUT_OF_RANGE, | ||
109 | + "malformed EFI Device Path node has length=%d", len); | ||
110 | + return NULL; | ||
111 | + } | ||
112 | + | ||
113 | + total_size += len; | ||
114 | if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p)) | ||
115 | break; | ||
116 | } | ||
117 | @@ -525,7 +557,7 @@ dump_vendor_path (const char *type, grub_efi_vendor_device_path_t *vendor) | ||
118 | void | ||
119 | grub_efi_print_device_path (grub_efi_device_path_t *dp) | ||
120 | { | ||
121 | - while (1) | ||
122 | + while (GRUB_EFI_DEVICE_PATH_VALID (dp)) | ||
123 | { | ||
124 | grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); | ||
125 | grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); | ||
126 | @@ -937,7 +969,10 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1, | ||
127 | /* Return non-zero. */ | ||
128 | return 1; | ||
129 | |||
130 | - while (1) | ||
131 | + if (dp1 == dp2) | ||
132 | + return 0; | ||
133 | + | ||
134 | + while (GRUB_EFI_DEVICE_PATH_VALID (dp1) && GRUB_EFI_DEVICE_PATH_VALID (dp2)) | ||
135 | { | ||
136 | grub_efi_uint8_t type1, type2; | ||
137 | grub_efi_uint8_t subtype1, subtype2; | ||
138 | @@ -973,5 +1008,14 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1, | ||
139 | dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2); | ||
140 | } | ||
141 | |||
142 | + /* | ||
143 | + * There's no "right" answer here, but we probably don't want to call a valid | ||
144 | + * dp and an invalid dp equal, so pick one way or the other. | ||
145 | + */ | ||
146 | + if (GRUB_EFI_DEVICE_PATH_VALID (dp1) && !GRUB_EFI_DEVICE_PATH_VALID (dp2)) | ||
147 | + return 1; | ||
148 | + else if (!GRUB_EFI_DEVICE_PATH_VALID (dp1) && GRUB_EFI_DEVICE_PATH_VALID (dp2)) | ||
149 | + return -1; | ||
150 | + | ||
151 | return 0; | ||
152 | } | ||
153 | diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c | ||
154 | index daf8c6b..a8d7b91 100644 | ||
155 | --- a/grub-core/loader/efi/chainloader.c | ||
156 | +++ b/grub-core/loader/efi/chainloader.c | ||
157 | @@ -156,9 +156,18 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename) | ||
158 | |||
159 | size = 0; | ||
160 | d = dp; | ||
161 | - while (1) | ||
162 | + while (d) | ||
163 | { | ||
164 | - size += GRUB_EFI_DEVICE_PATH_LENGTH (d); | ||
165 | + grub_size_t len = GRUB_EFI_DEVICE_PATH_LENGTH (d); | ||
166 | + | ||
167 | + if (len < 4) | ||
168 | + { | ||
169 | + grub_error (GRUB_ERR_OUT_OF_RANGE, | ||
170 | + "malformed EFI Device Path node has length=%d", len); | ||
171 | + return NULL; | ||
172 | + } | ||
173 | + | ||
174 | + size += len; | ||
175 | if ((GRUB_EFI_END_ENTIRE_DEVICE_PATH (d))) | ||
176 | break; | ||
177 | d = GRUB_EFI_NEXT_DEVICE_PATH (d); | ||
178 | diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c | ||
179 | index b7d176b..c50cb54 100644 | ||
180 | --- a/grub-core/loader/i386/xnu.c | ||
181 | +++ b/grub-core/loader/i386/xnu.c | ||
182 | @@ -516,14 +516,15 @@ grub_cmd_devprop_load (grub_command_t cmd __attribute__ ((unused)), | ||
183 | |||
184 | devhead = buf; | ||
185 | buf = devhead + 1; | ||
186 | - dpstart = buf; | ||
187 | + dp = dpstart = buf; | ||
188 | |||
189 | - do | ||
190 | + while (GRUB_EFI_DEVICE_PATH_VALID (dp) && buf < bufend) | ||
191 | { | ||
192 | - dp = buf; | ||
193 | buf = (char *) buf + GRUB_EFI_DEVICE_PATH_LENGTH (dp); | ||
194 | + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) | ||
195 | + break; | ||
196 | + dp = buf; | ||
197 | } | ||
198 | - while (!GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp) && buf < bufend); | ||
199 | |||
200 | dev = grub_xnu_devprop_add_device (dpstart, (char *) buf | ||
201 | - (char *) dpstart); | ||
202 | diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h | ||
203 | index addcbfa..cf1355a 100644 | ||
204 | --- a/include/grub/efi/api.h | ||
205 | +++ b/include/grub/efi/api.h | ||
206 | @@ -625,6 +625,7 @@ typedef struct grub_efi_device_path grub_efi_device_path_protocol_t; | ||
207 | #define GRUB_EFI_DEVICE_PATH_TYPE(dp) ((dp)->type & 0x7f) | ||
208 | #define GRUB_EFI_DEVICE_PATH_SUBTYPE(dp) ((dp)->subtype) | ||
209 | #define GRUB_EFI_DEVICE_PATH_LENGTH(dp) ((dp)->length) | ||
210 | +#define GRUB_EFI_DEVICE_PATH_VALID(dp) ((dp) != NULL && GRUB_EFI_DEVICE_PATH_LENGTH (dp) >= 4) | ||
211 | |||
212 | /* The End of Device Path nodes. */ | ||
213 | #define GRUB_EFI_END_DEVICE_PATH_TYPE (0xff & 0x7f) | ||
214 | @@ -633,13 +634,16 @@ typedef struct grub_efi_device_path grub_efi_device_path_protocol_t; | ||
215 | #define GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE 0x01 | ||
216 | |||
217 | #define GRUB_EFI_END_ENTIRE_DEVICE_PATH(dp) \ | ||
218 | - (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_END_DEVICE_PATH_TYPE \ | ||
219 | - && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) \ | ||
220 | - == GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE)) | ||
221 | + (!GRUB_EFI_DEVICE_PATH_VALID (dp) || \ | ||
222 | + (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_END_DEVICE_PATH_TYPE \ | ||
223 | + && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) \ | ||
224 | + == GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE))) | ||
225 | |||
226 | #define GRUB_EFI_NEXT_DEVICE_PATH(dp) \ | ||
227 | - ((grub_efi_device_path_t *) ((char *) (dp) \ | ||
228 | - + GRUB_EFI_DEVICE_PATH_LENGTH (dp))) | ||
229 | + (GRUB_EFI_DEVICE_PATH_VALID (dp) \ | ||
230 | + ? ((grub_efi_device_path_t *) \ | ||
231 | + ((char *) (dp) + GRUB_EFI_DEVICE_PATH_LENGTH (dp))) \ | ||
232 | + : NULL) | ||
233 | |||
234 | /* Hardware Device Path. */ | ||
235 | #define GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE 1 | ||
diff --git a/meta/recipes-bsp/grub/grub2.inc b/meta/recipes-bsp/grub/grub2.inc index 2e4e6d7ac2..f7f2aa892f 100644 --- a/meta/recipes-bsp/grub/grub2.inc +++ b/meta/recipes-bsp/grub/grub2.inc | |||
@@ -51,6 +51,7 @@ SRC_URI = "${GNU_MIRROR}/grub/grub-${PV}.tar.gz \ | |||
51 | file://0002-net-net-Fix-possible-dereference-to-of-a-NULL-pointe.patch \ | 51 | file://0002-net-net-Fix-possible-dereference-to-of-a-NULL-pointe.patch \ |
52 | file://0003-net-tftp-Fix-dangling-memory-pointer.patch \ | 52 | file://0003-net-tftp-Fix-dangling-memory-pointer.patch \ |
53 | file://0004-kern-parser-Fix-resource-leak-if-argc-0.patch \ | 53 | file://0004-kern-parser-Fix-resource-leak-if-argc-0.patch \ |
54 | file://0005-efi-Fix-some-malformed-device-path-arithmetic-errors.patch \ | ||
54 | " | 55 | " |
55 | SRC_URI[md5sum] = "5ce674ca6b2612d8939b9e6abed32934" | 56 | SRC_URI[md5sum] = "5ce674ca6b2612d8939b9e6abed32934" |
56 | SRC_URI[sha256sum] = "f10c85ae3e204dbaec39ae22fa3c5e99f0665417e91c2cb49b7e5031658ba6ea" | 57 | SRC_URI[sha256sum] = "f10c85ae3e204dbaec39ae22fa3c5e99f0665417e91c2cb49b7e5031658ba6ea" |