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 interface 10 * to make them more efficient, especially as they 11 * return an error value in addition to the "real" 12 * return value. 13 */ 14#include <linux/export.h> 15#include <linux/linkage.h> 16#include <linux/objtool.h> 17#include <asm/thread_info.h> 18#include <asm/errno.h> 19#include <asm/asm.h> 20#include <asm/smap.h> 21 22/* 23 * __put_user_X 24 * 25 * Inputs: %eax[:%edx] contains the data 26 * %ecx contains the address 27 * 28 * Outputs: %ecx is error code (0 or -EFAULT) 29 * 30 * Clobbers: %ebx needed for task pointer 31 * 32 * These functions should not modify any other registers, 33 * as they get called from within inline assembly. 34 */ 35 36.macro check_range size:req 37.if IS_ENABLED(CONFIG_X86_64) 38 mov %rcx, %rbx 39 sar $63, %rbx 40 or %rbx, %rcx 41.else 42 cmp $TASK_SIZE_MAX-\size+1, %ecx 43 jae .Lbad_put_user 44.endif 45.endm 46 47.text 48SYM_FUNC_START(__put_user_1) 49 ANNOTATE_NOENDBR 50 check_range size=1 51 ASM_STAC 521: movb %al,(%_ASM_CX) 53 xor %ecx,%ecx 54 ASM_CLAC 55 RET 56SYM_FUNC_END(__put_user_1) 57EXPORT_SYMBOL(__put_user_1) 58 59SYM_FUNC_START(__put_user_nocheck_1) 60 ANNOTATE_NOENDBR 61 ASM_STAC 622: movb %al,(%_ASM_CX) 63 xor %ecx,%ecx 64 ASM_CLAC 65 RET 66SYM_FUNC_END(__put_user_nocheck_1) 67EXPORT_SYMBOL(__put_user_nocheck_1) 68 69SYM_FUNC_START(__put_user_2) 70 ANNOTATE_NOENDBR 71 check_range size=2 72 ASM_STAC 733: movw %ax,(%_ASM_CX) 74 xor %ecx,%ecx 75 ASM_CLAC 76 RET 77SYM_FUNC_END(__put_user_2) 78EXPORT_SYMBOL(__put_user_2) 79 80SYM_FUNC_START(__put_user_nocheck_2) 81 ANNOTATE_NOENDBR 82 ASM_STAC 834: movw %ax,(%_ASM_CX) 84 xor %ecx,%ecx 85 ASM_CLAC 86 RET 87SYM_FUNC_END(__put_user_nocheck_2) 88EXPORT_SYMBOL(__put_user_nocheck_2) 89 90SYM_FUNC_START(__put_user_4) 91 ANNOTATE_NOENDBR 92 check_range size=4 93 ASM_STAC 945: movl %eax,(%_ASM_CX) 95 xor %ecx,%ecx 96 ASM_CLAC 97 RET 98SYM_FUNC_END(__put_user_4) 99EXPORT_SYMBOL(__put_user_4) 100 101SYM_FUNC_START(__put_user_nocheck_4) 102 ANNOTATE_NOENDBR 103 ASM_STAC 1046: movl %eax,(%_ASM_CX) 105 xor %ecx,%ecx 106 ASM_CLAC 107 RET 108SYM_FUNC_END(__put_user_nocheck_4) 109EXPORT_SYMBOL(__put_user_nocheck_4) 110 111SYM_FUNC_START(__put_user_8) 112 ANNOTATE_NOENDBR 113 check_range size=8 114 ASM_STAC 1157: mov %_ASM_AX,(%_ASM_CX) 116#ifdef CONFIG_X86_32 1178: movl %edx,4(%_ASM_CX) 118#endif 119 xor %ecx,%ecx 120 ASM_CLAC 121 RET 122SYM_FUNC_END(__put_user_8) 123EXPORT_SYMBOL(__put_user_8) 124 125SYM_FUNC_START(__put_user_nocheck_8) 126 ANNOTATE_NOENDBR 127 ASM_STAC 1289: mov %_ASM_AX,(%_ASM_CX) 129#ifdef CONFIG_X86_32 13010: movl %edx,4(%_ASM_CX) 131#endif 132 xor %ecx,%ecx 133 ASM_CLAC 134 RET 135SYM_FUNC_END(__put_user_nocheck_8) 136EXPORT_SYMBOL(__put_user_nocheck_8) 137 138SYM_CODE_START_LOCAL(__put_user_handle_exception) 139 ASM_CLAC 140.Lbad_put_user: 141 movl $-EFAULT,%ecx 142 RET 143SYM_CODE_END(__put_user_handle_exception) 144 145 _ASM_EXTABLE_UA(1b, __put_user_handle_exception) 146 _ASM_EXTABLE_UA(2b, __put_user_handle_exception) 147 _ASM_EXTABLE_UA(3b, __put_user_handle_exception) 148 _ASM_EXTABLE_UA(4b, __put_user_handle_exception) 149 _ASM_EXTABLE_UA(5b, __put_user_handle_exception) 150 _ASM_EXTABLE_UA(6b, __put_user_handle_exception) 151 _ASM_EXTABLE_UA(7b, __put_user_handle_exception) 152 _ASM_EXTABLE_UA(9b, __put_user_handle_exception) 153#ifdef CONFIG_X86_32 154 _ASM_EXTABLE_UA(8b, __put_user_handle_exception) 155 _ASM_EXTABLE_UA(10b, __put_user_handle_exception) 156#endif 157