From 333801861f28a2c63215d9de8ec5435f833691f7 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 10 Feb 2011 12:19:47 +0100 Subject: [PATCH] --- yaml --- r: 234799 b: refs/heads/master c: 44d60c0f5c58c2168f31df9a481761451840eb54 h: refs/heads/master i: 234797: b8a9ad2abcbc28ca02f00be5281258036c6e037a 234795: 32cbb620a9a3461893f97da97a11f868b244adae 234791: 21f31597aac0226129b6f71d1472e0186f0943a2 234783: abb49ff45e53e43ea71a15f6732c5e7789765965 v: v3 --- [refs] | 2 +- trunk/arch/x86/kernel/microcode_amd.c | 60 ++++++++++++++++++++------- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/[refs] b/[refs] index d4959a0641c8..d52296896f23 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 258721ef34fce97a7a6ca9cebebb303827645868 +refs/heads/master: 44d60c0f5c58c2168f31df9a481761451840eb54 diff --git a/trunk/arch/x86/kernel/microcode_amd.c b/trunk/arch/x86/kernel/microcode_amd.c index adbcef4f6333..9fb8405451c5 100644 --- a/trunk/arch/x86/kernel/microcode_amd.c +++ b/trunk/arch/x86/kernel/microcode_amd.c @@ -66,7 +66,6 @@ struct microcode_amd { unsigned int mpb[0]; }; -#define UCODE_MAX_SIZE 2048 #define UCODE_CONTAINER_SECTION_HDR 8 #define UCODE_CONTAINER_HEADER_SIZE 12 @@ -155,31 +154,60 @@ static int apply_microcode_amd(int cpu) return 0; } +static unsigned int verify_ucode_size(int cpu, const u8 *buf, unsigned int size) +{ + struct cpuinfo_x86 *c = &cpu_data(cpu); + unsigned int max_size, actual_size; + +#define F1XH_MPB_MAX_SIZE 2048 +#define F14H_MPB_MAX_SIZE 1824 +#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; + } + + actual_size = buf[4] + (buf[5] << 8); + + if (actual_size > size || actual_size > max_size) { + pr_err("section size mismatch\n"); + return 0; + } + + return actual_size; +} + static struct microcode_header_amd * -get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size) +get_next_ucode(int cpu, const u8 *buf, unsigned int size, unsigned int *mc_size) { - struct microcode_header_amd *mc; - unsigned int total_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"); - return NULL; + goto out; } - total_size = buf[4] + (buf[5] << 8); - - if (total_size > size || total_size > UCODE_MAX_SIZE) { - pr_err("section size mismatch\n"); - return NULL; - } + actual_size = verify_ucode_size(cpu, buf, size); + if (!actual_size) + goto out; - mc = vzalloc(UCODE_MAX_SIZE); + mc = vzalloc(actual_size); if (!mc) - return NULL; + goto out; - get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, total_size); - *mc_size = total_size + UCODE_CONTAINER_SECTION_HDR; + get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, actual_size); + *mc_size = actual_size + UCODE_CONTAINER_SECTION_HDR; +out: return mc; } @@ -234,7 +262,7 @@ generic_load_microcode(int cpu, const u8 *data, size_t size) leftover = size - offset; 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) break;