Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

uaccess: generalize access_ok()

There are many different ways that access_ok() is defined across
architectures, but in the end, they all just compare against the
user_addr_max() value or they accept anything.

Provide one definition that works for most architectures, checking
against TASK_SIZE_MAX for user processes or skipping the check inside
of uaccess_kernel() sections.

For architectures without CONFIG_SET_FS(), this should be the fastest
check, as it comes down to a single comparison of a pointer against a
compile-time constant, while the architecture specific versions tend to
do something more complex for historic reasons or get something wrong.

Type checking for __user annotations is handled inconsistently across
architectures, but this is easily simplified as well by using an inline
function that takes a 'const void __user *' argument. A handful of
callers need an extra __user annotation for this.

Some architectures had trick to use 33-bit or 65-bit arithmetic on the
addresses to calculate the overflow, however this simpler version uses
fewer registers, which means it can produce better object code in the
end despite needing a second (statically predicted) branch.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Acked-by: Mark Rutland <mark.rutland@arm.com> [arm64, asm-generic]
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Stafford Horne <shorne@gmail.com>
Acked-by: Dinh Nguyen <dinguyen@kernel.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+110 -362
+7
arch/Kconfig
··· 898 898 Architecture provides a function to run __do_softirq() on a 899 899 separate stack. 900 900 901 + config ALTERNATE_USER_ADDRESS_SPACE 902 + bool 903 + help 904 + Architectures set this when the CPU uses separate address 905 + spaces for kernel and user space pointers. In this case, the 906 + access_ok() check on a __user pointer is skipped. 907 + 901 908 config PGTABLE_LEVELS 902 909 int 903 910 default 2
+5 -29
arch/alpha/include/asm/uaccess.h
··· 20 20 #define get_fs() (current_thread_info()->addr_limit) 21 21 #define set_fs(x) (current_thread_info()->addr_limit = (x)) 22 22 23 - #define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) 24 - 25 - /* 26 - * Is a address valid? This does a straightforward calculation rather 27 - * than tests. 28 - * 29 - * Address valid if: 30 - * - "addr" doesn't have any high-bits set 31 - * - AND "size" doesn't have any high-bits set 32 - * - AND "addr+size-(size != 0)" doesn't have any high-bits set 33 - * - OR we are in kernel mode. 34 - */ 35 - #define __access_ok(addr, size) ({ \ 36 - unsigned long __ao_a = (addr), __ao_b = (size); \ 37 - unsigned long __ao_end = __ao_a + __ao_b - !!__ao_b; \ 38 - (get_fs().seg & (__ao_a | __ao_b | __ao_end)) == 0; }) 39 - 40 - #define access_ok(addr, size) \ 41 - ({ \ 42 - __chk_user_ptr(addr); \ 43 - __access_ok(((unsigned long)(addr)), (size)); \ 44 - }) 23 + #include <asm-generic/access_ok.h> 45 24 46 25 /* 47 26 * These are the main single-value transfer routines. They automatically ··· 84 105 long __gu_err = -EFAULT; \ 85 106 unsigned long __gu_val = 0; \ 86 107 const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ 87 - if (__access_ok((unsigned long)__gu_addr, size)) { \ 108 + if (__access_ok(__gu_addr, size)) { \ 88 109 __gu_err = 0; \ 89 110 switch (size) { \ 90 111 case 1: __get_user_8(__gu_addr); break; \ ··· 179 200 ({ \ 180 201 long __pu_err = -EFAULT; \ 181 202 __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ 182 - if (__access_ok((unsigned long)__pu_addr, size)) { \ 203 + if (__access_ok(__pu_addr, size)) { \ 183 204 __pu_err = 0; \ 184 205 switch (size) { \ 185 206 case 1: __put_user_8(x, __pu_addr); break; \ ··· 295 316 296 317 extern long __clear_user(void __user *to, long len); 297 318 298 - extern inline long 319 + static inline long 299 320 clear_user(void __user *to, long len) 300 321 { 301 - if (__access_ok((unsigned long)to, len)) 322 + if (__access_ok(to, len)) 302 323 len = __clear_user(to, len); 303 324 return len; 304 325 } 305 - 306 - #define user_addr_max() \ 307 - (uaccess_kernel() ? ~0UL : TASK_SIZE) 308 326 309 327 extern long strncpy_from_user(char *dest, const char __user *src, long count); 310 328 extern __must_check long strnlen_user(const char __user *str, long n);
-29
arch/arc/include/asm/uaccess.h
··· 23 23 24 24 #include <linux/string.h> /* for generic string functions */ 25 25 26 - 27 - #define __kernel_ok (uaccess_kernel()) 28 - 29 - /* 30 - * Algorithmically, for __user_ok() we want do: 31 - * (start < TASK_SIZE) && (start+len < TASK_SIZE) 32 - * where TASK_SIZE could either be retrieved from thread_info->addr_limit or 33 - * emitted directly in code. 34 - * 35 - * This can however be rewritten as follows: 36 - * (len <= TASK_SIZE) && (start+len < TASK_SIZE) 37 - * 38 - * Because it essentially checks if buffer end is within limit and @len is 39 - * non-ngeative, which implies that buffer start will be within limit too. 40 - * 41 - * The reason for rewriting being, for majority of cases, @len is generally 42 - * compile time constant, causing first sub-expression to be compile time 43 - * subsumed. 44 - * 45 - * The second part would generate weird large LIMMs e.g. (0x6000_0000 - 0x10), 46 - * so we check for TASK_SIZE using get_fs() since the addr_limit load from mem 47 - * would already have been done at this call site for __kernel_ok() 48 - * 49 - */ 50 - #define __user_ok(addr, sz) (((sz) <= TASK_SIZE) && \ 51 - ((addr) <= (get_fs() - (sz)))) 52 - #define __access_ok(addr, sz) (unlikely(__kernel_ok) || \ 53 - likely(__user_ok((addr), (sz)))) 54 - 55 26 /*********** Single byte/hword/word copies ******************/ 56 27 57 28 #define __get_user_fn(sz, u, k) \
+1 -19
arch/arm/include/asm/uaccess.h
··· 56 56 #ifdef CONFIG_MMU 57 57 58 58 /* 59 - * We use 33-bit arithmetic here. Success returns zero, failure returns 60 - * addr_limit. We take advantage that addr_limit will be zero for KERNEL_DS, 61 - * so this will always return success in that case. 62 - */ 63 - #define __range_ok(addr, size) ({ \ 64 - unsigned long flag, roksum; \ 65 - __chk_user_ptr(addr); \ 66 - __asm__(".syntax unified\n" \ 67 - "adds %1, %2, %3; sbcscc %1, %1, %0; movcc %0, #0" \ 68 - : "=&r" (flag), "=&r" (roksum) \ 69 - : "r" (addr), "Ir" (size), "0" (TASK_SIZE) \ 70 - : "cc"); \ 71 - flag; }) 72 - 73 - /* 74 59 * This is a type: either unsigned long, if the argument fits into 75 60 * that type, or otherwise unsigned long long. 76 61 */ ··· 226 241 227 242 #else /* CONFIG_MMU */ 228 243 229 - #define __addr_ok(addr) ((void)(addr), 1) 230 - #define __range_ok(addr, size) ((void)(addr), 0) 231 - 232 244 #define get_user(x, p) __get_user(x, p) 233 245 #define __put_user_check __put_user_nocheck 234 246 235 247 #endif /* CONFIG_MMU */ 236 248 237 - #define access_ok(addr, size) (__range_ok(addr, size) == 0) 249 + #include <asm-generic/access_ok.h> 238 250 239 251 #ifdef CONFIG_CPU_SPECTRE 240 252 /*
+4 -7
arch/arm64/include/asm/uaccess.h
··· 26 26 #include <asm/memory.h> 27 27 #include <asm/extable.h> 28 28 29 - static inline int __access_ok(const void __user *ptr, unsigned long size) 30 - { 31 - unsigned long limit = TASK_SIZE_MAX; 32 - unsigned long addr = (unsigned long)ptr; 33 - 34 - return (size <= limit) && (addr <= (limit - size)); 35 - } 29 + static inline int __access_ok(const void __user *ptr, unsigned long size); 36 30 37 31 /* 38 32 * Test whether a block of memory is a valid user space address. ··· 48 54 49 55 return likely(__access_ok(addr, size)); 50 56 } 57 + #define access_ok access_ok 58 + 59 + #include <asm-generic/access_ok.h> 51 60 52 61 /* 53 62 * User access enabling/disabling.
-8
arch/csky/include/asm/uaccess.h
··· 5 5 6 6 #define user_addr_max() (current_thread_info()->addr_limit.seg) 7 7 8 - static inline int __access_ok(unsigned long addr, unsigned long size) 9 - { 10 - unsigned long limit = user_addr_max(); 11 - 12 - return (size <= limit) && (addr <= (limit - size)); 13 - } 14 - #define __access_ok __access_ok 15 - 16 8 /* 17 9 * __put_user_fn 18 10 */
-25
arch/hexagon/include/asm/uaccess.h
··· 13 13 #include <asm/sections.h> 14 14 15 15 /* 16 - * access_ok: - Checks if a user space pointer is valid 17 - * @addr: User space pointer to start of block to check 18 - * @size: Size of block to check 19 - * 20 - * Context: User context only. This function may sleep if pagefaults are 21 - * enabled. 22 - * 23 - * Checks if a pointer to a block of memory in user space is valid. 24 - * 25 - * Returns true (nonzero) if the memory block *may* be valid, false (zero) 26 - * if it is definitely invalid. 27 - * 28 - */ 29 - #define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) 30 - #define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE) 31 - 32 - static inline int __access_ok(unsigned long addr, unsigned long size) 33 - { 34 - unsigned long limit = TASK_SIZE; 35 - 36 - return (size <= limit) && (addr <= (limit - size)); 37 - } 38 - #define __access_ok __access_ok 39 - 40 - /* 41 16 * When a kernel-mode page fault is taken, the faulting instruction 42 17 * address is checked against a table of exception_table_entries. 43 18 * Each entry is a tuple of the address of an instruction that may
+2 -3
arch/ia64/include/asm/uaccess.h
··· 50 50 #define get_fs() (current_thread_info()->addr_limit) 51 51 #define set_fs(x) (current_thread_info()->addr_limit = (x)) 52 52 53 - #define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) 54 - 55 53 /* 56 54 * When accessing user memory, we need to make sure the entire area really is in 57 55 * user-level space. In order to do this efficiently, we make sure that the page at ··· 63 65 return likely(addr <= seg) && 64 66 (seg == KERNEL_DS.seg || likely(REGION_OFFSET(addr) < RGN_MAP_LIMIT)); 65 67 } 66 - #define access_ok(addr, size) __access_ok((addr), (size)) 68 + #define __access_ok __access_ok 69 + #include <asm-generic/access_ok.h> 67 70 68 71 /* 69 72 * These are the main single-value transfer routines. They automatically
+1
arch/m68k/Kconfig.cpu
··· 453 453 454 454 config CPU_HAS_ADDRESS_SPACES 455 455 bool 456 + select ALTERNATE_USER_ADDRESS_SPACE 456 457 457 458 config FPU 458 459 bool
+1 -14
arch/m68k/include/asm/uaccess.h
··· 10 10 #include <linux/compiler.h> 11 11 #include <linux/types.h> 12 12 #include <asm/extable.h> 13 - 14 - /* We let the MMU do all checking */ 15 - static inline int access_ok(const void __user *ptr, 16 - unsigned long size) 17 - { 18 - unsigned long limit = TASK_SIZE; 19 - unsigned long addr = (unsigned long)ptr; 20 - 21 - if (IS_ENABLED(CONFIG_CPU_HAS_ADDRESS_SPACES) || 22 - !IS_ENABLED(CONFIG_MMU)) 23 - return 1; 24 - 25 - return (size <= limit) && (addr <= (limit - size)); 26 - } 13 + #include <asm-generic/access_ok.h> 27 14 28 15 /* 29 16 * Not all varients of the 68k family support the notion of address spaces.
+1 -7
arch/microblaze/include/asm/uaccess.h
··· 39 39 40 40 # define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) 41 41 42 - static inline int __access_ok(unsigned long addr, unsigned long size) 43 - { 44 - unsigned long limit = user_addr_max(); 45 - 46 - return (size <= limit) && (addr <= (limit - size)); 47 - } 48 - #define access_ok(addr, size) __access_ok((unsigned long)addr, size) 42 + #include <asm-generic/access_ok.h> 49 43 50 44 # define __FIXUP_SECTION ".section .fixup,\"ax\"\n" 51 45 # define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n"
+1 -28
arch/mips/include/asm/uaccess.h
··· 44 44 45 45 #endif /* CONFIG_64BIT */ 46 46 47 - /* 48 - * access_ok: - Checks if a user space pointer is valid 49 - * @addr: User space pointer to start of block to check 50 - * @size: Size of block to check 51 - * 52 - * Context: User context only. This function may sleep if pagefaults are 53 - * enabled. 54 - * 55 - * Checks if a pointer to a block of memory in user space is valid. 56 - * 57 - * Returns true (nonzero) if the memory block may be valid, false (zero) 58 - * if it is definitely invalid. 59 - * 60 - * Note that, depending on architecture, this function probably just 61 - * checks that the pointer is in the user space range - after calling 62 - * this function, memory access functions may still return -EFAULT. 63 - */ 64 - 65 - static inline int __access_ok(const void __user *p, unsigned long size) 66 - { 67 - unsigned long addr = (unsigned long)p; 68 - unsigned long limit = TASK_SIZE_MAX; 69 - 70 - return (size <= limit) && (addr <= (limit - size)); 71 - } 72 - 73 - #define access_ok(addr, size) \ 74 - likely(__access_ok((addr), (size))) 47 + #include <asm-generic/access_ok.h> 75 48 76 49 /* 77 50 * put_user: - Write a simple value into user space.
+2 -5
arch/nds32/include/asm/uaccess.h
··· 38 38 39 39 #define get_fs() (current_thread_info()->addr_limit) 40 40 #define user_addr_max get_fs 41 + #define uaccess_kernel() (get_fs() == KERNEL_DS) 41 42 42 43 static inline void set_fs(mm_segment_t fs) 43 44 { 44 45 current_thread_info()->addr_limit = fs; 45 46 } 46 47 47 - #define uaccess_kernel() (get_fs() == KERNEL_DS) 48 + #include <asm-generic/access_ok.h> 48 49 49 - #define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs() -size)) 50 - 51 - #define access_ok(addr, size) \ 52 - __range_ok((unsigned long)addr, (unsigned long)size) 53 50 /* 54 51 * Single-value transfer routines. They automatically use the right 55 52 * size if we just have the right pointer type. Note that the functions
+1 -10
arch/nios2/include/asm/uaccess.h
··· 30 30 #define get_fs() (current_thread_info()->addr_limit) 31 31 #define set_fs(seg) (current_thread_info()->addr_limit = (seg)) 32 32 33 - #define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) 34 - 35 - #define __access_ok(addr, len) \ 36 - (((signed long)(((long)get_fs().seg) & \ 37 - ((long)(addr) | (((long)(addr)) + (len)) | (len)))) == 0) 38 - 39 - #define access_ok(addr, len) \ 40 - likely(__access_ok((unsigned long)(addr), (unsigned long)(len))) 33 + #include <asm-generic/access_ok.h> 41 34 42 35 # define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n" 43 - 44 - #define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE) 45 36 46 37 /* 47 38 * Zero Userspace
+1 -18
arch/openrisc/include/asm/uaccess.h
··· 45 45 46 46 #define uaccess_kernel() (get_fs() == KERNEL_DS) 47 47 48 - /* Ensure that the range from addr to addr+size is all within the process' 49 - * address space 50 - */ 51 - static inline int __range_ok(unsigned long addr, unsigned long size) 52 - { 53 - const mm_segment_t fs = get_fs(); 54 - 55 - return size <= fs && addr <= (fs - size); 56 - } 57 - 58 - #define access_ok(addr, size) \ 59 - ({ \ 60 - __chk_user_ptr(addr); \ 61 - __range_ok((unsigned long)(addr), (size)); \ 62 - }) 48 + #include <asm-generic/access_ok.h> 63 49 64 50 /* 65 51 * These are the main single-value transfer routines. They automatically ··· 253 267 size = __clear_user(addr, size); 254 268 return size; 255 269 } 256 - 257 - #define user_addr_max() \ 258 - (uaccess_kernel() ? ~0UL : TASK_SIZE) 259 270 260 271 extern long strncpy_from_user(char *dest, const char __user *src, long count); 261 272
+1
arch/parisc/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 config PARISC 3 3 def_bool y 4 + select ALTERNATE_USER_ADDRESS_SPACE 4 5 select ARCH_32BIT_OFF_T if !64BIT 5 6 select ARCH_MIGHT_HAVE_PC_PARPORT 6 7 select HAVE_FUNCTION_TRACER
+3 -9
arch/parisc/include/asm/uaccess.h
··· 11 11 #include <linux/bug.h> 12 12 #include <linux/string.h> 13 13 14 - /* 15 - * Note that since kernel addresses are in a separate address space on 16 - * parisc, we don't need to do anything for access_ok(). 17 - * We just let the page fault handler do the right thing. This also means 18 - * that put_user is the same as __put_user, etc. 19 - */ 20 - 21 - #define access_ok(uaddr, size) \ 22 - ( (uaddr) == (uaddr) ) 14 + #define TASK_SIZE_MAX DEFAULT_TASK_SIZE 15 + #include <asm/pgtable.h> 16 + #include <asm-generic/access_ok.h> 23 17 24 18 #define put_user __put_user 25 19 #define get_user __get_user
+1 -10
arch/powerpc/include/asm/uaccess.h
··· 11 11 #ifdef __powerpc64__ 12 12 /* We use TASK_SIZE_USER64 as TASK_SIZE is not constant */ 13 13 #define TASK_SIZE_MAX TASK_SIZE_USER64 14 - #else 15 - #define TASK_SIZE_MAX TASK_SIZE 16 14 #endif 17 15 18 - static inline bool __access_ok(unsigned long addr, unsigned long size) 19 - { 20 - return addr < TASK_SIZE_MAX && size <= TASK_SIZE_MAX - addr; 21 - } 22 - 23 - #define access_ok(addr, size) \ 24 - (__chk_user_ptr(addr), \ 25 - __access_ok((unsigned long)(addr), (size))) 16 + #include <asm-generic/access_ok.h> 26 17 27 18 /* 28 19 * These are the main single-value transfer routines. They automatically
+1 -30
arch/riscv/include/asm/uaccess.h
··· 21 21 #include <asm/byteorder.h> 22 22 #include <asm/extable.h> 23 23 #include <asm/asm.h> 24 + #include <asm-generic/access_ok.h> 24 25 25 26 #define __enable_user_access() \ 26 27 __asm__ __volatile__ ("csrs sstatus, %0" : : "r" (SR_SUM) : "memory") 27 28 #define __disable_user_access() \ 28 29 __asm__ __volatile__ ("csrc sstatus, %0" : : "r" (SR_SUM) : "memory") 29 - 30 - /** 31 - * access_ok: - Checks if a user space pointer is valid 32 - * @addr: User space pointer to start of block to check 33 - * @size: Size of block to check 34 - * 35 - * Context: User context only. This function may sleep. 36 - * 37 - * Checks if a pointer to a block of memory in user space is valid. 38 - * 39 - * Returns true (nonzero) if the memory block may be valid, false (zero) 40 - * if it is definitely invalid. 41 - * 42 - * Note that, depending on architecture, this function probably just 43 - * checks that the pointer is in the user space range - after calling 44 - * this function, memory access functions may still return -EFAULT. 45 - */ 46 - #define access_ok(addr, size) ({ \ 47 - __chk_user_ptr(addr); \ 48 - likely(__access_ok((unsigned long __force)(addr), (size))); \ 49 - }) 50 - 51 - /* 52 - * Ensure that the range [addr, addr+size) is within the process's 53 - * address space 54 - */ 55 - static inline int __access_ok(unsigned long addr, unsigned long size) 56 - { 57 - return size <= TASK_SIZE && addr <= TASK_SIZE - size; 58 - } 59 30 60 31 /* 61 32 * The exception table consists of pairs of addresses: the first is the
+1
arch/s390/Kconfig
··· 55 55 # Note: keep this list sorted alphabetically 56 56 # 57 57 imply IMA_SECURE_AND_OR_TRUSTED_BOOT 58 + select ALTERNATE_USER_ADDRESS_SPACE 58 59 select ARCH_32BIT_USTAT_F_TINODE 59 60 select ARCH_BINFMT_ELF_STATE 60 61 select ARCH_ENABLE_MEMORY_HOTPLUG if SPARSEMEM
+1 -13
arch/s390/include/asm/uaccess.h
··· 17 17 #include <asm/ctl_reg.h> 18 18 #include <asm/extable.h> 19 19 #include <asm/facility.h> 20 + #include <asm-generic/access_ok.h> 20 21 21 22 void debug_user_asce(int exit); 22 - 23 - static inline int __range_ok(unsigned long addr, unsigned long size) 24 - { 25 - return 1; 26 - } 27 - 28 - #define __access_ok(addr, size) \ 29 - ({ \ 30 - __chk_user_ptr(addr); \ 31 - __range_ok((unsigned long)(addr), (size)); \ 32 - }) 33 - 34 - #define access_ok(addr, size) __access_ok(addr, size) 35 23 36 24 unsigned long __must_check 37 25 raw_copy_from_user(void *to, const void __user *from, unsigned long n);
+2 -20
arch/sh/include/asm/uaccess.h
··· 5 5 #include <asm/segment.h> 6 6 #include <asm/extable.h> 7 7 8 - #define __addr_ok(addr) \ 9 - ((unsigned long __force)(addr) < current_thread_info()->addr_limit.seg) 10 - 11 - /* 12 - * __access_ok: Check if address with size is OK or not. 13 - * 14 - * Uhhuh, this needs 33-bit arithmetic. We have a carry.. 15 - * 16 - * sum := addr + size; carry? --> flag = true; 17 - * if (sum >= addr_limit) flag = true; 18 - */ 19 - #define __access_ok(addr, size) ({ \ 20 - unsigned long __ao_a = (addr), __ao_b = (size); \ 21 - unsigned long __ao_end = __ao_a + __ao_b - !!__ao_b; \ 22 - __ao_end >= __ao_a && __addr_ok(__ao_end); }) 23 - 24 - #define access_ok(addr, size) \ 25 - (__chk_user_ptr(addr), \ 26 - __access_ok((unsigned long __force)(addr), (size))) 27 - 28 8 #define user_addr_max() (current_thread_info()->addr_limit.seg) 9 + 10 + #include <asm-generic/access_ok.h> 29 11 30 12 /* 31 13 * Uh, these should become the main single-value transfer routines ...
+1
arch/sparc/Kconfig
··· 62 62 63 63 config SPARC64 64 64 def_bool 64BIT 65 + select ALTERNATE_USER_ADDRESS_SPACE 65 66 select HAVE_FUNCTION_TRACER 66 67 select HAVE_FUNCTION_GRAPH_TRACER 67 68 select HAVE_KRETPROBES
-3
arch/sparc/include/asm/uaccess.h
··· 10 10 #include <asm/uaccess_32.h> 11 11 #endif 12 12 13 - #define user_addr_max() \ 14 - (uaccess_kernel() ? ~0UL : TASK_SIZE) 15 - 16 13 long strncpy_from_user(char *dest, const char __user *src, long count); 17 14 18 15 #endif
+4 -14
arch/sparc/include/asm/uaccess_32.h
··· 25 25 #define get_fs() (current->thread.current_ds) 26 26 #define set_fs(val) ((current->thread.current_ds) = (val)) 27 27 28 - #define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) 29 - 30 - /* We have there a nice not-mapped page at PAGE_OFFSET - PAGE_SIZE, so that this test 31 - * can be fairly lightweight. 32 - * No one can read/write anything from userland in the kernel space by setting 33 - * large size and address near to PAGE_OFFSET - a fault will break his intentions. 34 - */ 35 - #define __user_ok(addr, size) ({ (void)(size); (addr) < STACK_TOP; }) 36 - #define __kernel_ok (uaccess_kernel()) 37 - #define __access_ok(addr, size) (__user_ok((addr) & get_fs().seg, (size))) 38 - #define access_ok(addr, size) __access_ok((unsigned long)(addr), size) 28 + #include <asm-generic/access_ok.h> 39 29 40 30 /* Uh, these should become the main single-value transfer routines.. 41 31 * They automatically use the right size if we just have the right ··· 37 47 * and hide all the ugliness from the user. 38 48 */ 39 49 #define put_user(x, ptr) ({ \ 40 - unsigned long __pu_addr = (unsigned long)(ptr); \ 50 + void __user *__pu_addr = (ptr); \ 41 51 __chk_user_ptr(ptr); \ 42 52 __put_user_check((__typeof__(*(ptr)))(x), __pu_addr, sizeof(*(ptr))); \ 43 53 }) 44 54 45 55 #define get_user(x, ptr) ({ \ 46 - unsigned long __gu_addr = (unsigned long)(ptr); \ 56 + const void __user *__gu_addr = (ptr); \ 47 57 __chk_user_ptr(ptr); \ 48 58 __get_user_check((x), __gu_addr, sizeof(*(ptr)), __typeof__(*(ptr))); \ 49 59 }) ··· 222 232 223 233 static inline unsigned long clear_user(void __user *addr, unsigned long n) 224 234 { 225 - if (n && __access_ok((unsigned long) addr, n)) 235 + if (n && __access_ok(addr, n)) 226 236 return __clear_user(addr, n); 227 237 else 228 238 return n;
+1 -11
arch/sparc/include/asm/uaccess_64.h
··· 31 31 32 32 #define get_fs() ((mm_segment_t){(current_thread_info()->current_ds)}) 33 33 34 - #define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) 34 + #include <asm-generic/access_ok.h> 35 35 36 36 #define set_fs(val) \ 37 37 do { \ ··· 60 60 __chk_user_ptr(addr); \ 61 61 __chk_range_not_ok((unsigned long __force)(addr), size, limit); \ 62 62 }) 63 - 64 - static inline int __access_ok(const void __user * addr, unsigned long size) 65 - { 66 - return 1; 67 - } 68 - 69 - static inline int access_ok(const void __user * addr, unsigned long size) 70 - { 71 - return 1; 72 - } 73 63 74 64 void __retl_efault(void); 75 65
+3 -2
arch/um/include/asm/uaccess.h
··· 25 25 extern unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n); 26 26 extern unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n); 27 27 extern unsigned long __clear_user(void __user *mem, unsigned long len); 28 - static inline int __access_ok(unsigned long addr, unsigned long size); 28 + static inline int __access_ok(const void __user *ptr, unsigned long size); 29 29 30 30 /* Teach asm-generic/uaccess.h that we have C functions for these. */ 31 31 #define __access_ok __access_ok ··· 36 36 37 37 #include <asm-generic/uaccess.h> 38 38 39 - static inline int __access_ok(unsigned long addr, unsigned long size) 39 + static inline int __access_ok(const void __user *ptr, unsigned long size) 40 40 { 41 + unsigned long addr = (unsigned long)ptr; 41 42 return __addr_range_nowrap(addr, size) && 42 43 (__under_task_size(addr, size) || 43 44 __access_ok_vsyscall(addr, size));
+2 -12
arch/x86/include/asm/uaccess.h
··· 12 12 #include <asm/smap.h> 13 13 #include <asm/extable.h> 14 14 15 - /* 16 - * Test whether a block of memory is a valid user space address. 17 - * Returns 0 if the range is valid, nonzero otherwise. 18 - */ 19 - static inline bool __access_ok(void __user *ptr, unsigned long size) 20 - { 21 - unsigned long limit = TASK_SIZE_MAX; 22 - unsigned long addr = ptr; 23 - 24 - return (size <= limit) && (addr <= (limit - size)); 25 - } 26 - 27 15 #ifdef CONFIG_DEBUG_ATOMIC_SLEEP 28 16 static inline bool pagefault_disabled(void); 29 17 # define WARN_ON_IN_IRQ() \ ··· 42 54 WARN_ON_IN_IRQ(); \ 43 55 likely(__access_ok(addr, size)); \ 44 56 }) 57 + 58 + #include <asm-generic/access_ok.h> 45 59 46 60 extern int __get_user_1(void); 47 61 extern int __get_user_2(void);
+1 -9
arch/xtensa/include/asm/uaccess.h
··· 35 35 #define get_fs() (current->thread.current_ds) 36 36 #define set_fs(val) (current->thread.current_ds = (val)) 37 37 38 - #define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) 39 - 40 - #define __kernel_ok (uaccess_kernel()) 41 - #define __user_ok(addr, size) \ 42 - (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size))) 43 - #define __access_ok(addr, size) (__kernel_ok || __user_ok((addr), (size))) 44 - #define access_ok(addr, size) __access_ok((unsigned long)(addr), (size)) 45 - 46 - #define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE) 38 + #include <asm-generic/access_ok.h> 47 39 48 40 /* 49 41 * These are the main single-value transfer routines. They
+60
include/asm-generic/access_ok.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __ASM_GENERIC_ACCESS_OK_H__ 3 + #define __ASM_GENERIC_ACCESS_OK_H__ 4 + 5 + /* 6 + * Checking whether a pointer is valid for user space access. 7 + * These definitions work on most architectures, but overrides can 8 + * be used where necessary. 9 + */ 10 + 11 + /* 12 + * architectures with compat tasks have a variable TASK_SIZE and should 13 + * override this to a constant. 14 + */ 15 + #ifndef TASK_SIZE_MAX 16 + #define TASK_SIZE_MAX TASK_SIZE 17 + #endif 18 + 19 + #ifndef uaccess_kernel 20 + #ifdef CONFIG_SET_FS 21 + #define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) 22 + #else 23 + #define uaccess_kernel() (0) 24 + #endif 25 + #endif 26 + 27 + #ifndef user_addr_max 28 + #define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE_MAX) 29 + #endif 30 + 31 + #ifndef __access_ok 32 + /* 33 + * 'size' is a compile-time constant for most callers, so optimize for 34 + * this case to turn the check into a single comparison against a constant 35 + * limit and catch all possible overflows. 36 + * On architectures with separate user address space (m68k, s390, parisc, 37 + * sparc64) or those without an MMU, this should always return true. 38 + * 39 + * This version was originally contributed by Jonas Bonn for the 40 + * OpenRISC architecture, and was found to be the most efficient 41 + * for constant 'size' and 'limit' values. 42 + */ 43 + static inline int __access_ok(const void __user *ptr, unsigned long size) 44 + { 45 + unsigned long limit = user_addr_max(); 46 + unsigned long addr = (unsigned long)ptr; 47 + 48 + if (IS_ENABLED(CONFIG_ALTERNATE_USER_ADDRESS_SPACE) || 49 + !IS_ENABLED(CONFIG_MMU)) 50 + return true; 51 + 52 + return (size <= limit) && (addr <= (limit - size)); 53 + } 54 + #endif 55 + 56 + #ifndef access_ok 57 + #define access_ok(addr, size) likely(__access_ok(addr, size)) 58 + #endif 59 + 60 + #endif
+1 -20
include/asm-generic/uaccess.h
··· 114 114 } 115 115 #endif 116 116 117 - #ifndef uaccess_kernel 118 - #define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) 119 - #endif 120 - 121 - #ifndef user_addr_max 122 - #define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE) 123 - #endif 124 - 125 117 #endif /* CONFIG_SET_FS */ 126 118 127 - #define access_ok(addr, size) __access_ok((unsigned long)(addr),(size)) 128 - 129 - /* 130 - * The architecture should really override this if possible, at least 131 - * doing a check on the get_fs() 132 - */ 133 - #ifndef __access_ok 134 - static inline int __access_ok(unsigned long addr, unsigned long size) 135 - { 136 - return 1; 137 - } 138 - #endif 119 + #include <asm-generic/access_ok.h> 139 120 140 121 /* 141 122 * These are the main single-value transfer routines. They automatically
-7
include/linux/uaccess.h
··· 33 33 /* empty dummy */ 34 34 } mm_segment_t; 35 35 36 - #ifndef TASK_SIZE_MAX 37 - #define TASK_SIZE_MAX TASK_SIZE 38 - #endif 39 - 40 - #define uaccess_kernel() (false) 41 - #define user_addr_max() (TASK_SIZE_MAX) 42 - 43 36 static inline mm_segment_t force_uaccess_begin(void) 44 37 { 45 38 return (mm_segment_t) { };