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
192}192}
193 193
194static bool194static bool
195validate_device_path(struct efi_variable *var, int match, u8 *buffer, int len)195validate_device_path(struct efi_variable *var, int match, u8 *buffer,
196 unsigned long len)
196{197{
197 struct efi_generic_dev_path *node;198 struct efi_generic_dev_path *node;
198 int offset = 0;199 int offset = 0;
199 200
200 node = (struct efi_generic_dev_path *)buffer;201 node = (struct efi_generic_dev_path *)buffer;
201 202
202 while (offset < len) {203 if (len < sizeof(*node))
203 offset += node->length;204 return false;
204 205
205 if (offset > len)206 while (offset <= len - sizeof(*node) &&
206 return false;207 node->length >= sizeof(*node) &&
208 node->length <= len - offset) {
209 offset += node->length;
207 210
208 if ((node->type == EFI_DEV_END_PATH ||211 if ((node->type == EFI_DEV_END_PATH ||
209 node->type == EFI_DEV_END_PATH2) &&212 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
222}225}
223 226
224static bool227static bool
225validate_boot_order(struct efi_variable *var, int match, u8 *buffer, int len)228validate_boot_order(struct efi_variable *var, int match, u8 *buffer,
229 unsigned long len)
226{230{
227 /* An array of 16-bit integers */231 /* An array of 16-bit integers */
228 if ((len % 2) != 0)232 if ((len % 2) != 0)
@@ -232,19 +236,27 @@ validate_boot_order(struct efi_variable *var, int match, u8 *buffer, int len) · 3 unmodified lines
232}236}
233 237
234static bool238static bool
235validate_load_option(struct efi_variable *var, int match, u8 *buffer, int len)239validate_load_option(struct efi_variable *var, int match, u8 *buffer,
240 unsigned long len)
236{241{
237 u16 filepathlength;242 u16 filepathlength;
238 int i, desclength = 0;243 int i, desclength = 0, namelen;
244
245 namelen = utf16_strnlen(var->VariableName, sizeof(var->VariableName));
239 246
240 /* Either "Boot" or "Driver" followed by four digits of hex */247 /* Either "Boot" or "Driver" followed by four digits of hex */
241 for (i = match; i < match+4; i++) {248 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)
243 return true;251 return true;
244 }252 }
245 253
246 /* A valid entry must be at least 6 bytes */254 /* Reject it if there's 4 digits of hex and then further content */
247 if (len < 6)255 if (namelen > match + 4)
256 return false;
257
258 /* A valid entry must be at least 8 bytes */
259 if (len < 8)
248 return false;260 return false;
249 261
250 filepathlength = buffer[4] | buffer[5] << 8;262 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
253 * There's no stored length for the description, so it has to be265 * There's no stored length for the description, so it has to be
254 * found by hand266 * found by hand
255 */267 */
256 desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len) + 2;268 desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2;
257 269
258 /* Each boot entry must have a descriptor */270 /* Each boot entry must have a descriptor */
259 if (!desclength)271 if (!desclength)
@@ -275,7 +287,8 @@ validate_load_option(struct efi_variable *var, int match, u8 *buffer, int len) · 15 unmodified lines
275}287}
276 288
277static bool289static bool
278validate_uint16(struct efi_variable *var, int match, u8 *buffer, int len)290validate_uint16(struct efi_variable *var, int match, u8 *buffer,
291 unsigned long len)
279{292{
280 /* A single 16-bit integer */293 /* A single 16-bit integer */
281 if (len != 2)294 if (len != 2)
@@ -285,7 +298,8 @@ validate_uint16(struct efi_variable *var, int match, u8 *buffer, int len) · 3 unmodified lines
285}298}
286 299
287static bool300static bool
288validate_ascii_string(struct efi_variable *var, int match, u8 *buffer, int len)301validate_ascii_string(struct efi_variable *var, int match, u8 *buffer,
302 unsigned long len)
289{303{
290 int i;304 int i;
291 305
@@ -303,7 +317,7 @@ validate_ascii_string(struct efi_variable *var, int match, u8 *buffer, int len) · 11 unmodified lines
303struct variable_validate {317struct variable_validate {
304 char *name;318 char *name;
305 bool (*validate)(struct efi_variable *var, int match, u8 *data,319 bool (*validate)(struct efi_variable *var, int match, u8 *data,
306 int len);320 unsigned long len);
307};321};
308 322
309static const struct variable_validate variable_validate[] = {323static const struct variable_validate variable_validate[] = {
@@ -325,7 +339,7 @@ static const struct variable_validate variable_validate[] = { · 15 unmodified lines
325};339};
326 340
327static bool341static bool
328validate_var(struct efi_variable *var, u8 *data, int len)342validate_var(struct efi_variable *var, u8 *data, unsigned long len)
329{343{
330 int i;344 int i;
331 u16 *unicode_name = var->VariableName;345 u16 *unicode_name = var->VariableName;