162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#include <linux/uaccess.h> 462306a36Sopenharmony_ci#include <linux/kernel.h> 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <asm/vsyscall.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#ifdef CONFIG_X86_64 962306a36Sopenharmony_cibool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size) 1062306a36Sopenharmony_ci{ 1162306a36Sopenharmony_ci unsigned long vaddr = (unsigned long)unsafe_src; 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci /* 1462306a36Sopenharmony_ci * Do not allow userspace addresses. This disallows 1562306a36Sopenharmony_ci * normal userspace and the userspace guard page: 1662306a36Sopenharmony_ci */ 1762306a36Sopenharmony_ci if (vaddr < TASK_SIZE_MAX + PAGE_SIZE) 1862306a36Sopenharmony_ci return false; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci /* 2162306a36Sopenharmony_ci * Reading from the vsyscall page may cause an unhandled fault in 2262306a36Sopenharmony_ci * certain cases. Though it is at an address above TASK_SIZE_MAX, it is 2362306a36Sopenharmony_ci * usually considered as a user space address. 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ci if (is_vsyscall_vaddr(vaddr)) 2662306a36Sopenharmony_ci return false; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci /* 2962306a36Sopenharmony_ci * Allow everything during early boot before 'x86_virt_bits' 3062306a36Sopenharmony_ci * is initialized. Needed for instruction decoding in early 3162306a36Sopenharmony_ci * exception handlers. 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ci if (!boot_cpu_data.x86_virt_bits) 3462306a36Sopenharmony_ci return true; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci return __is_canonical_address(vaddr, boot_cpu_data.x86_virt_bits); 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci#else 3962306a36Sopenharmony_cibool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci return (unsigned long)unsafe_src >= TASK_SIZE_MAX; 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci#endif 44