blob: 19c8c3dc14df69a3a7815a0d84346f932490a5cf [file] [log] [blame]
Ingo Molnarc33fa9f2008-04-17 20:05:36 +02001/*
2 * Access kernel memory without faulting.
3 */
Paul Gortmakerb95f1b312011-10-16 02:01:52 -04004#include <linux/export.h>
Ingo Molnarc33fa9f2008-04-17 20:05:36 +02005#include <linux/mm.h>
David Howells7c7fcf72010-10-27 17:29:01 +01006#include <linux/uaccess.h>
Ingo Molnarc33fa9f2008-04-17 20:05:36 +02007
Masami Hiramatsu3d708182019-05-15 14:38:18 +09008static __always_inline long
9probe_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
Ingo Molnarc33fa9f2008-04-17 20:05:36 +020020/**
Masami Hiramatsu3d708182019-05-15 14:38:18 +090021 * probe_kernel_read(): safely attempt to read from a kernel-space location
Ingo Molnarc33fa9f2008-04-17 20:05:36 +020022 * @dst: pointer to the buffer that shall take the data
23 * @src: address to read from
24 * @size: size of the data chunk
25 *
26 * Safely read from address @src to the buffer at @dst. If a kernel fault
27 * happens, handle that and return -EFAULT.
Andrew Morton0ab32b62015-11-05 18:46:03 -080028 *
29 * We ensure that the copy_from_user is executed in atomic context so that
30 * do_page_fault() doesn't attempt to take mmap_sem. This makes
31 * probe_kernel_read() suitable for use within regions where the caller
32 * already holds mmap_sem, or other locks which nest inside mmap_sem.
Ingo Molnarc33fa9f2008-04-17 20:05:36 +020033 */
Jason Wessel6144a852010-01-07 11:58:36 -060034
Steven Rostedtf29c5042011-05-19 14:35:33 -040035long __weak probe_kernel_read(void *dst, const void *src, size_t size)
Jason Wessel6144a852010-01-07 11:58:36 -060036 __attribute__((alias("__probe_kernel_read")));
37
Steven Rostedtf29c5042011-05-19 14:35:33 -040038long __probe_kernel_read(void *dst, const void *src, size_t size)
Ingo Molnarc33fa9f2008-04-17 20:05:36 +020039{
40 long ret;
Jason Wesselb4b8ac52008-02-20 13:33:38 -060041 mm_segment_t old_fs = get_fs();
Ingo Molnarc33fa9f2008-04-17 20:05:36 +020042
Jason Wesselb4b8ac52008-02-20 13:33:38 -060043 set_fs(KERNEL_DS);
Masami Hiramatsu3d708182019-05-15 14:38:18 +090044 ret = probe_read_common(dst, (__force const void __user *)src, size);
Jason Wesselb4b8ac52008-02-20 13:33:38 -060045 set_fs(old_fs);
Ingo Molnarc33fa9f2008-04-17 20:05:36 +020046
Masami Hiramatsu3d708182019-05-15 14:38:18 +090047 return ret;
Ingo Molnarc33fa9f2008-04-17 20:05:36 +020048}
49EXPORT_SYMBOL_GPL(probe_kernel_read);
50
51/**
Masami Hiramatsu3d708182019-05-15 14:38:18 +090052 * probe_user_read(): safely attempt to read from a user-space location
53 * @dst: pointer to the buffer that shall take the data
54 * @src: address to read from. This must be a user address.
55 * @size: size of the data chunk
56 *
57 * Safely read from user address @src to the buffer at @dst. If a kernel fault
58 * happens, handle that and return -EFAULT.
59 */
60
61long __weak probe_user_read(void *dst, const void __user *src, size_t size)
62 __attribute__((alias("__probe_user_read")));
63
64long __probe_user_read(void *dst, const void __user *src, size_t size)
65{
66 long ret = -EFAULT;
67 mm_segment_t old_fs = get_fs();
68
69 set_fs(USER_DS);
70 if (access_ok(src, size))
71 ret = probe_read_common(dst, src, size);
72 set_fs(old_fs);
73
74 return ret;
75}
76EXPORT_SYMBOL_GPL(probe_user_read);
77
78/**
Ingo Molnarc33fa9f2008-04-17 20:05:36 +020079 * probe_kernel_write(): safely attempt to write to a location
80 * @dst: address to write to
81 * @src: pointer to the data that shall be written
82 * @size: size of the data chunk
83 *
84 * Safely write to address @dst from the buffer at @src. If a kernel fault
85 * happens, handle that and return -EFAULT.
86 */
Steven Rostedtf29c5042011-05-19 14:35:33 -040087long __weak probe_kernel_write(void *dst, const void *src, size_t size)
Jason Wessel6144a852010-01-07 11:58:36 -060088 __attribute__((alias("__probe_kernel_write")));
89
Steven Rostedtf29c5042011-05-19 14:35:33 -040090long __probe_kernel_write(void *dst, const void *src, size_t size)
Ingo Molnarc33fa9f2008-04-17 20:05:36 +020091{
92 long ret;
Jason Wesselb4b8ac52008-02-20 13:33:38 -060093 mm_segment_t old_fs = get_fs();
Ingo Molnarc33fa9f2008-04-17 20:05:36 +020094
Jason Wesselb4b8ac52008-02-20 13:33:38 -060095 set_fs(KERNEL_DS);
Ingo Molnarc33fa9f2008-04-17 20:05:36 +020096 pagefault_disable();
97 ret = __copy_to_user_inatomic((__force void __user *)dst, src, size);
98 pagefault_enable();
Jason Wesselb4b8ac52008-02-20 13:33:38 -060099 set_fs(old_fs);
Ingo Molnarc33fa9f2008-04-17 20:05:36 +0200100
101 return ret ? -EFAULT : 0;
102}
103EXPORT_SYMBOL_GPL(probe_kernel_write);
Alexei Starovoitovdbb7ee02015-08-31 08:57:10 -0700104
Masami Hiramatsu3d708182019-05-15 14:38:18 +0900105
Alexei Starovoitovdbb7ee02015-08-31 08:57:10 -0700106/**
107 * strncpy_from_unsafe: - Copy a NUL terminated string from unsafe address.
108 * @dst: Destination address, in kernel space. This buffer must be at
109 * least @count bytes long.
Mike Rapoportf144c392018-02-06 15:42:16 -0800110 * @unsafe_addr: Unsafe address.
Alexei Starovoitovdbb7ee02015-08-31 08:57:10 -0700111 * @count: Maximum number of bytes to copy, including the trailing NUL.
112 *
113 * Copies a NUL-terminated string from unsafe address to kernel buffer.
114 *
115 * On success, returns the length of the string INCLUDING the trailing NUL.
116 *
117 * If access fails, returns -EFAULT (some data may have been copied
118 * and the trailing NUL added).
119 *
120 * If @count is smaller than the length of the string, copies @count-1 bytes,
121 * sets the last byte of @dst buffer to NUL and returns @count.
122 */
123long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count)
124{
125 mm_segment_t old_fs = get_fs();
126 const void *src = unsafe_addr;
127 long ret;
128
129 if (unlikely(count <= 0))
130 return 0;
131
132 set_fs(KERNEL_DS);
133 pagefault_disable();
134
135 do {
Linus Torvaldsbd28b142016-05-22 17:21:27 -0700136 ret = __get_user(*dst++, (const char __user __force *)src++);
Alexei Starovoitovdbb7ee02015-08-31 08:57:10 -0700137 } while (dst[-1] && ret == 0 && src - unsafe_addr < count);
138
139 dst[-1] = '\0';
140 pagefault_enable();
141 set_fs(old_fs);
142
Rasmus Villemoes9dd861d2015-11-05 18:50:11 -0800143 return ret ? -EFAULT : src - unsafe_addr;
Alexei Starovoitovdbb7ee02015-08-31 08:57:10 -0700144}
Masami Hiramatsu3d708182019-05-15 14:38:18 +0900145
146/**
147 * strncpy_from_unsafe_user: - Copy a NUL terminated string from unsafe user
148 * address.
149 * @dst: Destination address, in kernel space. This buffer must be at
150 * least @count bytes long.
151 * @unsafe_addr: Unsafe user address.
152 * @count: Maximum number of bytes to copy, including the trailing NUL.
153 *
154 * Copies a NUL-terminated string from unsafe user address to kernel buffer.
155 *
156 * On success, returns the length of the string INCLUDING the trailing NUL.
157 *
158 * If access fails, returns -EFAULT (some data may have been copied
159 * and the trailing NUL added).
160 *
161 * If @count is smaller than the length of the string, copies @count-1 bytes,
162 * sets the last byte of @dst buffer to NUL and returns @count.
163 */
164long strncpy_from_unsafe_user(char *dst, const void __user *unsafe_addr,
165 long count)
166{
167 mm_segment_t old_fs = get_fs();
168 long ret;
169
170 if (unlikely(count <= 0))
171 return 0;
172
173 set_fs(USER_DS);
174 pagefault_disable();
175 ret = strncpy_from_user(dst, unsafe_addr, count);
176 pagefault_enable();
177 set_fs(old_fs);
178
179 if (ret >= count) {
180 ret = count;
181 dst[ret - 1] = '\0';
182 } else if (ret > 0) {
183 ret++;
184 }
185
186 return ret;
187}
188
189/**
190 * strnlen_unsafe_user: - Get the size of a user string INCLUDING final NUL.
191 * @unsafe_addr: The string to measure.
192 * @count: Maximum count (including NUL)
193 *
194 * Get the size of a NUL-terminated string in user space without pagefault.
195 *
196 * Returns the size of the string INCLUDING the terminating NUL.
197 *
198 * If the string is too long, returns a number larger than @count. User
199 * has to check the return value against "> count".
200 * On exception (or invalid count), returns 0.
201 *
202 * Unlike strnlen_user, this can be used from IRQ handler etc. because
203 * it disables pagefaults.
204 */
205long strnlen_unsafe_user(const void __user *unsafe_addr, long count)
206{
207 mm_segment_t old_fs = get_fs();
208 int ret;
209
210 set_fs(USER_DS);
211 pagefault_disable();
212 ret = strnlen_user(unsafe_addr, count);
213 pagefault_enable();
214 set_fs(old_fs);
215
216 return ret;
217}