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 Hellwigbool 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 Hellwigbool 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