efi_loader: remove limit on variable length

The EFI spec does not provide a length limit for variables.

Reviewed-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
Heinrich Schuchardt 2018-08-31 21:31:31 +02:00 committed by Alexander Graf
parent fbba2f6776
commit dcdb64f7f5

View file

@ -44,10 +44,7 @@
* converted to utf16? * converted to utf16?
*/ */
#define MAX_VAR_NAME 31 #define PREFIX_LEN (strlen("efi_xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx_"))
#define MAX_NATIVE_VAR_NAME \
(strlen("efi_xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx_") + \
(MAX_VAR_NAME * MAX_UTF8_PER_UTF16))
static int hex(int ch) static int hex(int ch)
{ {
@ -101,18 +98,20 @@ static char *mem2hex(char *hexstr, const u8 *mem, int count)
return hexstr; return hexstr;
} }
static efi_status_t efi_to_native(char *native, u16 *variable_name, static efi_status_t efi_to_native(char **native, const u16 *variable_name,
efi_guid_t *vendor) efi_guid_t *vendor)
{ {
size_t len; size_t len;
char *pos;
len = u16_strlen((u16 *)variable_name); len = PREFIX_LEN + utf16_utf8_strlen(variable_name) + 1;
if (len >= MAX_VAR_NAME) *native = malloc(len);
return EFI_DEVICE_ERROR; if (!*native)
return EFI_OUT_OF_RESOURCES;
native += sprintf(native, "efi_%pUl_", vendor); pos = *native;
native = (char *)utf16_to_utf8((u8 *)native, (u16 *)variable_name, len); pos += sprintf(pos, "efi_%pUl_", vendor);
*native = '\0'; utf16_utf8_strcpy(&pos, variable_name);
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -168,7 +167,7 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, efi_guid_t *vendor,
u32 *attributes, efi_uintn_t *data_size, u32 *attributes, efi_uintn_t *data_size,
void *data) void *data)
{ {
char native_name[MAX_NATIVE_VAR_NAME + 1]; char *native_name;
efi_status_t ret; efi_status_t ret;
unsigned long in_size; unsigned long in_size;
const char *val, *s; const char *val, *s;
@ -180,13 +179,14 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, efi_guid_t *vendor,
if (!variable_name || !vendor || !data_size) if (!variable_name || !vendor || !data_size)
return EFI_EXIT(EFI_INVALID_PARAMETER); return EFI_EXIT(EFI_INVALID_PARAMETER);
ret = efi_to_native(native_name, variable_name, vendor); ret = efi_to_native(&native_name, variable_name, vendor);
if (ret) if (ret)
return EFI_EXIT(ret); return EFI_EXIT(ret);
debug("%s: get '%s'\n", __func__, native_name); debug("%s: get '%s'\n", __func__, native_name);
val = env_get(native_name); val = env_get(native_name);
free(native_name);
if (!val) if (!val)
return EFI_EXIT(EFI_NOT_FOUND); return EFI_EXIT(EFI_NOT_FOUND);
@ -256,35 +256,41 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name, efi_guid_t *vendor,
u32 attributes, efi_uintn_t data_size, u32 attributes, efi_uintn_t data_size,
void *data) void *data)
{ {
char native_name[MAX_NATIVE_VAR_NAME + 1]; char *native_name = NULL, *val = NULL, *s;
efi_status_t ret = EFI_SUCCESS; efi_status_t ret = EFI_SUCCESS;
char *val, *s;
u32 attr; u32 attr;
EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes, EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes,
data_size, data); data_size, data);
if (!variable_name || !vendor) if (!variable_name || !vendor) {
return EFI_EXIT(EFI_INVALID_PARAMETER); ret = EFI_INVALID_PARAMETER;
goto out;
}
ret = efi_to_native(native_name, variable_name, vendor); ret = efi_to_native(&native_name, variable_name, vendor);
if (ret) if (ret)
return EFI_EXIT(ret); goto out;
#define ACCESS_ATTR (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS) #define ACCESS_ATTR (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)
if ((data_size == 0) || !(attributes & ACCESS_ATTR)) { if ((data_size == 0) || !(attributes & ACCESS_ATTR)) {
/* delete the variable: */ /* delete the variable: */
env_set(native_name, NULL); env_set(native_name, NULL);
return EFI_EXIT(EFI_SUCCESS); ret = EFI_SUCCESS;
goto out;
} }
val = env_get(native_name); val = env_get(native_name);
if (val) { if (val) {
parse_attr(val, &attr); parse_attr(val, &attr);
if (attr & READ_ONLY) if (attr & READ_ONLY) {
return EFI_EXIT(EFI_WRITE_PROTECTED); /* We should not free val */
val = NULL;
ret = EFI_WRITE_PROTECTED;
goto out;
}
} }
val = malloc(2 * data_size + strlen("{ro,run,boot}(blob)") + 1); val = malloc(2 * data_size + strlen("{ro,run,boot}(blob)") + 1);
@ -320,6 +326,8 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name, efi_guid_t *vendor,
if (env_set(native_name, val)) if (env_set(native_name, val))
ret = EFI_DEVICE_ERROR; ret = EFI_DEVICE_ERROR;
out:
free(native_name);
free(val); free(val);
return EFI_EXIT(ret); return EFI_EXIT(ret);