diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index 9e3ac95acf2d..78796b98a544 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -96,6 +96,6 @@ static inline bool intel_cpu_signatures_match(unsigned int s1, unsigned int p1, extern u64 x86_read_arch_cap_msr(void); int intel_find_matching_signature(void *mc, unsigned int csig, int cpf); -int intel_microcode_sanity_check(void *mc, bool print_err); +int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type); #endif /* _ASM_X86_CPU_H */ diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/microcode_intel.h index 4c92cea7e4b5..2a999bf91ef0 100644 --- a/arch/x86/include/asm/microcode_intel.h +++ b/arch/x86/include/asm/microcode_intel.h @@ -41,6 +41,7 @@ struct extended_sigtable { #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) #define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) #define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) +#define MC_HEADER_TYPE_MICROCODE 1 #define get_totalsize(mc) \ (((struct microcode_intel *)mc)->hdr.datasize ? \ diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index bef06a1fafe9..b6997eb6e519 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -244,7 +244,21 @@ int intel_find_matching_signature(void *mc, unsigned int csig, int cpf) } EXPORT_SYMBOL_GPL(intel_find_matching_signature); -int intel_microcode_sanity_check(void *mc, bool print_err) +/** + * intel_microcode_sanity_check() - Sanity check microcode file. + * @mc: Pointer to the microcode file contents. + * @print_err: Display failure reason if true, silent if false. + * @hdr_type: Type of file, i.e. normal microcode file or In Field Scan file. + * Validate if the microcode header type matches with the type + * specified here. + * + * Validate certain header fields and verify if computed checksum matches + * with the one specified in the header. + * + * Return: 0 if the file passes all the checks, -EINVAL if any of the checks + * fail. + */ +int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type) { unsigned long total_size, data_size, ext_table_size; struct microcode_header_intel *mc_header = mc; @@ -261,9 +275,10 @@ int intel_microcode_sanity_check(void *mc, bool print_err) return -EINVAL; } - if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { + if (mc_header->ldrver != 1 || mc_header->hdrver != hdr_type) { if (print_err) - pr_err("Error: invalid/unknown microcode update format.\n"); + pr_err("Error: invalid/unknown microcode update format. Header type %d\n", + mc_header->hdrver); return -EINVAL; } diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index fb6ff71a5ff5..c4a00fb97f61 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -155,7 +155,7 @@ scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save) mc_size = get_totalsize(mc_header); if (!mc_size || mc_size > size || - intel_microcode_sanity_check(data, false) < 0) + intel_microcode_sanity_check(data, false, MC_HEADER_TYPE_MICROCODE) < 0) break; size -= mc_size; @@ -694,7 +694,7 @@ static enum ucode_state generic_load_microcode(int cpu, struct iov_iter *iter) memcpy(mc, &mc_header, sizeof(mc_header)); data = mc + sizeof(mc_header); if (!copy_from_iter_full(data, data_size, iter) || - intel_microcode_sanity_check(mc, true) < 0) { + intel_microcode_sanity_check(mc, true, MC_HEADER_TYPE_MICROCODE) < 0) { break; }