Commit 44d60c0f authored by Borislav Petkov's avatar Borislav Petkov

x86, microcode, AMD: Extend ucode size verification

The different families have a different max size for the ucode patch,
adjust size checking to the family we're running on. Also, do not
vzalloc the max size of the ucode but only the actual size that is
passed on from the firmware loader.
Signed-off-by: default avatarBorislav Petkov <borislav.petkov@amd.com>
parent 258721ef
...@@ -66,7 +66,6 @@ struct microcode_amd { ...@@ -66,7 +66,6 @@ struct microcode_amd {
unsigned int mpb[0]; unsigned int mpb[0];
}; };
#define UCODE_MAX_SIZE 2048
#define UCODE_CONTAINER_SECTION_HDR 8 #define UCODE_CONTAINER_SECTION_HDR 8
#define UCODE_CONTAINER_HEADER_SIZE 12 #define UCODE_CONTAINER_HEADER_SIZE 12
...@@ -155,31 +154,60 @@ static int apply_microcode_amd(int cpu) ...@@ -155,31 +154,60 @@ static int apply_microcode_amd(int cpu)
return 0; return 0;
} }
static struct microcode_header_amd * static unsigned int verify_ucode_size(int cpu, const u8 *buf, unsigned int size)
get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size)
{ {
struct microcode_header_amd *mc; struct cpuinfo_x86 *c = &cpu_data(cpu);
unsigned int total_size; unsigned int max_size, actual_size;
if (buf[0] != UCODE_UCODE_TYPE) { #define F1XH_MPB_MAX_SIZE 2048
pr_err("invalid type field in container file section header\n"); #define F14H_MPB_MAX_SIZE 1824
return NULL; #define F15H_MPB_MAX_SIZE 4096
switch (c->x86) {
case 0x14:
max_size = F14H_MPB_MAX_SIZE;
break;
case 0x15:
max_size = F15H_MPB_MAX_SIZE;
break;
default:
max_size = F1XH_MPB_MAX_SIZE;
break;
} }
total_size = buf[4] + (buf[5] << 8); actual_size = buf[4] + (buf[5] << 8);
if (total_size > size || total_size > UCODE_MAX_SIZE) { if (actual_size > size || actual_size > max_size) {
pr_err("section size mismatch\n"); pr_err("section size mismatch\n");
return NULL; return 0;
} }
mc = vzalloc(UCODE_MAX_SIZE); return actual_size;
}
static struct microcode_header_amd *
get_next_ucode(int cpu, const u8 *buf, unsigned int size, unsigned int *mc_size)
{
struct microcode_header_amd *mc = NULL;
unsigned int actual_size = 0;
if (buf[0] != UCODE_UCODE_TYPE) {
pr_err("invalid type field in container file section header\n");
goto out;
}
actual_size = verify_ucode_size(cpu, buf, size);
if (!actual_size)
goto out;
mc = vzalloc(actual_size);
if (!mc) if (!mc)
return NULL; goto out;
get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, total_size); get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, actual_size);
*mc_size = total_size + UCODE_CONTAINER_SECTION_HDR; *mc_size = actual_size + UCODE_CONTAINER_SECTION_HDR;
out:
return mc; return mc;
} }
...@@ -234,7 +262,7 @@ generic_load_microcode(int cpu, const u8 *data, size_t size) ...@@ -234,7 +262,7 @@ generic_load_microcode(int cpu, const u8 *data, size_t size)
leftover = size - offset; leftover = size - offset;
while (leftover) { while (leftover) {
mc_hdr = get_next_ucode(ucode_ptr, leftover, &mc_size); mc_hdr = get_next_ucode(cpu, ucode_ptr, leftover, &mc_size);
if (!mc_hdr) if (!mc_hdr)
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment