1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * __put_user functions. 4 * 5 * (C) Copyright 2005 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 #include <linux/export.h> 15 #include <linux/linkage.h> 16 #include <asm/thread_info.h> 17 #include <asm/errno.h> 18 #include <asm/asm.h> 19 #include <asm/smap.h> 20 21 /* 22 * __put_user_X 23 * 24 * Inputs: %eax[:%edx] contains the data 25 * %ecx contains the address 26 * 27 * Outputs: %ecx is error code (0 or -EFAU 28 * 29 * Clobbers: %ebx needed for task pointer 30 * 31 * These functions should not modify any other 32 * as they get called from within inline assem 33 */ 34 35 .macro check_range size:req 36 .if IS_ENABLED(CONFIG_X86_64) 37 mov %rcx, %rbx 38 sar $63, %rbx 39 or %rbx, %rcx 40 .else 41 cmp $TASK_SIZE_MAX-\size+1, %ecx 42 jae .Lbad_put_user 43 .endif 44 .endm 45 46 .text 47 SYM_FUNC_START(__put_user_1) 48 check_range size=1 49 ASM_STAC 50 1: movb %al,(%_ASM_CX) 51 xor %ecx,%ecx 52 ASM_CLAC 53 RET 54 SYM_FUNC_END(__put_user_1) 55 EXPORT_SYMBOL(__put_user_1) 56 57 SYM_FUNC_START(__put_user_nocheck_1) 58 ASM_STAC 59 2: movb %al,(%_ASM_CX) 60 xor %ecx,%ecx 61 ASM_CLAC 62 RET 63 SYM_FUNC_END(__put_user_nocheck_1) 64 EXPORT_SYMBOL(__put_user_nocheck_1) 65 66 SYM_FUNC_START(__put_user_2) 67 check_range size=2 68 ASM_STAC 69 3: movw %ax,(%_ASM_CX) 70 xor %ecx,%ecx 71 ASM_CLAC 72 RET 73 SYM_FUNC_END(__put_user_2) 74 EXPORT_SYMBOL(__put_user_2) 75 76 SYM_FUNC_START(__put_user_nocheck_2) 77 ASM_STAC 78 4: movw %ax,(%_ASM_CX) 79 xor %ecx,%ecx 80 ASM_CLAC 81 RET 82 SYM_FUNC_END(__put_user_nocheck_2) 83 EXPORT_SYMBOL(__put_user_nocheck_2) 84 85 SYM_FUNC_START(__put_user_4) 86 check_range size=4 87 ASM_STAC 88 5: movl %eax,(%_ASM_CX) 89 xor %ecx,%ecx 90 ASM_CLAC 91 RET 92 SYM_FUNC_END(__put_user_4) 93 EXPORT_SYMBOL(__put_user_4) 94 95 SYM_FUNC_START(__put_user_nocheck_4) 96 ASM_STAC 97 6: movl %eax,(%_ASM_CX) 98 xor %ecx,%ecx 99 ASM_CLAC 100 RET 101 SYM_FUNC_END(__put_user_nocheck_4) 102 EXPORT_SYMBOL(__put_user_nocheck_4) 103 104 SYM_FUNC_START(__put_user_8) 105 check_range size=8 106 ASM_STAC 107 7: mov %_ASM_AX,(%_ASM_CX) 108 #ifdef CONFIG_X86_32 109 8: movl %edx,4(%_ASM_CX) 110 #endif 111 xor %ecx,%ecx 112 ASM_CLAC 113 RET 114 SYM_FUNC_END(__put_user_8) 115 EXPORT_SYMBOL(__put_user_8) 116 117 SYM_FUNC_START(__put_user_nocheck_8) 118 ASM_STAC 119 9: mov %_ASM_AX,(%_ASM_CX) 120 #ifdef CONFIG_X86_32 121 10: movl %edx,4(%_ASM_CX) 122 #endif 123 xor %ecx,%ecx 124 ASM_CLAC 125 RET 126 SYM_FUNC_END(__put_user_nocheck_8) 127 EXPORT_SYMBOL(__put_user_nocheck_8) 128 129 SYM_CODE_START_LOCAL(__put_user_handle_excepti 130 ASM_CLAC 131 .Lbad_put_user: 132 movl $-EFAULT,%ecx 133 RET 134 SYM_CODE_END(__put_user_handle_exception) 135 136 _ASM_EXTABLE_UA(1b, __put_user_handle_ 137 _ASM_EXTABLE_UA(2b, __put_user_handle_ 138 _ASM_EXTABLE_UA(3b, __put_user_handle_ 139 _ASM_EXTABLE_UA(4b, __put_user_handle_ 140 _ASM_EXTABLE_UA(5b, __put_user_handle_ 141 _ASM_EXTABLE_UA(6b, __put_user_handle_ 142 _ASM_EXTABLE_UA(7b, __put_user_handle_ 143 _ASM_EXTABLE_UA(9b, __put_user_handle_ 144 #ifdef CONFIG_X86_32 145 _ASM_EXTABLE_UA(8b, __put_user_handle_ 146 _ASM_EXTABLE_UA(10b, __put_user_handle 147 #endif
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.