aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firmware/efivars.c46
1 files changed, 30 insertions, 16 deletions
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 891e4674d29b..47408e802ab6 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -192,18 +192,21 @@ utf16_strncmp(const efi_char16_t *a, const efi_char16_t *b, size_t len)
192} 192}
193 193
194static bool 194static 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)
222} 225}
223 226
224static bool 227static 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)
232} 236}
233 237
234static bool 238static 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)
253 * There's no stored length for the description, so it has to be 265 * There's no stored length for the description, so it has to be
254 * found by hand 266 * 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)
275} 287}
276 288
277static bool 289static 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)
285} 298}
286 299
287static bool 300static 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)
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[] = {
325}; 339};
326 340
327static bool 341static 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;