diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2006-06-23 05:04:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-23 10:42:54 -0400 |
commit | a8a77573c9e5345bcf6a963858745cd83c923f44 (patch) | |
tree | 04f9bc72aca54effdb2254dd1e0b8ec5fa94f6cf | |
parent | 86c3a7645c05a7d06b72653aa4b2bea4e7229d1b (diff) |
[PATCH] frv: __user infrastructure
Add general annotations to the FRV arch for sparse.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/frv/kernel/uaccess.c | 6 | ||||
-rw-r--r-- | include/asm-frv/uaccess.h | 64 |
2 files changed, 40 insertions, 30 deletions
diff --git a/arch/frv/kernel/uaccess.c b/arch/frv/kernel/uaccess.c index 9b751c0f0e84..9fb771a20df3 100644 --- a/arch/frv/kernel/uaccess.c +++ b/arch/frv/kernel/uaccess.c | |||
@@ -17,7 +17,7 @@ | |||
17 | /* | 17 | /* |
18 | * copy a null terminated string from userspace | 18 | * copy a null terminated string from userspace |
19 | */ | 19 | */ |
20 | long strncpy_from_user(char *dst, const char *src, long count) | 20 | long strncpy_from_user(char *dst, const char __user *src, long count) |
21 | { | 21 | { |
22 | unsigned long max; | 22 | unsigned long max; |
23 | char *p, ch; | 23 | char *p, ch; |
@@ -70,9 +70,9 @@ EXPORT_SYMBOL(strncpy_from_user); | |||
70 | * | 70 | * |
71 | * Return 0 on exception, a value greater than N if too long | 71 | * Return 0 on exception, a value greater than N if too long |
72 | */ | 72 | */ |
73 | long strnlen_user(const char *src, long count) | 73 | long strnlen_user(const char __user *src, long count) |
74 | { | 74 | { |
75 | const char *p; | 75 | const char __user *p; |
76 | long err = 0; | 76 | long err = 0; |
77 | char ch; | 77 | char ch; |
78 | 78 | ||
diff --git a/include/asm-frv/uaccess.h b/include/asm-frv/uaccess.h index a1d140438863..3d90e1018ee2 100644 --- a/include/asm-frv/uaccess.h +++ b/include/asm-frv/uaccess.h | |||
@@ -22,7 +22,7 @@ | |||
22 | 22 | ||
23 | #define HAVE_ARCH_UNMAPPED_AREA /* we decide where to put mmaps */ | 23 | #define HAVE_ARCH_UNMAPPED_AREA /* we decide where to put mmaps */ |
24 | 24 | ||
25 | #define __ptr(x) ((unsigned long *)(x)) | 25 | #define __ptr(x) ((unsigned long __force *)(x)) |
26 | 26 | ||
27 | #define VERIFY_READ 0 | 27 | #define VERIFY_READ 0 |
28 | #define VERIFY_WRITE 1 | 28 | #define VERIFY_WRITE 1 |
@@ -64,7 +64,7 @@ static inline int ___range_ok(unsigned long addr, unsigned long size) | |||
64 | 64 | ||
65 | #define __range_ok(addr,size) ___range_ok((unsigned long) (addr), (unsigned long) (size)) | 65 | #define __range_ok(addr,size) ___range_ok((unsigned long) (addr), (unsigned long) (size)) |
66 | 66 | ||
67 | #define access_ok(type,addr,size) (__range_ok((addr), (size)) == 0) | 67 | #define access_ok(type,addr,size) (__range_ok((void __user *)(addr), (size)) == 0) |
68 | #define __access_ok(addr,size) (__range_ok((addr), (size)) == 0) | 68 | #define __access_ok(addr,size) (__range_ok((addr), (size)) == 0) |
69 | 69 | ||
70 | /* | 70 | /* |
@@ -97,6 +97,7 @@ extern unsigned long search_exception_table(unsigned long); | |||
97 | int __pu_err = 0; \ | 97 | int __pu_err = 0; \ |
98 | \ | 98 | \ |
99 | typeof(*(ptr)) __pu_val = (x); \ | 99 | typeof(*(ptr)) __pu_val = (x); \ |
100 | __chk_user_ptr(ptr); \ | ||
100 | \ | 101 | \ |
101 | switch (sizeof (*(ptr))) { \ | 102 | switch (sizeof (*(ptr))) { \ |
102 | case 1: \ | 103 | case 1: \ |
@@ -120,7 +121,7 @@ extern unsigned long search_exception_table(unsigned long); | |||
120 | 121 | ||
121 | #define put_user(x, ptr) \ | 122 | #define put_user(x, ptr) \ |
122 | ({ \ | 123 | ({ \ |
123 | typeof(&*ptr) _p = (ptr); \ | 124 | typeof(*(ptr)) __user *_p = (ptr); \ |
124 | int _e; \ | 125 | int _e; \ |
125 | \ | 126 | \ |
126 | _e = __range_ok(_p, sizeof(*_p)); \ | 127 | _e = __range_ok(_p, sizeof(*_p)); \ |
@@ -175,33 +176,44 @@ do { \ | |||
175 | */ | 176 | */ |
176 | #define __get_user(x, ptr) \ | 177 | #define __get_user(x, ptr) \ |
177 | ({ \ | 178 | ({ \ |
178 | typeof(*(ptr)) __gu_val = 0; \ | ||
179 | int __gu_err = 0; \ | 179 | int __gu_err = 0; \ |
180 | __chk_user_ptr(ptr); \ | ||
180 | \ | 181 | \ |
181 | switch (sizeof(*(ptr))) { \ | 182 | switch (sizeof(*(ptr))) { \ |
182 | case 1: \ | 183 | case 1: { \ |
183 | __get_user_asm(__gu_err, *(u8*)&__gu_val, ptr, "ub", "=r"); \ | 184 | unsigned char __gu_val; \ |
185 | __get_user_asm(__gu_err, __gu_val, ptr, "ub", "=r"); \ | ||
186 | (x) = *(__force __typeof__(*(ptr)) *) &__gu_val; \ | ||
184 | break; \ | 187 | break; \ |
185 | case 2: \ | 188 | } \ |
186 | __get_user_asm(__gu_err, *(u16*)&__gu_val, ptr, "uh", "=r"); \ | 189 | case 2: { \ |
190 | unsigned short __gu_val; \ | ||
191 | __get_user_asm(__gu_err, __gu_val, ptr, "uh", "=r"); \ | ||
192 | (x) = *(__force __typeof__(*(ptr)) *) &__gu_val; \ | ||
187 | break; \ | 193 | break; \ |
188 | case 4: \ | 194 | } \ |
189 | __get_user_asm(__gu_err, *(u32*)&__gu_val, ptr, "", "=r"); \ | 195 | case 4: { \ |
196 | unsigned int __gu_val; \ | ||
197 | __get_user_asm(__gu_err, __gu_val, ptr, "", "=r"); \ | ||
198 | (x) = *(__force __typeof__(*(ptr)) *) &__gu_val; \ | ||
190 | break; \ | 199 | break; \ |
191 | case 8: \ | 200 | } \ |
192 | __get_user_asm(__gu_err, *(u64*)&__gu_val, ptr, "d", "=e"); \ | 201 | case 8: { \ |
202 | unsigned long long __gu_val; \ | ||
203 | __get_user_asm(__gu_err, __gu_val, ptr, "d", "=e"); \ | ||
204 | (x) = *(__force __typeof__(*(ptr)) *) &__gu_val; \ | ||
193 | break; \ | 205 | break; \ |
206 | } \ | ||
194 | default: \ | 207 | default: \ |
195 | __gu_err = __get_user_bad(); \ | 208 | __gu_err = __get_user_bad(); \ |
196 | break; \ | 209 | break; \ |
197 | } \ | 210 | } \ |
198 | (x) = __gu_val; \ | ||
199 | __gu_err; \ | 211 | __gu_err; \ |
200 | }) | 212 | }) |
201 | 213 | ||
202 | #define get_user(x, ptr) \ | 214 | #define get_user(x, ptr) \ |
203 | ({ \ | 215 | ({ \ |
204 | typeof(&*ptr) _p = (ptr); \ | 216 | const typeof(*(ptr)) __user *_p = (ptr);\ |
205 | int _e; \ | 217 | int _e; \ |
206 | \ | 218 | \ |
207 | _e = __range_ok(_p, sizeof(*_p)); \ | 219 | _e = __range_ok(_p, sizeof(*_p)); \ |
@@ -248,19 +260,20 @@ do { \ | |||
248 | /* | 260 | /* |
249 | * | 261 | * |
250 | */ | 262 | */ |
263 | #define ____force(x) (__force void *)(void __user *)(x) | ||
251 | #ifdef CONFIG_MMU | 264 | #ifdef CONFIG_MMU |
252 | extern long __memset_user(void *dst, unsigned long count); | 265 | extern long __memset_user(void *dst, unsigned long count); |
253 | extern long __memcpy_user(void *dst, const void *src, unsigned long count); | 266 | extern long __memcpy_user(void *dst, const void *src, unsigned long count); |
254 | 267 | ||
255 | #define clear_user(dst,count) __memset_user((dst), (count)) | 268 | #define clear_user(dst,count) __memset_user(____force(dst), (count)) |
256 | #define __copy_from_user_inatomic(to, from, n) __memcpy_user((to), (from), (n)) | 269 | #define __copy_from_user_inatomic(to, from, n) __memcpy_user((to), ____force(from), (n)) |
257 | #define __copy_to_user_inatomic(to, from, n) __memcpy_user((to), (from), (n)) | 270 | #define __copy_to_user_inatomic(to, from, n) __memcpy_user(____force(to), (from), (n)) |
258 | 271 | ||
259 | #else | 272 | #else |
260 | 273 | ||
261 | #define clear_user(dst,count) (memset((dst), 0, (count)), 0) | 274 | #define clear_user(dst,count) (memset(____force(dst), 0, (count)), 0) |
262 | #define __copy_from_user_inatomic(to, from, n) (memcpy((to), (from), (n)), 0) | 275 | #define __copy_from_user_inatomic(to, from, n) (memcpy((to), ____force(from), (n)), 0) |
263 | #define __copy_to_user_inatomic(to, from, n) (memcpy((to), (from), (n)), 0) | 276 | #define __copy_to_user_inatomic(to, from, n) (memcpy(____force(to), (from), (n)), 0) |
264 | 277 | ||
265 | #endif | 278 | #endif |
266 | 279 | ||
@@ -278,7 +291,7 @@ __copy_from_user(void *to, const void __user *from, unsigned long n) | |||
278 | return __copy_from_user_inatomic(to, from, n); | 291 | return __copy_from_user_inatomic(to, from, n); |
279 | } | 292 | } |
280 | 293 | ||
281 | static inline long copy_from_user(void *to, const void *from, unsigned long n) | 294 | static inline long copy_from_user(void *to, const void __user *from, unsigned long n) |
282 | { | 295 | { |
283 | unsigned long ret = n; | 296 | unsigned long ret = n; |
284 | 297 | ||
@@ -291,16 +304,13 @@ static inline long copy_from_user(void *to, const void *from, unsigned long n) | |||
291 | return ret; | 304 | return ret; |
292 | } | 305 | } |
293 | 306 | ||
294 | static inline long copy_to_user(void *to, const void *from, unsigned long n) | 307 | static inline long copy_to_user(void __user *to, const void *from, unsigned long n) |
295 | { | 308 | { |
296 | return likely(__access_ok(to, n)) ? __copy_to_user(to, from, n) : n; | 309 | return likely(__access_ok(to, n)) ? __copy_to_user(to, from, n) : n; |
297 | } | 310 | } |
298 | 311 | ||
299 | #define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; }) | 312 | extern long strncpy_from_user(char *dst, const char __user *src, long count); |
300 | #define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; }) | 313 | extern long strnlen_user(const char __user *src, long count); |
301 | |||
302 | extern long strncpy_from_user(char *dst, const char *src, long count); | ||
303 | extern long strnlen_user(const char *src, long count); | ||
304 | 314 | ||
305 | #define strlen_user(str) strnlen_user(str, 32767) | 315 | #define strlen_user(str) strnlen_user(str, 32767) |
306 | 316 | ||