From: Sean Christopherson sean.j.christopherson@intel.com
mainline inclusion from mainline-v5.11-rc1 commit cd072dab453a9b4a9f7927f9eddca5a156fbd87d category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I4SIGI CVE: NA
--------------------------------
vDSO exception fixup is a replacement for signals in limited situations. Signals and vDSO exception fixup need to provide similar information to userspace, including the hardware error code.
That hardware error code needs to be sanitized. For instance, if userspace accesses a kernel address, the error code could indicate to userspace whether the address had a Present=1 PTE. That can leak information about the kernel layout to userspace, which is bad.
The existing signal code does this sanitization, but fairly late in the signal process. The vDSO exception code runs before the sanitization happens.
Move error code sanitization out of the signal code and into a helper. Call the helper in the signal code.
Intel-SIG: commit cd072dab453a x86/fault: Add a helper function to sanitize error code. Backport summary: This is a dependency patch for CET preparation patch
Signed-off-by: Sean Christopherson sean.j.christopherson@intel.com Signed-off-by: Jarkko Sakkinen jarkko@kernel.org Signed-off-by: Borislav Petkov bp@suse.de Acked-by: Jethro Beekman jethro@fortanix.com Link: https://lkml.kernel.org/r/20201112220135.165028-18-jarkko@kernel.org Signed-off-by: Fan Du fan.du@intel.com #openEuler_contributor Signed-off-by: Laibin Qiu qiulaibin@huawei.com Reviewed-by: Bamvor Zhang bamvor.zhang@suse.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/x86/mm/fault.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 7b707c9b661a..e86cdbb9692e 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -610,11 +610,9 @@ pgtable_bad(struct pt_regs *regs, unsigned long error_code, oops_end(flags, regs, sig); }
-static void set_signal_archinfo(unsigned long address, - unsigned long error_code) +static void sanitize_error_code(unsigned long address, + unsigned long *error_code) { - struct task_struct *tsk = current; - /* * To avoid leaking information about the kernel page * table layout, pretend that user-mode accesses to @@ -625,7 +623,13 @@ static void set_signal_archinfo(unsigned long address, * information and does not appear to cause any problems. */ if (address >= TASK_SIZE_MAX) - error_code |= X86_PF_PROT; + *error_code |= X86_PF_PROT; +} + +static void set_signal_archinfo(unsigned long address, + unsigned long error_code) +{ + struct task_struct *tsk = current;
tsk->thread.trap_nr = X86_TRAP_PF; tsk->thread.error_code = error_code | X86_PF_USER; @@ -666,6 +670,8 @@ no_context(struct pt_regs *regs, unsigned long error_code, * faulting through the emulate_vsyscall() logic. */ if (current->thread.sig_on_uaccess_err && signal) { + sanitize_error_code(address, &error_code); + set_signal_archinfo(address, error_code);
/* XXX: hwpoison faults will set the wrong code. */ @@ -819,13 +825,7 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, if (is_errata100(regs, address)) return;
- /* - * To avoid leaking information about the kernel page table - * layout, pretend that user-mode accesses to kernel addresses - * are always protection faults. - */ - if (address >= TASK_SIZE_MAX) - error_code |= X86_PF_PROT; + sanitize_error_code(address, &error_code);
if (likely(show_unhandled_signals)) show_signal_msg(regs, error_code, address, tsk); @@ -944,6 +944,8 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, if (is_prefetch(regs, error_code, address)) return;
+ sanitize_error_code(address, &error_code); + set_signal_archinfo(address, error_code);
#ifdef CONFIG_MEMORY_FAILURE