mirror of
https://github.com/torvalds/linux.git
synced 2024-12-12 22:23:55 +00:00
x86/microcode/intel: Reuse microcode_sanity_check()
IFS test image carries the same microcode header as regular Intel microcode blobs. Reuse microcode_sanity_check() in the IFS driver to perform sanity check of the IFS test images too. Signed-off-by: Jithu Joseph <jithu.joseph@intel.com> Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: Tony Luck <tony.luck@intel.com> Reviewed-by: Ashok Raj <ashok.raj@intel.com> Reviewed-by: Sohil Mehta <sohil.mehta@intel.com> Link: https://lore.kernel.org/r/20221117035935.4136738-8-jithu.joseph@intel.com
This commit is contained in:
parent
2e13ab0158
commit
514ee839c6
@ -96,5 +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);
|
||||
|
||||
#endif /* _ASM_X86_CPU_H */
|
||||
|
@ -244,6 +244,105 @@ 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)
|
||||
{
|
||||
unsigned long total_size, data_size, ext_table_size;
|
||||
struct microcode_header_intel *mc_header = mc;
|
||||
struct extended_sigtable *ext_header = NULL;
|
||||
u32 sum, orig_sum, ext_sigcount = 0, i;
|
||||
struct extended_signature *ext_sig;
|
||||
|
||||
total_size = get_totalsize(mc_header);
|
||||
data_size = get_datasize(mc_header);
|
||||
|
||||
if (data_size + MC_HEADER_SIZE > total_size) {
|
||||
if (print_err)
|
||||
pr_err("Error: bad microcode data file size.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
|
||||
if (print_err)
|
||||
pr_err("Error: invalid/unknown microcode update format.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
|
||||
if (ext_table_size) {
|
||||
u32 ext_table_sum = 0;
|
||||
u32 *ext_tablep;
|
||||
|
||||
if (ext_table_size < EXT_HEADER_SIZE ||
|
||||
((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
|
||||
if (print_err)
|
||||
pr_err("Error: truncated extended signature table.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ext_header = mc + MC_HEADER_SIZE + data_size;
|
||||
if (ext_table_size != exttable_size(ext_header)) {
|
||||
if (print_err)
|
||||
pr_err("Error: extended signature table size mismatch.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ext_sigcount = ext_header->count;
|
||||
|
||||
/*
|
||||
* Check extended table checksum: the sum of all dwords that
|
||||
* comprise a valid table must be 0.
|
||||
*/
|
||||
ext_tablep = (u32 *)ext_header;
|
||||
|
||||
i = ext_table_size / sizeof(u32);
|
||||
while (i--)
|
||||
ext_table_sum += ext_tablep[i];
|
||||
|
||||
if (ext_table_sum) {
|
||||
if (print_err)
|
||||
pr_warn("Bad extended signature table checksum, aborting.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the checksum of update data and header. The checksum of
|
||||
* valid update data and header including the extended signature table
|
||||
* must be 0.
|
||||
*/
|
||||
orig_sum = 0;
|
||||
i = (MC_HEADER_SIZE + data_size) / sizeof(u32);
|
||||
while (i--)
|
||||
orig_sum += ((u32 *)mc)[i];
|
||||
|
||||
if (orig_sum) {
|
||||
if (print_err)
|
||||
pr_err("Bad microcode data checksum, aborting.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!ext_table_size)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Check extended signature checksum: 0 => valid.
|
||||
*/
|
||||
for (i = 0; i < ext_sigcount; i++) {
|
||||
ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
|
||||
EXT_SIGNATURE_SIZE * i;
|
||||
|
||||
sum = (mc_header->sig + mc_header->pf + mc_header->cksum) -
|
||||
(ext_sig->sig + ext_sig->pf + ext_sig->cksum);
|
||||
if (sum) {
|
||||
if (print_err)
|
||||
pr_err("Bad extended signature checksum, aborting.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_microcode_sanity_check);
|
||||
|
||||
static void early_init_intel(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u64 misc_enable;
|
||||
|
@ -135,104 +135,6 @@ static void save_microcode_patch(struct ucode_cpu_info *uci, void *data, unsigne
|
||||
intel_ucode_patch = p->data;
|
||||
}
|
||||
|
||||
static int microcode_sanity_check(void *mc, bool print_err)
|
||||
{
|
||||
unsigned long total_size, data_size, ext_table_size;
|
||||
struct microcode_header_intel *mc_header = mc;
|
||||
struct extended_sigtable *ext_header = NULL;
|
||||
u32 sum, orig_sum, ext_sigcount = 0, i;
|
||||
struct extended_signature *ext_sig;
|
||||
|
||||
total_size = get_totalsize(mc_header);
|
||||
data_size = get_datasize(mc_header);
|
||||
|
||||
if (data_size + MC_HEADER_SIZE > total_size) {
|
||||
if (print_err)
|
||||
pr_err("Error: bad microcode data file size.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
|
||||
if (print_err)
|
||||
pr_err("Error: invalid/unknown microcode update format.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
|
||||
if (ext_table_size) {
|
||||
u32 ext_table_sum = 0;
|
||||
u32 *ext_tablep;
|
||||
|
||||
if ((ext_table_size < EXT_HEADER_SIZE)
|
||||
|| ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
|
||||
if (print_err)
|
||||
pr_err("Error: truncated extended signature table.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ext_header = mc + MC_HEADER_SIZE + data_size;
|
||||
if (ext_table_size != exttable_size(ext_header)) {
|
||||
if (print_err)
|
||||
pr_err("Error: extended signature table size mismatch.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ext_sigcount = ext_header->count;
|
||||
|
||||
/*
|
||||
* Check extended table checksum: the sum of all dwords that
|
||||
* comprise a valid table must be 0.
|
||||
*/
|
||||
ext_tablep = (u32 *)ext_header;
|
||||
|
||||
i = ext_table_size / sizeof(u32);
|
||||
while (i--)
|
||||
ext_table_sum += ext_tablep[i];
|
||||
|
||||
if (ext_table_sum) {
|
||||
if (print_err)
|
||||
pr_warn("Bad extended signature table checksum, aborting.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the checksum of update data and header. The checksum of
|
||||
* valid update data and header including the extended signature table
|
||||
* must be 0.
|
||||
*/
|
||||
orig_sum = 0;
|
||||
i = (MC_HEADER_SIZE + data_size) / sizeof(u32);
|
||||
while (i--)
|
||||
orig_sum += ((u32 *)mc)[i];
|
||||
|
||||
if (orig_sum) {
|
||||
if (print_err)
|
||||
pr_err("Bad microcode data checksum, aborting.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!ext_table_size)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Check extended signature checksum: 0 => valid.
|
||||
*/
|
||||
for (i = 0; i < ext_sigcount; i++) {
|
||||
ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
|
||||
EXT_SIGNATURE_SIZE * i;
|
||||
|
||||
sum = (mc_header->sig + mc_header->pf + mc_header->cksum) -
|
||||
(ext_sig->sig + ext_sig->pf + ext_sig->cksum);
|
||||
if (sum) {
|
||||
if (print_err)
|
||||
pr_err("Bad extended signature checksum, aborting.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get microcode matching with BSP's model. Only CPUs with the same model as
|
||||
* BSP can stay in the platform.
|
||||
@ -253,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 ||
|
||||
microcode_sanity_check(data, false) < 0)
|
||||
intel_microcode_sanity_check(data, false) < 0)
|
||||
break;
|
||||
|
||||
size -= mc_size;
|
||||
@ -792,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) ||
|
||||
microcode_sanity_check(mc, true) < 0) {
|
||||
intel_microcode_sanity_check(mc, true) < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user