Merge tag 'v4.5-rc5' into efi/core, before queueing up new changes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
@@ -165,67 +165,133 @@ validate_ascii_string(efi_char16_t *var_name, int match, u8 *buffer,
|
||||
}
|
||||
|
||||
struct variable_validate {
|
||||
efi_guid_t vendor;
|
||||
char *name;
|
||||
bool (*validate)(efi_char16_t *var_name, int match, u8 *data,
|
||||
unsigned long len);
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the list of variables we need to validate, as well as the
|
||||
* whitelist for what we think is safe not to default to immutable.
|
||||
*
|
||||
* If it has a validate() method that's not NULL, it'll go into the
|
||||
* validation routine. If not, it is assumed valid, but still used for
|
||||
* whitelisting.
|
||||
*
|
||||
* Note that it's sorted by {vendor,name}, but globbed names must come after
|
||||
* any other name with the same prefix.
|
||||
*/
|
||||
static const struct variable_validate variable_validate[] = {
|
||||
{ "BootNext", validate_uint16 },
|
||||
{ "BootOrder", validate_boot_order },
|
||||
{ "DriverOrder", validate_boot_order },
|
||||
{ "Boot*", validate_load_option },
|
||||
{ "Driver*", validate_load_option },
|
||||
{ "ConIn", validate_device_path },
|
||||
{ "ConInDev", validate_device_path },
|
||||
{ "ConOut", validate_device_path },
|
||||
{ "ConOutDev", validate_device_path },
|
||||
{ "ErrOut", validate_device_path },
|
||||
{ "ErrOutDev", validate_device_path },
|
||||
{ "Timeout", validate_uint16 },
|
||||
{ "Lang", validate_ascii_string },
|
||||
{ "PlatformLang", validate_ascii_string },
|
||||
{ "", NULL },
|
||||
{ EFI_GLOBAL_VARIABLE_GUID, "BootNext", validate_uint16 },
|
||||
{ EFI_GLOBAL_VARIABLE_GUID, "BootOrder", validate_boot_order },
|
||||
{ EFI_GLOBAL_VARIABLE_GUID, "Boot*", validate_load_option },
|
||||
{ EFI_GLOBAL_VARIABLE_GUID, "DriverOrder", validate_boot_order },
|
||||
{ EFI_GLOBAL_VARIABLE_GUID, "Driver*", validate_load_option },
|
||||
{ EFI_GLOBAL_VARIABLE_GUID, "ConIn", validate_device_path },
|
||||
{ EFI_GLOBAL_VARIABLE_GUID, "ConInDev", validate_device_path },
|
||||
{ EFI_GLOBAL_VARIABLE_GUID, "ConOut", validate_device_path },
|
||||
{ EFI_GLOBAL_VARIABLE_GUID, "ConOutDev", validate_device_path },
|
||||
{ EFI_GLOBAL_VARIABLE_GUID, "ErrOut", validate_device_path },
|
||||
{ EFI_GLOBAL_VARIABLE_GUID, "ErrOutDev", validate_device_path },
|
||||
{ EFI_GLOBAL_VARIABLE_GUID, "Lang", validate_ascii_string },
|
||||
{ EFI_GLOBAL_VARIABLE_GUID, "OsIndications", NULL },
|
||||
{ EFI_GLOBAL_VARIABLE_GUID, "PlatformLang", validate_ascii_string },
|
||||
{ EFI_GLOBAL_VARIABLE_GUID, "Timeout", validate_uint16 },
|
||||
{ LINUX_EFI_CRASH_GUID, "*", NULL },
|
||||
{ NULL_GUID, "", NULL },
|
||||
};
|
||||
|
||||
static bool
|
||||
variable_matches(const char *var_name, size_t len, const char *match_name,
|
||||
int *match)
|
||||
{
|
||||
for (*match = 0; ; (*match)++) {
|
||||
char c = match_name[*match];
|
||||
char u = var_name[*match];
|
||||
|
||||
/* Wildcard in the matching name means we've matched */
|
||||
if (c == '*')
|
||||
return true;
|
||||
|
||||
/* Case sensitive match */
|
||||
if (!c && *match == len)
|
||||
return true;
|
||||
|
||||
if (c != u)
|
||||
return false;
|
||||
|
||||
if (!c)
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long len)
|
||||
efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
|
||||
unsigned long data_size)
|
||||
{
|
||||
int i;
|
||||
u16 *unicode_name = var_name;
|
||||
unsigned long utf8_size;
|
||||
u8 *utf8_name;
|
||||
|
||||
for (i = 0; variable_validate[i].validate != NULL; i++) {
|
||||
utf8_size = ucs2_utf8size(var_name);
|
||||
utf8_name = kmalloc(utf8_size + 1, GFP_KERNEL);
|
||||
if (!utf8_name)
|
||||
return false;
|
||||
|
||||
ucs2_as_utf8(utf8_name, var_name, utf8_size);
|
||||
utf8_name[utf8_size] = '\0';
|
||||
|
||||
for (i = 0; variable_validate[i].name[0] != '\0'; i++) {
|
||||
const char *name = variable_validate[i].name;
|
||||
int match;
|
||||
int match = 0;
|
||||
|
||||
for (match = 0; ; match++) {
|
||||
char c = name[match];
|
||||
u16 u = unicode_name[match];
|
||||
if (efi_guidcmp(vendor, variable_validate[i].vendor))
|
||||
continue;
|
||||
|
||||
/* All special variables are plain ascii */
|
||||
if (u > 127)
|
||||
return true;
|
||||
|
||||
/* Wildcard in the matching name means we've matched */
|
||||
if (c == '*')
|
||||
return variable_validate[i].validate(var_name,
|
||||
match, data, len);
|
||||
|
||||
/* Case sensitive match */
|
||||
if (c != u)
|
||||
if (variable_matches(utf8_name, utf8_size+1, name, &match)) {
|
||||
if (variable_validate[i].validate == NULL)
|
||||
break;
|
||||
|
||||
/* Reached the end of the string while matching */
|
||||
if (!c)
|
||||
return variable_validate[i].validate(var_name,
|
||||
match, data, len);
|
||||
kfree(utf8_name);
|
||||
return variable_validate[i].validate(var_name, match,
|
||||
data, data_size);
|
||||
}
|
||||
}
|
||||
|
||||
kfree(utf8_name);
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(efivar_validate);
|
||||
|
||||
bool
|
||||
efivar_variable_is_removable(efi_guid_t vendor, const char *var_name,
|
||||
size_t len)
|
||||
{
|
||||
int i;
|
||||
bool found = false;
|
||||
int match = 0;
|
||||
|
||||
/*
|
||||
* Check if our variable is in the validated variables list
|
||||
*/
|
||||
for (i = 0; variable_validate[i].name[0] != '\0'; i++) {
|
||||
if (efi_guidcmp(variable_validate[i].vendor, vendor))
|
||||
continue;
|
||||
|
||||
if (variable_matches(var_name, len,
|
||||
variable_validate[i].name, &match)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's in our list, it is removable.
|
||||
*/
|
||||
return found;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(efivar_variable_is_removable);
|
||||
|
||||
static efi_status_t
|
||||
check_var_size(u32 attributes, unsigned long size)
|
||||
{
|
||||
@@ -864,7 +930,7 @@ int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,
|
||||
|
||||
*set = false;
|
||||
|
||||
if (efivar_validate(name, data, *size) == false)
|
||||
if (efivar_validate(*vendor, name, data, *size) == false)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user