static bool validate_load_option(struct efi_variable *var, int match, u8 *buffer, unsigned long len) { u16 filepathlength; int i, desclength = 0, namelen; namelen = utf16_strnlen(var->VariableName, sizeof(var->VariableName)); /* Either "Boot" or "Driver" followed by four digits of hex */ for (i = match; i < match+4; i++) { if (var->VariableName[i] > 127 || hex_to_bin(var->VariableName[i] & 0xff) < 0) return true; } /* Reject it if there's 4 digits of hex and then further content */ if (namelen > match + 4) return false; /* A valid entry must be at least 8 bytes */ if (len < 8) return false; filepathlength = buffer[4] | buffer[5] << 8; /* * There's no stored length for the description, so it has to be * found by hand */ desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2; /* Each boot entry must have a descriptor */ if (!desclength) return false; /* * If the sum of the length of the description, the claimed filepath * length and the original header are greater than the length of the * variable, it's malformed */ if ((desclength + filepathlength + 6) > len) return false; /* * And, finally, check the filepath */ return validate_device_path(var, match, buffer + desclength + 6, filepathlength); }
static bool validate_load_option(struct efi_variable *var, int match, u8 *buffer, unsigned long len) { u16 filepathlength; int i, desclength = 0, namelen; namelen = utf16_strnlen(var->VariableName, sizeof(var->VariableName)); for (i = match; i < match+4; i++) { if (var->VariableName[i] > 127 || hex_to_bin(var->VariableName[i] & 0xff) < 0) return true; } if (namelen > match + 4) return false; if (len < 8) return false; filepathlength = buffer[4] | buffer[5] << 8; desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2; if (!desclength) return false; if ((desclength + filepathlength + 6) > len) return false; return validate_device_path(var, match, buffer + desclength + 6, filepathlength); }
/* * Return the number of bytes is the length of this string * Note: this is NOT the same as the number of unicode characters */ static inline unsigned long utf16_strsize(efi_char16_t *data, unsigned long maxlength) { return utf16_strnlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t); }
static inline unsigned long utf16_strlen(efi_char16_t *s) { return utf16_strnlen(s, ~0UL); }