1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * __get_user functions. 4 * 5 * (C) Copyright 1998 Linus Torvalds 6 * (C) Copyright 2005 Andi Kleen 7 * (C) Copyright 2008 Glauber Costa 8 * 9 * These functions have a non-standard call in 10 * to make them more efficient, especially as 11 * return an error value in addition to the "r 12 * return value. 13 */ 14 15 /* 16 * __get_user_X 17 * 18 * Inputs: %[r|e]ax contains the address. 19 * 20 * Outputs: %[r|e]ax is error code (0 or - 21 * %[r|e]dx contains zero-extende 22 * %ecx contains the high half fo 23 * 24 * 25 * These functions should not modify any other 26 * as they get called from within inline assem 27 */ 28 29 #include <linux/export.h> 30 #include <linux/linkage.h> 31 #include <asm/page_types.h> 32 #include <asm/errno.h> 33 #include <asm/asm-offsets.h> 34 #include <asm/thread_info.h> 35 #include <asm/asm.h> 36 #include <asm/smap.h> 37 38 #define ASM_BARRIER_NOSPEC ALTERNATIVE "", "lf 39 40 .macro check_range size:req 41 .if IS_ENABLED(CONFIG_X86_64) 42 mov %rax, %rdx 43 sar $63, %rdx 44 or %rdx, %rax 45 .else 46 cmp $TASK_SIZE_MAX-\size+1, %eax 47 jae .Lbad_get_user 48 sbb %edx, %edx /* array_index 49 and %edx, %eax 50 .endif 51 .endm 52 53 .macro UACCESS op src dst 54 1: \op \src,\dst 55 _ASM_EXTABLE_UA(1b, __get_user_handle_ 56 .endm 57 58 59 .text 60 SYM_FUNC_START(__get_user_1) 61 check_range size=1 62 ASM_STAC 63 UACCESS movzbl (%_ASM_AX),%edx 64 xor %eax,%eax 65 ASM_CLAC 66 RET 67 SYM_FUNC_END(__get_user_1) 68 EXPORT_SYMBOL(__get_user_1) 69 70 SYM_FUNC_START(__get_user_2) 71 check_range size=2 72 ASM_STAC 73 UACCESS movzwl (%_ASM_AX),%edx 74 xor %eax,%eax 75 ASM_CLAC 76 RET 77 SYM_FUNC_END(__get_user_2) 78 EXPORT_SYMBOL(__get_user_2) 79 80 SYM_FUNC_START(__get_user_4) 81 check_range size=4 82 ASM_STAC 83 UACCESS movl (%_ASM_AX),%edx 84 xor %eax,%eax 85 ASM_CLAC 86 RET 87 SYM_FUNC_END(__get_user_4) 88 EXPORT_SYMBOL(__get_user_4) 89 90 SYM_FUNC_START(__get_user_8) 91 #ifndef CONFIG_X86_64 92 xor %ecx,%ecx 93 #endif 94 check_range size=8 95 ASM_STAC 96 #ifdef CONFIG_X86_64 97 UACCESS movq (%_ASM_AX),%rdx 98 #else 99 UACCESS movl (%_ASM_AX),%edx 100 UACCESS movl 4(%_ASM_AX),%ecx 101 #endif 102 xor %eax,%eax 103 ASM_CLAC 104 RET 105 SYM_FUNC_END(__get_user_8) 106 EXPORT_SYMBOL(__get_user_8) 107 108 /* .. and the same for __get_user, just withou 109 SYM_FUNC_START(__get_user_nocheck_1) 110 ASM_STAC 111 ASM_BARRIER_NOSPEC 112 UACCESS movzbl (%_ASM_AX),%edx 113 xor %eax,%eax 114 ASM_CLAC 115 RET 116 SYM_FUNC_END(__get_user_nocheck_1) 117 EXPORT_SYMBOL(__get_user_nocheck_1) 118 119 SYM_FUNC_START(__get_user_nocheck_2) 120 ASM_STAC 121 ASM_BARRIER_NOSPEC 122 UACCESS movzwl (%_ASM_AX),%edx 123 xor %eax,%eax 124 ASM_CLAC 125 RET 126 SYM_FUNC_END(__get_user_nocheck_2) 127 EXPORT_SYMBOL(__get_user_nocheck_2) 128 129 SYM_FUNC_START(__get_user_nocheck_4) 130 ASM_STAC 131 ASM_BARRIER_NOSPEC 132 UACCESS movl (%_ASM_AX),%edx 133 xor %eax,%eax 134 ASM_CLAC 135 RET 136 SYM_FUNC_END(__get_user_nocheck_4) 137 EXPORT_SYMBOL(__get_user_nocheck_4) 138 139 SYM_FUNC_START(__get_user_nocheck_8) 140 ASM_STAC 141 ASM_BARRIER_NOSPEC 142 #ifdef CONFIG_X86_64 143 UACCESS movq (%_ASM_AX),%rdx 144 #else 145 xor %ecx,%ecx 146 UACCESS movl (%_ASM_AX),%edx 147 UACCESS movl 4(%_ASM_AX),%ecx 148 #endif 149 xor %eax,%eax 150 ASM_CLAC 151 RET 152 SYM_FUNC_END(__get_user_nocheck_8) 153 EXPORT_SYMBOL(__get_user_nocheck_8) 154 155 156 SYM_CODE_START_LOCAL(__get_user_handle_excepti 157 ASM_CLAC 158 .Lbad_get_user: 159 xor %edx,%edx 160 mov $(-EFAULT),%_ASM_AX 161 RET 162 SYM_CODE_END(__get_user_handle_exception)
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.