xref: /openbmc/linux/arch/x86/mm/maccess.c (revision 5ee9cd065836e5934710ca35653bce7905add20b)
175a1a607SDaniel Borkmann // SPDX-License-Identifier: GPL-2.0-only
275a1a607SDaniel Borkmann 
375a1a607SDaniel Borkmann #include <linux/uaccess.h>
475a1a607SDaniel Borkmann #include <linux/kernel.h>
575a1a607SDaniel Borkmann 
6*57f78c46SHou Tao #include <asm/vsyscall.h>
7*57f78c46SHou Tao 
875a1a607SDaniel Borkmann #ifdef CONFIG_X86_64
copy_from_kernel_nofault_allowed(const void * unsafe_src,size_t size)9fe557319SChristoph Hellwig bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
1075a1a607SDaniel Borkmann {
11eab0c608SChristoph Hellwig 	unsigned long vaddr = (unsigned long)unsafe_src;
12eab0c608SChristoph Hellwig 
1375a1a607SDaniel Borkmann 	/*
1495846cd8SAdam Dunlap 	 * Do not allow userspace addresses.  This disallows
1595846cd8SAdam Dunlap 	 * normal userspace and the userspace guard page:
1675a1a607SDaniel Borkmann 	 */
1795846cd8SAdam Dunlap 	if (vaddr < TASK_SIZE_MAX + PAGE_SIZE)
1895846cd8SAdam Dunlap 		return false;
1995846cd8SAdam Dunlap 
2095846cd8SAdam Dunlap 	/*
21*57f78c46SHou Tao 	 * Reading from the vsyscall page may cause an unhandled fault in
22*57f78c46SHou Tao 	 * certain cases.  Though it is at an address above TASK_SIZE_MAX, it is
23*57f78c46SHou Tao 	 * usually considered as a user space address.
24*57f78c46SHou Tao 	 */
25*57f78c46SHou Tao 	if (is_vsyscall_vaddr(vaddr))
26*57f78c46SHou Tao 		return false;
27*57f78c46SHou Tao 
28*57f78c46SHou Tao 	/*
2995846cd8SAdam Dunlap 	 * Allow everything during early boot before 'x86_virt_bits'
3095846cd8SAdam Dunlap 	 * is initialized.  Needed for instruction decoding in early
3195846cd8SAdam Dunlap 	 * exception handlers.
3295846cd8SAdam Dunlap 	 */
3395846cd8SAdam Dunlap 	if (!boot_cpu_data.x86_virt_bits)
3495846cd8SAdam Dunlap 		return true;
3595846cd8SAdam Dunlap 
3695846cd8SAdam Dunlap 	return __is_canonical_address(vaddr, boot_cpu_data.x86_virt_bits);
3775a1a607SDaniel Borkmann }
3875a1a607SDaniel Borkmann #else
copy_from_kernel_nofault_allowed(const void * unsafe_src,size_t size)39fe557319SChristoph Hellwig bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
4075a1a607SDaniel Borkmann {
41eab0c608SChristoph Hellwig 	return (unsigned long)unsafe_src >= TASK_SIZE_MAX;
4275a1a607SDaniel Borkmann }
4375a1a607SDaniel Borkmann #endif
44