1 /*
2  * User address space access functions.
3  * The non inlined parts of asm-i386/uaccess.h are here.
4  *
5  * Copyright 1997 Andi Kleen <ak@muc.de>
6  * Copyright 1997 Linus Torvalds
7  */
8 #include <linux/config.h>
9 #include <asm/uaccess.h>
10 #include <asm/mmx.h>
11 
12 #ifdef CONFIG_X86_USE_3DNOW_AND_WORKS
13 
14 unsigned long
__generic_copy_to_user(void * to,const void * from,unsigned long n)15 __generic_copy_to_user(void *to, const void *from, unsigned long n)
16 {
17 	BUG_ON((long) n < 0);
18 	if (access_ok(VERIFY_WRITE, to, n))
19 	{
20 		if(n<512)
21 			__copy_user(to,from,n);
22 		else
23 			mmx_copy_user(to,from,n);
24 	}
25 	return n;
26 }
27 
28 unsigned long
__generic_copy_from_user(void * to,const void * from,unsigned long n)29 __generic_copy_from_user(void *to, const void *from, unsigned long n)
30 {
31 	BUG_ON((long) n < 0);
32 	if (access_ok(VERIFY_READ, from, n))
33 	{
34 		if(n<512)
35 			__copy_user_zeroing(to,from,n);
36 		else
37 			mmx_copy_user_zeroing(to, from, n);
38 	}
39 	else
40 		memset(to, 0, n);
41 	return n;
42 }
43 
44 #else
45 
46 unsigned long
__generic_copy_to_user(void * to,const void * from,unsigned long n)47 __generic_copy_to_user(void *to, const void *from, unsigned long n)
48 {
49 	BUG_ON((long) n < 0);
50 	prefetch(from);
51 	if (access_ok(VERIFY_WRITE, to, n))
52 		__copy_user(to,from,n);
53 	return n;
54 }
55 
56 unsigned long
__generic_copy_from_user(void * to,const void * from,unsigned long n)57 __generic_copy_from_user(void *to, const void *from, unsigned long n)
58 {
59 	BUG_ON((long) n < 0);
60 	prefetchw(to);
61 	if (access_ok(VERIFY_READ, from, n))
62 		__copy_user_zeroing(to,from,n);
63 	else
64 		memset(to, 0, n);
65 	return n;
66 }
67 
68 #endif
69 
70 /*
71  * Copy a null terminated string from userspace.
72  */
73 
74 #define __do_strncpy_from_user(dst,src,count,res)			   \
75 do {									   \
76 	int __d0, __d1, __d2;						   \
77 	__asm__ __volatile__(						   \
78 		"	testl %1,%1\n"					   \
79 		"	jz 2f\n"					   \
80 		"0:	lodsb\n"					   \
81 		"	stosb\n"					   \
82 		"	testb %%al,%%al\n"				   \
83 		"	jz 1f\n"					   \
84 		"	decl %1\n"					   \
85 		"	jnz 0b\n"					   \
86 		"1:	subl %1,%0\n"					   \
87 		"2:\n"							   \
88 		".section .fixup,\"ax\"\n"				   \
89 		"3:	movl %5,%0\n"					   \
90 		"	jmp 2b\n"					   \
91 		".previous\n"						   \
92 		".section __ex_table,\"a\"\n"				   \
93 		"	.align 4\n"					   \
94 		"	.long 0b,3b\n"					   \
95 		".previous"						   \
96 		: "=d"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1),	   \
97 		  "=&D" (__d2)						   \
98 		: "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
99 		: "memory");						   \
100 } while (0)
101 
102 /**
103  * __strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking.
104  * @dst:   Destination address, in kernel space.  This buffer must be at
105  *         least @count bytes long.
106  * @src:   Source address, in user space.
107  * @count: Maximum number of bytes to copy, including the trailing NUL.
108  *
109  * Copies a NUL-terminated string from userspace to kernel space.
110  * Caller must check the specified block with access_ok() before calling
111  * this function.
112  *
113  * On success, returns the length of the string (not including the trailing
114  * NUL).
115  *
116  * If access to userspace fails, returns -EFAULT (some data may have been
117  * copied).
118  *
119  * If @count is smaller than the length of the string, copies @count bytes
120  * and returns @count.
121  */
122 long
__strncpy_from_user(char * dst,const char * src,long count)123 __strncpy_from_user(char *dst, const char *src, long count)
124 {
125 	long res;
126 	__do_strncpy_from_user(dst, src, count, res);
127 	return res;
128 }
129 
130 /**
131  * strncpy_from_user: - Copy a NUL terminated string from userspace.
132  * @dst:   Destination address, in kernel space.  This buffer must be at
133  *         least @count bytes long.
134  * @src:   Source address, in user space.
135  * @count: Maximum number of bytes to copy, including the trailing NUL.
136  *
137  * Copies a NUL-terminated string from userspace to kernel space.
138  *
139  * On success, returns the length of the string (not including the trailing
140  * NUL).
141  *
142  * If access to userspace fails, returns -EFAULT (some data may have been
143  * copied).
144  *
145  * If @count is smaller than the length of the string, copies @count bytes
146  * and returns @count.
147  */
148 long
strncpy_from_user(char * dst,const char * src,long count)149 strncpy_from_user(char *dst, const char *src, long count)
150 {
151 	long res = -EFAULT;
152 	if (access_ok(VERIFY_READ, src, 1))
153 		__do_strncpy_from_user(dst, src, count, res);
154 	return res;
155 }
156 
157 
158 /*
159  * Zero Userspace
160  */
161 
162 #define __do_clear_user(addr,size)					\
163 do {									\
164 	int __d0;							\
165   	__asm__ __volatile__(						\
166 		"0:	rep; stosl\n"					\
167 		"	movl %2,%0\n"					\
168 		"1:	rep; stosb\n"					\
169 		"2:\n"							\
170 		".section .fixup,\"ax\"\n"				\
171 		"3:	lea 0(%2,%0,4),%0\n"				\
172 		"	jmp 2b\n"					\
173 		".previous\n"						\
174 		".section __ex_table,\"a\"\n"				\
175 		"	.align 4\n"					\
176 		"	.long 0b,3b\n"					\
177 		"	.long 1b,2b\n"					\
178 		".previous"						\
179 		: "=&c"(size), "=&D" (__d0)				\
180 		: "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0));	\
181 } while (0)
182 
183 /**
184  * clear_user: - Zero a block of memory in user space.
185  * @to:   Destination address, in user space.
186  * @n:    Number of bytes to zero.
187  *
188  * Zero a block of memory in user space.
189  *
190  * Returns number of bytes that could not be cleared.
191  * On success, this will be zero.
192  */
193 unsigned long
clear_user(void * to,unsigned long n)194 clear_user(void *to, unsigned long n)
195 {
196 	if (access_ok(VERIFY_WRITE, to, n))
197 		__do_clear_user(to, n);
198 	return n;
199 }
200 
201 /**
202  * __clear_user: - Zero a block of memory in user space, with less checking.
203  * @to:   Destination address, in user space.
204  * @n:    Number of bytes to zero.
205  *
206  * Zero a block of memory in user space.  Caller must check
207  * the specified block with access_ok() before calling this function.
208  *
209  * Returns number of bytes that could not be cleared.
210  * On success, this will be zero.
211  */
212 unsigned long
__clear_user(void * to,unsigned long n)213 __clear_user(void *to, unsigned long n)
214 {
215 	__do_clear_user(to, n);
216 	return n;
217 }
218 
219 /**
220  * strlen_user: - Get the size of a string in user space.
221  * @str: The string to measure.
222  * @n:   The maximum valid length
223  *
224  * Get the size of a NUL-terminated string in user space.
225  *
226  * Returns the size of the string INCLUDING the terminating NUL.
227  * On exception, returns 0.
228  * If the string is too long, returns a value greater than @n.
229  */
strnlen_user(const char * s,long n)230 long strnlen_user(const char *s, long n)
231 {
232 	unsigned long mask = -__addr_ok(s);
233 	unsigned long res, tmp;
234 
235 	__asm__ __volatile__(
236 		"	testl %0, %0\n"
237 		"	jz 3f\n"
238 		"	andl %0,%%ecx\n"
239 		"0:	repne; scasb\n"
240 		"	setne %%al\n"
241 		"	subl %%ecx,%0\n"
242 		"	addl %0,%%eax\n"
243 		"1:\n"
244 		".section .fixup,\"ax\"\n"
245 		"2:	xorl %%eax,%%eax\n"
246 		"	jmp 1b\n"
247 		"3:	movb $1,%%al\n"
248 		"	jmp 1b\n"
249 		".previous\n"
250 		".section __ex_table,\"a\"\n"
251 		"	.align 4\n"
252 		"	.long 0b,2b\n"
253 		".previous"
254 		:"=r" (n), "=D" (s), "=a" (res), "=c" (tmp)
255 		:"0" (n), "1" (s), "2" (0), "3" (mask)
256 		:"cc");
257 	return res & mask;
258 }
259