xref: /openbmc/linux/mm/maccess.c (revision 6084466e)
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