Commit-ID:  d430a305b7f8127d992e79e90b6fac00f99d23b3
Gitweb:     https://git.kernel.org/tip/d430a305b7f8127d992e79e90b6fac00f99d23b3
Author:     Borislav Petkov <b...@suse.de>
AuthorDate: Fri, 19 Oct 2018 14:27:24 +0200
Committer:  Borislav Petkov <b...@suse.de>
CommitDate: Mon, 19 Nov 2018 10:51:06 +0100

x86/microcode/AMD: Change verify_patch()'s return value

Have it return 0 on success, positive value when the current patch
should be skipped and negative on error.

Signed-off-by: Borislav Petkov <b...@suse.de>
Cc: x...@kernel.org
Link: https://lkml.kernel.org/r/20181107170218.7596-11...@alien8.de
---
 arch/x86/kernel/cpu/microcode/amd.c | 91 +++++++++++++++++++++----------------
 1 file changed, 52 insertions(+), 39 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/amd.c 
b/arch/x86/kernel/cpu/microcode/amd.c
index ebac82357639..79216cfb9f72 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -210,24 +210,32 @@ __verify_patch_size(u8 family, u32 sh_psize, unsigned int 
buf_size)
                break;
        }
 
-       if (sh_psize > min_t(u32, buf_size, max_size)) {
-               pr_err("patch size mismatch\n");
+       if (sh_psize > min_t(u32, buf_size, max_size))
                return 0;
-       }
 
        return sh_psize;
 }
 
-static unsigned int
-verify_patch(u8 family, const u8 *buf, unsigned int buf_size, bool early)
+/*
+ * Verify the patch in @buf.
+ *
+ * Returns:
+ * negative: on error
+ * positive: patch is not for this family, skip it
+ * 0: success
+ */
+static int
+verify_patch(u8 family, const u8 *buf, size_t buf_size, u32 *patch_size, bool 
early)
 {
        struct microcode_header_amd *mc_hdr;
+       unsigned int ret;
        u32 sh_psize;
        u16 proc_id;
        u8 patch_fam;
 
        if (!__verify_patch_section(buf, buf_size, &sh_psize, early))
-               return 0;
+               return -1;
+
        /*
         * The section header length is not included in this indicated size
         * but is present in the leftover file length so we need to subtract
@@ -243,23 +251,31 @@ verify_patch(u8 family, const u8 *buf, unsigned int 
buf_size, bool early)
                if (!early)
                        pr_debug("Patch of size %u truncated.\n", sh_psize);
 
-               return 0;
+               return -1;
        }
 
-       mc_hdr  = (struct microcode_header_amd *)(buf + SECTION_HDR_SIZE);
-       proc_id = mc_hdr->processor_rev_id;
+       ret = __verify_patch_size(family, sh_psize, buf_size);
+       if (!ret) {
+               if (!early)
+                       pr_debug("Per-family patch size mismatch.\n");
+               return -1;
+       }
+
+       *patch_size = sh_psize;
 
+       mc_hdr  = (struct microcode_header_amd *)(buf + SECTION_HDR_SIZE);
        if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
                if (!early)
                        pr_err("Patch-ID 0x%08x: chipset-specific code 
unsupported.\n", mc_hdr->patch_id);
-               return 0;
+               return -1;
        }
 
+       proc_id = mc_hdr->processor_rev_id;
        patch_fam = 0xf + (proc_id >> 12);
        if (patch_fam != family)
-               return 0;
+               return 1;
 
-       return __verify_patch_size(family, sh_psize, buf_size);
+       return 0;
 }
 
 /*
@@ -729,23 +745,17 @@ static void cleanup(void)
  * driver cannot continue functioning normally. In such cases, we tear
  * down everything we've used up so far and exit.
  */
-static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover)
+static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover,
+                               unsigned int *patch_size)
 {
        struct microcode_header_amd *mc_hdr;
-       unsigned int patch_size, crnt_size;
        struct ucode_patch *patch;
        u16 proc_id;
+       int ret;
 
-       patch_size = verify_patch(family, fw, leftover, false);
-       if (!patch_size) {
-               pr_debug("Patch size mismatch.\n");
-               return 1;
-       }
-
-       /* If initial rough pokes pass, we can start looking at the header. */
-       crnt_size   = patch_size + SECTION_HDR_SIZE;
-       mc_hdr      = (struct microcode_header_amd *)(fw + SECTION_HDR_SIZE);
-       proc_id     = mc_hdr->processor_rev_id;
+       ret = verify_patch(family, fw, leftover, patch_size, false);
+       if (ret)
+               return ret;
 
        patch = kzalloc(sizeof(*patch), GFP_KERNEL);
        if (!patch) {
@@ -753,13 +763,16 @@ static int verify_and_add_patch(u8 family, u8 *fw, 
unsigned int leftover)
                return -EINVAL;
        }
 
-       patch->data = kmemdup(fw + SECTION_HDR_SIZE, patch_size, GFP_KERNEL);
+       patch->data = kmemdup(fw + SECTION_HDR_SIZE, *patch_size, GFP_KERNEL);
        if (!patch->data) {
                pr_err("Patch data allocation failure.\n");
                kfree(patch);
                return -EINVAL;
        }
 
+       mc_hdr      = (struct microcode_header_amd *)(fw + SECTION_HDR_SIZE);
+       proc_id     = mc_hdr->processor_rev_id;
+
        INIT_LIST_HEAD(&patch->plist);
        patch->patch_id  = mc_hdr->patch_id;
        patch->equiv_cpu = proc_id;
@@ -770,39 +783,39 @@ static int verify_and_add_patch(u8 family, u8 *fw, 
unsigned int leftover)
        /* ... and add to cache. */
        update_cache(patch);
 
-       return crnt_size;
+       return 0;
 }
 
 static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
                                             size_t size)
 {
-       enum ucode_state ret = UCODE_ERROR;
-       unsigned int leftover;
        u8 *fw = (u8 *)data;
-       int crnt_size = 0;
        int offset;
 
        offset = install_equiv_cpu_table(data);
        if (offset < 0) {
                pr_err("failed to create equivalent cpu table\n");
-               return ret;
+               return UCODE_ERROR;
        }
-       fw += offset;
-       leftover = size - offset;
+       fw   += offset;
+       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;
+               return UCODE_ERROR;
        }
 
-       while (leftover) {
-               crnt_size = verify_and_add_patch(family, fw, leftover);
-               if (crnt_size < 0)
-                       return ret;
+       while (size > 0) {
+               unsigned int crnt_size = 0;
+               int ret;
+
+               ret = verify_and_add_patch(family, fw, size, &crnt_size);
+               if (ret < 0)
+                       return UCODE_ERROR;
 
-               fw       += crnt_size;
-               leftover -= crnt_size;
+               fw   +=  crnt_size + SECTION_HDR_SIZE;
+               size -= (crnt_size + SECTION_HDR_SIZE);
        }
 
        return UCODE_OK;

Reply via email to