Convert the late loader in the AMD microcode update driver to use newly
introduced microcode container data checking functions as it was previously
done for the early loader.

Signed-off-by: Maciej S. Szmigiero <m...@maciej.szmigiero.name>
---
 arch/x86/kernel/cpu/microcode/amd.c | 70 +++++++++++++----------------
 1 file changed, 32 insertions(+), 38 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/amd.c 
b/arch/x86/kernel/cpu/microcode/amd.c
index f8bd74341ed8..3e10a5920f58 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -693,28 +693,26 @@ static enum ucode_state apply_microcode_amd(int cpu)
        return UCODE_UPDATED;
 }
 
-static int install_equiv_cpu_table(const u8 *buf)
+static unsigned int install_equiv_cpu_table(const u8 *buf, size_t buf_size)
 {
-       unsigned int *ibuf = (unsigned int *)buf;
-       unsigned int type = ibuf[1];
-       unsigned int size = ibuf[2];
+       const u32 *hdr;
+       u32 equiv_tbl_len;
 
-       if (type != UCODE_EQUIV_CPU_TABLE_TYPE || !size) {
-               pr_err("empty section/"
-                      "invalid type field in container file section header\n");
-               return -EINVAL;
-       }
+       if (!verify_equivalence_table(buf, buf_size, false))
+               return 0;
+
+       hdr = (const u32 *)buf;
+       equiv_tbl_len = hdr[2];
 
-       equiv_cpu_table = vmalloc(size);
+       equiv_cpu_table = vmalloc(equiv_tbl_len);
        if (!equiv_cpu_table) {
                pr_err("failed to allocate equivalent CPU table\n");
-               return -ENOMEM;
+               return 0;
        }
 
-       memcpy(equiv_cpu_table, buf + CONTAINER_HDR_SZ, size);
+       memcpy(equiv_cpu_table, buf + CONTAINER_HDR_SZ, equiv_tbl_len);
 
-       /* add header length */
-       return size + CONTAINER_HDR_SZ;
+       return equiv_tbl_len;
 }
 
 static void free_equiv_cpu_table(void)
@@ -739,13 +737,19 @@ static void cleanup(void)
 static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover,
                                unsigned int *crnt_size)
 {
+       u32 *hdr = (u32 *)fw;
        struct microcode_header_amd *mc_hdr;
        struct ucode_patch *patch;
-       unsigned int patch_size, ret;
+       u32 patch_size;
        u32 proc_fam;
        u16 proc_id;
 
-       patch_size  = *(u32 *)(fw + 4);
+       if (!verify_patch_section(fw, leftover, false)) {
+               *crnt_size = leftover;
+               return 0;
+       }
+
+       patch_size  = hdr[1];
        *crnt_size  = patch_size + SECTION_HDR_SIZE;
        mc_hdr      = (struct microcode_header_amd *)(fw + SECTION_HDR_SIZE);
        proc_id     = mc_hdr->processor_rev_id;
@@ -767,16 +771,8 @@ static int verify_and_add_patch(u8 family, u8 *fw, 
unsigned int leftover,
                return 0;
        }
 
-       /*
-        * The section header length is not included in this indicated size
-        * but is present in the leftover file length so we need to subtract
-        * it before passing this value to the function below.
-        */
-       ret = verify_patch_size(family, patch_size, leftover - 
SECTION_HDR_SIZE);
-       if (!ret) {
-               pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id);
+       if (!verify_patch(family, fw, leftover, false))
                return 0;
-       }
 
        patch = kzalloc(sizeof(*patch), GFP_KERNEL);
        if (!patch) {
@@ -810,21 +806,21 @@ static enum ucode_state __load_microcode_amd(u8 family, 
const u8 *data,
        enum ucode_state ret = UCODE_ERROR;
        unsigned int leftover;
        u8 *fw = (u8 *)data;
-       int offset;
+       unsigned int offset;
 
-       offset = install_equiv_cpu_table(data);
-       if (offset < 0) {
+       offset = install_equiv_cpu_table(data, size);
+       if (!offset) {
                pr_err("failed to create equivalent cpu table\n");
                return ret;
        }
-       fw += offset;
-       leftover = size - offset;
 
-       if (*(u32 *)fw != UCODE_UCODE_TYPE) {
-               pr_err("invalid type field in container file section header\n");
-               free_equiv_cpu_table();
-               return ret;
-       }
+       /*
+        * Skip also the container header, since install_equiv_cpu_table()
+        * returns just the raw equivalence table size without the header.
+        */
+       fw += CONTAINER_HDR_SZ;
+       fw += offset;
+       leftover = size - CONTAINER_HDR_SZ - offset;
 
        while (leftover) {
                unsigned int crnt_size;
@@ -912,10 +908,8 @@ static enum ucode_state request_microcode_amd(int cpu, 
struct device *device,
        }
 
        ret = UCODE_ERROR;
-       if (*(u32 *)fw->data != UCODE_MAGIC) {
-               pr_err("invalid magic value (0x%08x)\n", *(u32 *)fw->data);
+       if (!verify_container(fw->data, fw->size, false))
                goto fw_release;
-       }
 
        ret = load_microcode_amd(bsp, c->x86, fw->data, fw->size);
 

Reply via email to