1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Access kernel or user memory without faulting. 4 */ 5 #include <linux/export.h> 6 #include <linux/mm.h> 7 #include <linux/uaccess.h> 8 9 bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src, 10 size_t size) 11 { 12 return true; 13 } 14 15 #define copy_from_kernel_nofault_loop(dst, src, len, type, err_label) \ 16 while (len >= sizeof(type)) { \ 17 __get_kernel_nofault(dst, src, type, err_label); \ 18 dst += sizeof(type); \ 19 src += sizeof(type); \ 20 len -= sizeof(type); \ 21 } 22 23 long copy_from_kernel_nofault(void *dst, const void *src, size_t size) 24 { 25 unsigned long align = 0; 26 27 if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) 28 align = (unsigned long)dst | (unsigned long)src; 29 30 if (!copy_from_kernel_nofault_allowed(src, size)) 31 return -ERANGE; 32 33 pagefault_disable(); 34 if (!(align & 7)) 35 copy_from_kernel_nofault_loop(dst, src, size, u64, Efault); 36 if (!(align & 3)) 37 copy_from_kernel_nofault_loop(dst, src, size, u32, Efault); 38 if (!(align & 1)) 39 copy_from_kernel_nofault_loop(dst, src, size, u16, Efault); 40 copy_from_kernel_nofault_loop(dst, src, size, u8, Efault); 41 pagefault_enable(); 42 return 0; 43 Efault: 44 pagefault_enable(); 45 return -EFAULT; 46 } 47 EXPORT_SYMBOL_GPL(copy_from_kernel_nofault); 48 49 #define copy_to_kernel_nofault_loop(dst, src, len, type, err_label) \ 50 while (len >= sizeof(type)) { \ 51 __put_kernel_nofault(dst, src, type, err_label); \ 52 dst += sizeof(type); \ 53 src += sizeof(type); \ 54 len -= sizeof(type); \ 55 } 56 57 long copy_to_kernel_nofault(void *dst, const void *src, size_t size) 58 { 59 unsigned long align = 0; 60 61 if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) 62 align = (unsigned long)dst | (unsigned long)src; 63 64 pagefault_disable(); 65 if (!(align & 7)) 66 copy_to_kernel_nofault_loop(dst, src, size, u64, Efault); 67 if (!(align & 3)) 68 copy_to_kernel_nofault_loop(dst, src, size, u32, Efault); 69 if (!(align & 1)) 70 copy_to_kernel_nofault_loop(dst, src, size, u16, Efault); 71 copy_to_kernel_nofault_loop(dst, src, size, u8, Efault); 72 pagefault_enable(); 73 return 0; 74 Efault: 75 pagefault_enable(); 76 return -EFAULT; 77 } 78 79 long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count) 80 { 81 const void *src = unsafe_addr; 82 83 if (unlikely(count <= 0)) 84 return 0; 85 if (!copy_from_kernel_nofault_allowed(unsafe_addr, count)) 86 return -ERANGE; 87 88 pagefault_disable(); 89 do { 90 __get_kernel_nofault(dst, src, u8, Efault); 91 dst++; 92 src++; 93 } while (dst[-1] && src - unsafe_addr < count); 94 pagefault_enable(); 95 96 dst[-1] = '\0'; 97 return src - unsafe_addr; 98 Efault: 99 pagefault_enable(); 100 dst[0] = '\0'; 101 return -EFAULT; 102 } 103 104 /** 105 * copy_from_user_nofault(): safely attempt to read from a user-space location 106 * @dst: pointer to the buffer that shall take the data 107 * @src: address to read from. This must be a user address. 108 * @size: size of the data chunk 109 * 110 * Safely read from user address @src to the buffer at @dst. If a kernel fault 111 * happens, handle that and return -EFAULT. 112 */ 113 long copy_from_user_nofault(void *dst, const void __user *src, size_t size) 114 { 115 long ret = -EFAULT; 116 if (access_ok(src, size)) { 117 pagefault_disable(); 118 ret = __copy_from_user_inatomic(dst, src, size); 119 pagefault_enable(); 120 } 121 122 if (ret) 123 return -EFAULT; 124 return 0; 125 } 126 EXPORT_SYMBOL_GPL(copy_from_user_nofault); 127 128 /** 129 * copy_to_user_nofault(): safely attempt to write to a user-space location 130 * @dst: address to write to 131 * @src: pointer to the data that shall be written 132 * @size: size of the data chunk 133 * 134 * Safely write to address @dst from the buffer at @src. If a kernel fault 135 * happens, handle that and return -EFAULT. 136 */ 137 long copy_to_user_nofault(void __user *dst, const void *src, size_t size) 138 { 139 long ret = -EFAULT; 140 141 if (access_ok(dst, size)) { 142 pagefault_disable(); 143 ret = __copy_to_user_inatomic(dst, src, size); 144 pagefault_enable(); 145 } 146 147 if (ret) 148 return -EFAULT; 149 return 0; 150 } 151 EXPORT_SYMBOL_GPL(copy_to_user_nofault); 152 153 /** 154 * strncpy_from_user_nofault: - Copy a NUL terminated string from unsafe user 155 * address. 156 * @dst: Destination address, in kernel space. This buffer must be at 157 * least @count bytes long. 158 * @unsafe_addr: Unsafe user address. 159 * @count: Maximum number of bytes to copy, including the trailing NUL. 160 * 161 * Copies a NUL-terminated string from unsafe user address to kernel buffer. 162 * 163 * On success, returns the length of the string INCLUDING the trailing NUL. 164 * 165 * If access fails, returns -EFAULT (some data may have been copied 166 * and the trailing NUL added). 167 * 168 * If @count is smaller than the length of the string, copies @count-1 bytes, 169 * sets the last byte of @dst buffer to NUL and returns @count. 170 */ 171 long strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr, 172 long count) 173 { 174 long ret; 175 176 if (unlikely(count <= 0)) 177 return 0; 178 179 pagefault_disable(); 180 ret = strncpy_from_user(dst, unsafe_addr, count); 181 pagefault_enable(); 182 183 if (ret >= count) { 184 ret = count; 185 dst[ret - 1] = '\0'; 186 } else if (ret > 0) { 187 ret++; 188 } 189 190 return ret; 191 } 192 193 /** 194 * strnlen_user_nofault: - Get the size of a user string INCLUDING final NUL. 195 * @unsafe_addr: The string to measure. 196 * @count: Maximum count (including NUL) 197 * 198 * Get the size of a NUL-terminated string in user space without pagefault. 199 * 200 * Returns the size of the string INCLUDING the terminating NUL. 201 * 202 * If the string is too long, returns a number larger than @count. User 203 * has to check the return value against "> count". 204 * On exception (or invalid count), returns 0. 205 * 206 * Unlike strnlen_user, this can be used from IRQ handler etc. because 207 * it disables pagefaults. 208 */ 209 long strnlen_user_nofault(const void __user *unsafe_addr, long count) 210 { 211 int ret; 212 213 pagefault_disable(); 214 ret = strnlen_user(unsafe_addr, count); 215 pagefault_enable(); 216 217 return ret; 218 } 219 220 void __copy_overflow(int size, unsigned long count) 221 { 222 WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count); 223 } 224 EXPORT_SYMBOL(__copy_overflow); 225