From fb46e9f7bd639b60cbb26e1efbd4d19e65115c0b Mon Sep 17 00:00:00 2001 From: sanglipeng Date: Wed, 22 Nov 2023 18:41:41 +0800 Subject: [PATCH] Revert "x86/microcode: Rip out the OLD_INTERFACE" stable inclusion from stable-v5.10.173 commit 9e56938f207241512aab787b17c88c96dc150b90 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8IOCW CVE: NA Reference: https://github.com/torvalds/linux/commit/9e56938f207241512aab787b17c88c96dc150b90 -------------------------------- This reverts commit ab873cbbab393da2ee7aa047cb8d5401cffc5a94. Signed-off-by: sanglipeng Conflicts: arch/x86/Kconfig --- arch/x86/Kconfig | 12 ++++ arch/x86/kernel/cpu/microcode/core.c | 100 +++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index f8e6060eaeb7..64567773fc55 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1347,6 +1347,18 @@ config MICROCODE_LATE_LOADING not guarantee that cores might not softlock after the loading. Therefore, use this at your own risk. Late loading taints the kernel too. +config MICROCODE_OLD_INTERFACE + bool "Ancient loading interface (DEPRECATED)" + default n + depends on MICROCODE + help + DO NOT USE THIS! This is the ancient /dev/cpu/microcode interface + which was used by userspace tools like iucode_tool and microcode.ctl. + It is inadequate because it runs too late to be able to properly + load microcode on a machine and it needs special tools. Instead, you + should've switched to the early loading method with the initrd or + builtin microcode by now: Documentation/x86/microcode.rst + config X86_MSR tristate "/dev/cpu/*/msr - Model-specific register support" help diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index 707a385943b4..ef814e28f7ae 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -390,6 +390,98 @@ static int apply_microcode_on_target(int cpu) return ret; } +#ifdef CONFIG_MICROCODE_OLD_INTERFACE +static int do_microcode_update(const void __user *buf, size_t size) +{ + int error = 0; + int cpu; + + for_each_online_cpu(cpu) { + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + enum ucode_state ustate; + + if (!uci->valid) + continue; + + ustate = microcode_ops->request_microcode_user(cpu, buf, size); + if (ustate == UCODE_ERROR) { + error = -1; + break; + } else if (ustate == UCODE_NEW) { + apply_microcode_on_target(cpu); + } + } + + return error; +} + +static int microcode_open(struct inode *inode, struct file *file) +{ + return capable(CAP_SYS_RAWIO) ? stream_open(inode, file) : -EPERM; +} + +static ssize_t microcode_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) +{ + ssize_t ret = -EINVAL; + unsigned long nr_pages = totalram_pages(); + + if ((len >> PAGE_SHIFT) > nr_pages) { + pr_err("too much data (max %ld pages)\n", nr_pages); + return ret; + } + + cpus_read_lock(); + mutex_lock(µcode_mutex); + + if (do_microcode_update(buf, len) == 0) + ret = (ssize_t)len; + + if (ret > 0) + perf_check_microcode(); + + mutex_unlock(µcode_mutex); + cpus_read_unlock(); + + return ret; +} + +static const struct file_operations microcode_fops = { + .owner = THIS_MODULE, + .write = microcode_write, + .open = microcode_open, + .llseek = no_llseek, +}; + +static struct miscdevice microcode_dev = { + .minor = MICROCODE_MINOR, + .name = "microcode", + .nodename = "cpu/microcode", + .fops = µcode_fops, +}; + +static int __init microcode_dev_init(void) +{ + int error; + + error = misc_register(µcode_dev); + if (error) { + pr_err("can't misc_register on minor=%d\n", MICROCODE_MINOR); + return error; + } + + return 0; +} + +static void __exit microcode_dev_exit(void) +{ + misc_deregister(µcode_dev); +} +#else +#define microcode_dev_init() 0 +#define microcode_dev_exit() do { } while (0) +#endif + /* fake device for request_firmware */ static struct platform_device *microcode_pdev; @@ -787,6 +879,10 @@ int __init microcode_init(void) goto out_driver; } + error = microcode_dev_init(); + if (error) + goto out_ucode_group; + register_syscore_ops(&mc_syscore_ops); cpuhp_setup_state_nocalls(CPUHP_AP_MICROCODE_LOADER, "x86/microcode:starting", mc_cpu_starting, NULL); @@ -797,6 +893,10 @@ int __init microcode_init(void) return 0; + out_ucode_group: + sysfs_remove_group(&cpu_subsys.dev_root->kobj, + &cpu_root_microcode_group); + out_driver: cpus_read_lock(); mutex_lock(µcode_mutex); -- Gitee