[tip:x86/microcode] x86, microcode, AMD: Extend ucode size verification

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Commit-ID:  44d60c0f5c58c2168f31df9a481761451840eb54
Gitweb:     http://git.kernel.org/tip/44d60c0f5c58c2168f31df9a481761451840eb54
Author:     Borislav Petkov <borislav.petkov@xxxxxxx>
AuthorDate: Thu, 10 Feb 2011 12:19:47 +0100
Committer:  Borislav Petkov <borislav.petkov@xxxxxxx>
CommitDate: Thu, 10 Feb 2011 12:24:03 +0100

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: Borislav Petkov <borislav.petkov@xxxxxxx>
---
 arch/x86/kernel/microcode_amd.c |   60 ++++++++++++++++++++++++++++----------
 1 files changed, 44 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index adbcef4..9fb8405 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/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;
 
--
To unsubscribe from this list: send the line "unsubscribe linux-tip-commits" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Stable Commits]     [Linux Stable Kernel]     [Linux Kernel]     [Linux USB Devel]     [Linux Video &Media]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux