Olivier Deprez | 157378f | 2022-04-04 15:47:50 +0200 | [diff] [blame^] | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | |
| 3 | #include <linux/uaccess.h> |
| 4 | #include <linux/kernel.h> |
| 5 | |
| 6 | #ifdef CONFIG_X86_64 |
| 7 | static __always_inline u64 canonical_address(u64 vaddr, u8 vaddr_bits) |
| 8 | { |
| 9 | return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits); |
| 10 | } |
| 11 | |
| 12 | bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size) |
| 13 | { |
| 14 | unsigned long vaddr = (unsigned long)unsafe_src; |
| 15 | |
| 16 | /* |
| 17 | * Range covering the highest possible canonical userspace address |
| 18 | * as well as non-canonical address range. For the canonical range |
| 19 | * we also need to include the userspace guard page. |
| 20 | */ |
| 21 | return vaddr >= TASK_SIZE_MAX + PAGE_SIZE && |
| 22 | canonical_address(vaddr, boot_cpu_data.x86_virt_bits) == vaddr; |
| 23 | } |
| 24 | #else |
| 25 | bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size) |
| 26 | { |
| 27 | return (unsigned long)unsafe_src >= TASK_SIZE_MAX; |
| 28 | } |
| 29 | #endif |