Re: [PATCH] [42/106] x86, microcode, AMD: Extend ucode size verification

From: Paul Gortmaker
Date: Tue Apr 26 2011 - 18:44:12 EST


On Tue, Apr 26, 2011 at 5:13 PM, Andi Kleen <andi@xxxxxxxxxxxxxx> wrote:
> 2.6.35-longterm review patch.  If anyone has any objections, please let me know.

Minor nit, but git am complains about whitespace in this backport. I checked
the original, and at a glance it looks OK in this respect.

(42/106) Applying: x86, microcode, AMD: Extend ucode size verification
/home/paul/git/stable/linux-2.6.35.y/.git/rebase-apply/patch:95: space
before tab in indent.
return NULL;
/home/paul/git/stable/linux-2.6.35.y/.git/rebase-apply/patch:100:
trailing whitespace.

warning: 2 lines add whitespace errors.

Paul.

>
> ------------------
>
> From: Borislav Petkov <borislav.petkov@xxxxxxx>
>
> Upstream commit: 44d60c0f5c58c2168f31df9a481761451840eb54
>
> 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.
>
> Cc: <stable@xxxxxxxxxx>
> Signed-off-by: Borislav Petkov <borislav.petkov@xxxxxxx>
> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>
> Signed-off-by: Andi Kleen <ak@xxxxxxxxxxxxxxx>
>
> ---
>  arch/x86/kernel/microcode_amd.c |   63 +++++++++++++++++++++++++++-------------
>  1 file changed, 44 insertions(+), 19 deletions(-)
>
> Index: linux-2.6.35.y/arch/x86/kernel/microcode_amd.c
> ===================================================================
> --- linux-2.6.35.y.orig/arch/x86/kernel/microcode_amd.c
> +++ linux-2.6.35.y/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
>
> @@ -125,6 +124,37 @@ static int get_matching_microcode(int cp
>        return 1;
>  }
>
> +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 int apply_microcode_amd(int cpu)
>  {
>        u32 rev, dummy;
> @@ -162,11 +192,11 @@ static int get_ucode_data(void *to, cons
>  }
>
>  static void *
> -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)
>  {
> -       unsigned int total_size;
> +       unsigned int actual_size = 0;
>        u8 section_hdr[UCODE_CONTAINER_SECTION_HDR];
> -       void *mc;
> +       void *mc = NULL;
>
>        if (get_ucode_data(section_hdr, buf, UCODE_CONTAINER_SECTION_HDR))
>                return NULL;
> @@ -176,23 +206,18 @@ get_next_ucode(const u8 *buf, unsigned i
>                return NULL;
>        }
>
> -       total_size = (unsigned long) (section_hdr[4] + (section_hdr[5] << 8));
> -
> -       if (total_size > size || total_size > UCODE_MAX_SIZE) {
> -               pr_err("error: size mismatch\n");
> +       actual_size = verify_ucode_size(cpu, buf, size);
> +       if (!actual_size)
>                return NULL;
> -       }
>
> -       mc = vmalloc(UCODE_MAX_SIZE);
> -       if (mc) {
> -               memset(mc, 0, UCODE_MAX_SIZE);
> -               if (get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR,
> -                                  total_size)) {
> -                       vfree(mc);
> -                       mc = NULL;
> -               } else
> -                       *mc_size = total_size + UCODE_CONTAINER_SECTION_HDR;
> -       }
> +       mc = vmalloc(actual_size);
> +       if (!mc)
> +               return NULL;
> +
> +       memset(mc, 0, actual_size);
> +       get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, actual_size);
> +       *mc_size = actual_size + UCODE_CONTAINER_SECTION_HDR;
> +
>        return mc;
>  }
>
> @@ -258,7 +283,7 @@ generic_load_microcode(int cpu, const u8
>                unsigned int uninitialized_var(mc_size);
>                struct microcode_header_amd *mc_header;
>
> -               mc = get_next_ucode(ucode_ptr, leftover, &mc_size);
> +               mc = get_next_ucode(cpu, ucode_ptr, leftover, &mc_size);
>                if (!mc)
>                        break;
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/