History

Merge branch 'efi-vars' from Matthew Garrett

* efi-vars: efivars: Improve variable validation

Linus Torvalds committed 14 years ago

Commit 65e62b52 parents 6b4c555 54b3a4d1 file · +30 −16Browse files

Unified · Split

drivers/firmware/efivars.c+30−16
@@ -192,18 +192,21 @@ utf16_strncmp(const efi_char16_t *a, const efi_char16_t *b, size_t len) · 191 unmodified lines
192192 }
193193
194194 static bool
195−validate_device_path(struct efi_variable *var, int match, u8 *buffer, int len)
195+validate_device_path(struct efi_variable *var, int match, u8 *buffer,
196+ unsigned long len)
196197 {
197198 struct efi_generic_dev_path *node;
198199 int offset = 0;
199200
200201 node = (struct efi_generic_dev_path *)buffer;
201202
202− while (offset < len) {
203− offset += node->length;
203+ if (len < sizeof(*node))
204+ return false;
204205
205− if (offset > len)
206− return false;
206+ while (offset <= len - sizeof(*node) &&
207+ node->length >= sizeof(*node) &&
208+ node->length <= len - offset) {
209+ offset += node->length;
207210
208211 if ((node->type == EFI_DEV_END_PATH ||
209212 node->type == EFI_DEV_END_PATH2) &&
@@ -222,7 +225,8 @@ validate_device_path(struct efi_variable *var, int match, u8 *buffer, int len) · 12 unmodified lines
222225 }
223226
224227 static bool
225−validate_boot_order(struct efi_variable *var, int match, u8 *buffer, int len)
228+validate_boot_order(struct efi_variable *var, int match, u8 *buffer,
229+ unsigned long len)
226230 {
227231 /* An array of 16-bit integers */
228232 if ((len % 2) != 0)
@@ -232,19 +236,27 @@ validate_boot_order(struct efi_variable *var, int match, u8 *buffer, int len) · 3 unmodified lines
232236 }
233237
234238 static bool
235−validate_load_option(struct efi_variable *var, int match, u8 *buffer, int len)
239+validate_load_option(struct efi_variable *var, int match, u8 *buffer,
240+ unsigned long len)
236241 {
237242 u16 filepathlength;
238− int i, desclength = 0;
243+ int i, desclength = 0, namelen;
244+
245+ namelen = utf16_strnlen(var->VariableName, sizeof(var->VariableName));
239246
240247 /* Either "Boot" or "Driver" followed by four digits of hex */
241248 for (i = match; i < match+4; i++) {
242− if (hex_to_bin(var->VariableName[i] & 0xff) < 0)
249+ if (var->VariableName[i] > 127 ||
250+ hex_to_bin(var->VariableName[i] & 0xff) < 0)
243251 return true;
244252 }
245253
246− /* A valid entry must be at least 6 bytes */
247− if (len < 6)
254+ /* Reject it if there's 4 digits of hex and then further content */
255+ if (namelen > match + 4)
256+ return false;
257+
258+ /* A valid entry must be at least 8 bytes */
259+ if (len < 8)
248260 return false;
249261
250262 filepathlength = buffer[4] | buffer[5] << 8;
@@ -253,7 +265,7 @@ validate_load_option(struct efi_variable *var, int match, u8 *buffer, int len) · 2 unmodified lines
253265 * There's no stored length for the description, so it has to be
254266 * found by hand
255267 */
256− desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len) + 2;
268+ desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2;
257269
258270 /* Each boot entry must have a descriptor */
259271 if (!desclength)
@@ -275,7 +287,8 @@ validate_load_option(struct efi_variable *var, int match, u8 *buffer, int len) · 15 unmodified lines
275287 }
276288
277289 static bool
278−validate_uint16(struct efi_variable *var, int match, u8 *buffer, int len)
290+validate_uint16(struct efi_variable *var, int match, u8 *buffer,
291+ unsigned long len)
279292 {
280293 /* A single 16-bit integer */
281294 if (len != 2)
@@ -285,7 +298,8 @@ validate_uint16(struct efi_variable *var, int match, u8 *buffer, int len) · 3 unmodified lines
285298 }
286299
287300 static bool
288−validate_ascii_string(struct efi_variable *var, int match, u8 *buffer, int len)
301+validate_ascii_string(struct efi_variable *var, int match, u8 *buffer,
302+ unsigned long len)
289303 {
290304 int i;
291305
@@ -303,7 +317,7 @@ validate_ascii_string(struct efi_variable *var, int match, u8 *buffer, int len) · 11 unmodified lines
303317 struct variable_validate {
304318 char *name;
305319 bool (*validate)(struct efi_variable *var, int match, u8 *data,
306− int len);
320+ unsigned long len);
307321 };
308322
309323 static const struct variable_validate variable_validate[] = {
@@ -325,7 +339,7 @@ static const struct variable_validate variable_validate[] = { · 15 unmodified lines
325339 };
326340
327341 static bool
328−validate_var(struct efi_variable *var, u8 *data, int len)
342+validate_var(struct efi_variable *var, u8 *data, unsigned long len)
329343 {
330344 int i;
331345 u16 *unicode_name = var->VariableName;