From: Maciej S. Szmigiero Date: Tue, 19 Jun 2018 18:47:32 +0000 (+0200) Subject: x86/microcode/AMD: Add microcode container verification X-Git-Tag: v5.15~7357^2~14 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f4ff25916c1186912e1b53c25861c8abc9f15687;p=platform%2Fkernel%2Flinux-starfive.git x86/microcode/AMD: Add microcode container verification Add container and patch verification functions to the AMD microcode update driver. These functions check whether a passed buffer contains the relevant structure, whether it isn't truncated and (for actual microcode patches) whether the size of a patch is not too large for a particular CPU family. By adding these checks as separate functions the actual microcode loading code won't get interspersed with a lot of checks and so will be more readable. [ bp: Make all pr_err() calls into pr_debug() and drop the verify_patch() bits. ] Signed-off-by: Maciej S. Szmigiero Signed-off-by: Borislav Petkov Cc: x86-ml Link: http://lkml.kernel.org/r/3014e96c82cd90761b4601bd2cfe59c4119e46a7.1529424596.git.mail@maciej.szmigiero.name --- diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index b44c902..36aeb01 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -74,6 +74,107 @@ static u16 find_equiv_id(struct equiv_cpu_entry *equiv_table, u32 sig) } /* + * Check whether there is a valid microcode container file at the beginning + * of @buf of size @buf_size. Set @early to use this function in the early path. + */ +static bool verify_container(const u8 *buf, size_t buf_size, bool early) +{ + u32 cont_magic; + + if (buf_size <= CONTAINER_HDR_SZ) { + if (!early) + pr_debug("Truncated microcode container header.\n"); + + return false; + } + + cont_magic = *(const u32 *)buf; + if (cont_magic != UCODE_MAGIC) { + if (!early) + pr_debug("Invalid magic value (0x%08x).\n", cont_magic); + + return false; + } + + return true; +} + +/* + * Check whether there is a valid, non-truncated CPU equivalence table at the + * beginning of @buf of size @buf_size. Set @early to use this function in the + * early path. + */ +static bool verify_equivalence_table(const u8 *buf, size_t buf_size, bool early) +{ + const u32 *hdr = (const u32 *)buf; + u32 cont_type, equiv_tbl_len; + + if (!verify_container(buf, buf_size, early)) + return false; + + cont_type = hdr[1]; + if (cont_type != UCODE_EQUIV_CPU_TABLE_TYPE) { + if (!early) + pr_debug("Wrong microcode container equivalence table type: %u.\n", + cont_type); + + return false; + } + + buf_size -= CONTAINER_HDR_SZ; + + equiv_tbl_len = hdr[2]; + if (equiv_tbl_len < sizeof(struct equiv_cpu_entry) || + buf_size < equiv_tbl_len) { + if (!early) + pr_debug("Truncated equivalence table.\n"); + + return false; + } + + return true; +} + +/* + * Check whether there is a valid, non-truncated microcode patch section at the + * beginning of @buf of size @buf_size. Set @early to use this function in the + * early path. + */ +static bool verify_patch_section(const u8 *buf, size_t buf_size, bool early) +{ + const u32 *hdr; + u32 patch_type, patch_size; + + if (buf_size < SECTION_HDR_SIZE) { + if (!early) + pr_debug("Truncated patch section.\n"); + + return false; + } + + hdr = (const u32 *)buf; + patch_type = hdr[0]; + patch_size = hdr[1]; + + if (patch_type != UCODE_UCODE_TYPE) { + if (!early) + pr_debug("Invalid type field (0x%x) in container file section header.\n", + patch_type); + + return false; + } + + if (patch_size < sizeof(struct microcode_header_amd)) { + if (!early) + pr_debug("Patch of size %u too short.\n", patch_size); + + return false; + } + + return true; +} + +/* * This scans the ucode blob for the proper container as we can have multiple * containers glued together. Returns the equivalence ID from the equivalence * table or 0 if none found.