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