Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only 2 : : /* 3 : : * Access kernel memory without faulting. 4 : : */ 5 : : #include <linux/export.h> 6 : : #include <linux/mm.h> 7 : : #include <linux/uaccess.h> 8 : : 9 : : static __always_inline long 10 : : probe_read_common(void *dst, const void __user *src, size_t size) 11 : : { 12 : : long ret; 13 : : 14 : 3 : pagefault_disable(); 15 : : ret = __copy_from_user_inatomic(dst, src, size); 16 : 3 : pagefault_enable(); 17 : : 18 : 3 : return ret ? -EFAULT : 0; 19 : : } 20 : : 21 : : static __always_inline long 22 : : probe_write_common(void __user *dst, const void *src, size_t size) 23 : : { 24 : : long ret; 25 : : 26 : 3 : pagefault_disable(); 27 : : ret = __copy_to_user_inatomic(dst, src, size); 28 : 3 : pagefault_enable(); 29 : : 30 : 3 : return ret ? -EFAULT : 0; 31 : : } 32 : : 33 : : /** 34 : : * probe_kernel_read(): safely attempt to read from a kernel-space location 35 : : * @dst: pointer to the buffer that shall take the data 36 : : * @src: address to read from 37 : : * @size: size of the data chunk 38 : : * 39 : : * Safely read from address @src to the buffer at @dst. If a kernel fault 40 : : * happens, handle that and return -EFAULT. 41 : : * 42 : : * We ensure that the copy_from_user is executed in atomic context so that 43 : : * do_page_fault() doesn't attempt to take mmap_sem. This makes 44 : : * probe_kernel_read() suitable for use within regions where the caller 45 : : * already holds mmap_sem, or other locks which nest inside mmap_sem. 46 : : */ 47 : : 48 : : long __weak probe_kernel_read(void *dst, const void *src, size_t size) 49 : : __attribute__((alias("__probe_kernel_read"))); 50 : : 51 : 3 : long __probe_kernel_read(void *dst, const void *src, size_t size) 52 : : { 53 : : long ret; 54 : 3 : mm_segment_t old_fs = get_fs(); 55 : : 56 : : set_fs(KERNEL_DS); 57 : : ret = probe_read_common(dst, (__force const void __user *)src, size); 58 : : set_fs(old_fs); 59 : : 60 : 3 : return ret; 61 : : } 62 : : EXPORT_SYMBOL_GPL(probe_kernel_read); 63 : : 64 : : /** 65 : : * probe_user_read(): safely attempt to read from a user-space location 66 : : * @dst: pointer to the buffer that shall take the data 67 : : * @src: address to read from. This must be a user address. 68 : : * @size: size of the data chunk 69 : : * 70 : : * Safely read from user address @src to the buffer at @dst. If a kernel fault 71 : : * happens, handle that and return -EFAULT. 72 : : */ 73 : : 74 : : long __weak probe_user_read(void *dst, const void __user *src, size_t size) 75 : : __attribute__((alias("__probe_user_read"))); 76 : : 77 : 0 : long __probe_user_read(void *dst, const void __user *src, size_t size) 78 : : { 79 : : long ret = -EFAULT; 80 : 0 : mm_segment_t old_fs = get_fs(); 81 : : 82 : : set_fs(USER_DS); 83 : 0 : if (access_ok(src, size)) 84 : : ret = probe_read_common(dst, src, size); 85 : : set_fs(old_fs); 86 : : 87 : 0 : return ret; 88 : : } 89 : : EXPORT_SYMBOL_GPL(probe_user_read); 90 : : 91 : : /** 92 : : * probe_kernel_write(): safely attempt to write to a location 93 : : * @dst: address to write to 94 : : * @src: pointer to the data that shall be written 95 : : * @size: size of the data chunk 96 : : * 97 : : * Safely write to address @dst from the buffer at @src. If a kernel fault 98 : : * happens, handle that and return -EFAULT. 99 : : */ 100 : : 101 : : long __weak probe_kernel_write(void *dst, const void *src, size_t size) 102 : : __attribute__((alias("__probe_kernel_write"))); 103 : : 104 : 3 : long __probe_kernel_write(void *dst, const void *src, size_t size) 105 : : { 106 : : long ret; 107 : 3 : mm_segment_t old_fs = get_fs(); 108 : : 109 : : set_fs(KERNEL_DS); 110 : : ret = probe_write_common((__force void __user *)dst, src, size); 111 : : set_fs(old_fs); 112 : : 113 : 3 : return ret; 114 : : } 115 : : EXPORT_SYMBOL_GPL(probe_kernel_write); 116 : : 117 : : /** 118 : : * probe_user_write(): safely attempt to write to a user-space location 119 : : * @dst: address to write to 120 : : * @src: pointer to the data that shall be written 121 : : * @size: size of the data chunk 122 : : * 123 : : * Safely write to address @dst from the buffer at @src. If a kernel fault 124 : : * happens, handle that and return -EFAULT. 125 : : */ 126 : : 127 : : long __weak probe_user_write(void __user *dst, const void *src, size_t size) 128 : : __attribute__((alias("__probe_user_write"))); 129 : : 130 : 0 : long __probe_user_write(void __user *dst, const void *src, size_t size) 131 : : { 132 : : long ret = -EFAULT; 133 : 0 : mm_segment_t old_fs = get_fs(); 134 : : 135 : : set_fs(USER_DS); 136 : 0 : if (access_ok(dst, size)) 137 : : ret = probe_write_common(dst, src, size); 138 : : set_fs(old_fs); 139 : : 140 : 0 : return ret; 141 : : } 142 : : EXPORT_SYMBOL_GPL(probe_user_write); 143 : : 144 : : /** 145 : : * strncpy_from_unsafe: - Copy a NUL terminated string from unsafe address. 146 : : * @dst: Destination address, in kernel space. This buffer must be at 147 : : * least @count bytes long. 148 : : * @unsafe_addr: Unsafe address. 149 : : * @count: Maximum number of bytes to copy, including the trailing NUL. 150 : : * 151 : : * Copies a NUL-terminated string from unsafe address to kernel buffer. 152 : : * 153 : : * On success, returns the length of the string INCLUDING the trailing NUL. 154 : : * 155 : : * If access fails, returns -EFAULT (some data may have been copied 156 : : * and the trailing NUL added). 157 : : * 158 : : * If @count is smaller than the length of the string, copies @count-1 bytes, 159 : : * sets the last byte of @dst buffer to NUL and returns @count. 160 : : */ 161 : 0 : long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count) 162 : : { 163 : 0 : mm_segment_t old_fs = get_fs(); 164 : : const void *src = unsafe_addr; 165 : : long ret; 166 : : 167 : 0 : if (unlikely(count <= 0)) 168 : : return 0; 169 : : 170 : : set_fs(KERNEL_DS); 171 : : pagefault_disable(); 172 : : 173 : : do { 174 : 0 : ret = __get_user(*dst++, (const char __user __force *)src++); 175 : 0 : } while (dst[-1] && ret == 0 && src - unsafe_addr < count); 176 : : 177 : 0 : dst[-1] = '\0'; 178 : : pagefault_enable(); 179 : : set_fs(old_fs); 180 : : 181 : 0 : return ret ? -EFAULT : src - unsafe_addr; 182 : : } 183 : : 184 : : /** 185 : : * strncpy_from_unsafe_user: - Copy a NUL terminated string from unsafe user 186 : : * address. 187 : : * @dst: Destination address, in kernel space. This buffer must be at 188 : : * least @count bytes long. 189 : : * @unsafe_addr: Unsafe user address. 190 : : * @count: Maximum number of bytes to copy, including the trailing NUL. 191 : : * 192 : : * Copies a NUL-terminated string from unsafe user address to kernel buffer. 193 : : * 194 : : * On success, returns the length of the string INCLUDING the trailing NUL. 195 : : * 196 : : * If access fails, returns -EFAULT (some data may have been copied 197 : : * and the trailing NUL added). 198 : : * 199 : : * If @count is smaller than the length of the string, copies @count-1 bytes, 200 : : * sets the last byte of @dst buffer to NUL and returns @count. 201 : : */ 202 : 0 : long strncpy_from_unsafe_user(char *dst, const void __user *unsafe_addr, 203 : : long count) 204 : : { 205 : 0 : mm_segment_t old_fs = get_fs(); 206 : : long ret; 207 : : 208 : 0 : if (unlikely(count <= 0)) 209 : : return 0; 210 : : 211 : : set_fs(USER_DS); 212 : : pagefault_disable(); 213 : 0 : ret = strncpy_from_user(dst, unsafe_addr, count); 214 : : pagefault_enable(); 215 : : set_fs(old_fs); 216 : : 217 : 0 : if (ret >= count) { 218 : : ret = count; 219 : 0 : dst[ret - 1] = '\0'; 220 : 0 : } else if (ret > 0) { 221 : 0 : ret++; 222 : : } 223 : : 224 : 0 : return ret; 225 : : } 226 : : 227 : : /** 228 : : * strnlen_unsafe_user: - Get the size of a user string INCLUDING final NUL. 229 : : * @unsafe_addr: The string to measure. 230 : : * @count: Maximum count (including NUL) 231 : : * 232 : : * Get the size of a NUL-terminated string in user space without pagefault. 233 : : * 234 : : * Returns the size of the string INCLUDING the terminating NUL. 235 : : * 236 : : * If the string is too long, returns a number larger than @count. User 237 : : * has to check the return value against "> count". 238 : : * On exception (or invalid count), returns 0. 239 : : * 240 : : * Unlike strnlen_user, this can be used from IRQ handler etc. because 241 : : * it disables pagefaults. 242 : : */ 243 : 0 : long strnlen_unsafe_user(const void __user *unsafe_addr, long count) 244 : : { 245 : 0 : mm_segment_t old_fs = get_fs(); 246 : : int ret; 247 : : 248 : : set_fs(USER_DS); 249 : : pagefault_disable(); 250 : 0 : ret = strnlen_user(unsafe_addr, count); 251 : : pagefault_enable(); 252 : : set_fs(old_fs); 253 : : 254 : 0 : return ret; 255 : : }