Commit 67e8b28b authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] sparse: amd64 annotation - beginning

	Annotated basic primitives (copy_.._user, get_user, ...).
Functions got __user in prototypes, macros (in uaccess.h) got a
conditional check - see CHECK_UPTR() below.  If you have more elegant
way to deal with the macros - please, tell.
parent ecf88904
......@@ -19,7 +19,7 @@
* src and dst are best aligned to 64bits.
*/
unsigned int
csum_partial_copy_from_user(const char *src, char *dst,
csum_partial_copy_from_user(const char __user *src, char *dst,
int len, unsigned int isum, int *errp)
{
*errp = 0;
......@@ -33,7 +33,7 @@ csum_partial_copy_from_user(const char *src, char *dst,
if (unlikely((unsigned long)src & 6)) {
while (((unsigned long)src & 6) && len >= 2) {
__u16 val16;
*errp = __get_user(val16, (__u16 *)src);
*errp = __get_user(val16, (__u16 __user *)src);
if (*errp)
return isum;
*(__u16 *)dst = val16;
......@@ -43,7 +43,7 @@ csum_partial_copy_from_user(const char *src, char *dst,
len -= 2;
}
}
isum = csum_partial_copy_generic(src,dst,len,isum,errp,NULL);
isum = csum_partial_copy_generic((void *)src,dst,len,isum,errp,NULL);
if (likely(*errp == 0))
return isum;
}
......@@ -66,7 +66,7 @@ EXPORT_SYMBOL(csum_partial_copy_from_user);
* src and dst are best aligned to 64bits.
*/
unsigned int
csum_partial_copy_to_user(const char *src, char *dst,
csum_partial_copy_to_user(const char *src, char __user *dst,
int len, unsigned int isum, int *errp)
{
if (unlikely(!access_ok(VERIFY_WRITE, dst, len))) {
......@@ -78,7 +78,7 @@ csum_partial_copy_to_user(const char *src, char *dst,
while (((unsigned long)dst & 6) && len >= 2) {
__u16 val16 = *(__u16 *)src;
isum = add32_with_carry(isum, val16);
*errp = __put_user(val16, (__u16 *)dst);
*errp = __put_user(val16, (__u16 __user *)dst);
if (*errp)
return isum;
src += 2;
......@@ -88,7 +88,7 @@ csum_partial_copy_to_user(const char *src, char *dst,
}
*errp = 0;
return csum_partial_copy_generic(src,dst,len,isum,NULL,errp);
return csum_partial_copy_generic(src, (void *)dst,len,isum,NULL,errp);
}
EXPORT_SYMBOL(csum_partial_copy_to_user);
......
......@@ -40,7 +40,7 @@ do { \
} while (0)
long
__strncpy_from_user(char *dst, const char *src, long count)
__strncpy_from_user(char *dst, const char __user *src, long count)
{
long res;
__do_strncpy_from_user(dst, src, count, res);
......@@ -48,7 +48,7 @@ __strncpy_from_user(char *dst, const char *src, long count)
}
long
strncpy_from_user(char *dst, const char *src, long count)
strncpy_from_user(char *dst, const char __user *src, long count)
{
long res = -EFAULT;
if (access_ok(VERIFY_READ, src, 1))
......@@ -60,7 +60,7 @@ strncpy_from_user(char *dst, const char *src, long count)
* Zero Userspace
*/
unsigned long __clear_user(void *addr, unsigned long size)
unsigned long __clear_user(void __user *addr, unsigned long size)
{
long __d0;
/* no memory constraint because it doesn't change any memory gcc knows
......@@ -94,7 +94,7 @@ unsigned long __clear_user(void *addr, unsigned long size)
}
unsigned long clear_user(void *to, unsigned long n)
unsigned long clear_user(void __user *to, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
return __clear_user(to, n);
......@@ -107,7 +107,7 @@ unsigned long clear_user(void *to, unsigned long n)
* Return 0 on exception, a value greater than N if too long
*/
long strnlen_user(const char *s, long n)
long strnlen_user(const char __user *s, long n)
{
long res = 0;
char c;
......@@ -127,7 +127,7 @@ long strnlen_user(const char *s, long n)
}
}
long strlen_user(const char *s)
long strlen_user(const char __user *s)
{
long res = 0;
char c;
......@@ -142,10 +142,10 @@ long strlen_user(const char *s)
}
}
unsigned long copy_in_user(void *to, const void *from, unsigned len)
unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len)
{
if (access_ok(VERIFY_WRITE, to, len) && access_ok(VERIFY_READ, from, len)) {
return copy_user_generic(to, from, len);
return copy_user_generic((void *)to, (void *)from, len);
}
return len;
}
......@@ -186,15 +186,15 @@ struct compat_shmid64_ds {
*/
typedef u32 compat_uptr_t;
static inline void *compat_ptr(compat_uptr_t uptr)
static inline void __user *compat_ptr(compat_uptr_t uptr)
{
return (void *)(unsigned long)uptr;
return (void __user *)(unsigned long)uptr;
}
static __inline__ void *compat_alloc_user_space(long len)
static __inline__ void __user *compat_alloc_user_space(long len)
{
struct pt_regs *regs = (void *)current->thread.rsp0 - sizeof(struct pt_regs);
return (void *)regs->rsp - len;
return (void __user *)regs->rsp - len;
}
#endif /* _ASM_X86_64_COMPAT_H */
......@@ -33,6 +33,16 @@
#define segment_eq(a,b) ((a).seg == (b).seg)
#ifdef __CHECKER__
#define CHECK_UPTR(ptr) do { \
__typeof__(*(ptr)) *__dummy_check_uptr = \
(void __user *)&__dummy_check_uptr; \
} while(0)
#else
#define CHECK_UPTR(ptr)
#endif
#define __addr_ok(addr) (!((unsigned long)(addr) & (current_thread_info()->addr_limit.seg)))
/*
......@@ -40,15 +50,16 @@
*/
#define __range_not_ok(addr,size) ({ \
unsigned long flag,sum; \
CHECK_UPTR(addr); \
asm("# range_ok\n\r" \
"addq %3,%1 ; sbbq %0,%0 ; cmpq %1,%4 ; sbbq $0,%0" \
:"=&r" (flag), "=r" (sum) \
:"1" (addr),"g" ((long)(size)),"g" (current_thread_info()->addr_limit.seg)); \
flag; })
#define access_ok(type,addr,size) (__range_not_ok(addr,size) == 0)
#define access_ok(type, addr, size) (__range_not_ok(addr,size) == 0)
extern inline int verify_area(int type, const void * addr, unsigned long size)
extern inline int verify_area(int type, const void __user * addr, unsigned long size)
{
return access_ok(type,addr,size) ? 0 : -EFAULT;
}
......@@ -103,6 +114,7 @@ extern void __get_user_8(void);
#define get_user(x,ptr) \
({ long __val_gu; \
int __ret_gu; \
CHECK_UPTR(ptr); \
switch(sizeof (*(ptr))) { \
case 1: __get_user_x(1,__ret_gu,__val_gu,ptr); break; \
case 2: __get_user_x(2,__ret_gu,__val_gu,ptr); break; \
......@@ -138,6 +150,7 @@ extern void __put_user_bad(void);
#define __put_user_nocheck(x,ptr,size) \
({ \
int __pu_err; \
CHECK_UPTR(ptr); \
__put_user_size((x),(ptr),(size),__pu_err); \
__pu_err; \
})
......@@ -193,6 +206,7 @@ struct __large_struct { unsigned long buf[100]; };
({ \
int __gu_err; \
long __gu_val; \
CHECK_UPTR(ptr); \
__get_user_size(__gu_val,(ptr),(size),__gu_err); \
(x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \
......@@ -235,15 +249,15 @@ do { \
/* Handles exceptions in both to and from, but doesn't do access_ok */
extern unsigned long copy_user_generic(void *to, const void *from, unsigned len);
extern unsigned long copy_to_user(void *to, const void *from, unsigned len);
extern unsigned long copy_from_user(void *to, const void *from, unsigned len);
extern unsigned long copy_in_user(void *to, const void *from, unsigned len);
extern unsigned long copy_to_user(void __user *to, const void *from, unsigned len);
extern unsigned long copy_from_user(void *to, const void __user *from, unsigned len);
extern unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len);
static inline int __copy_from_user(void *dst, const void *src, unsigned size)
static inline int __copy_from_user(void *dst, const void __user *src, unsigned size)
{
int ret = 0;
if (!__builtin_constant_p(size))
return copy_user_generic(dst,src,size);
return copy_user_generic(dst,(void *)src,size);
switch (size) {
case 1:__get_user_asm(*(u8*)dst,(u8 *)src,ret,"b","b","=q",1);
return ret;
......@@ -264,15 +278,15 @@ static inline int __copy_from_user(void *dst, const void *src, unsigned size)
__get_user_asm(*(u64*)(8+(char*)dst),(u64*)(8+(char*)src),ret,"q","","=r",8);
return ret;
default:
return copy_user_generic(dst,src,size);
return copy_user_generic(dst,(void *)src,size);
}
}
static inline int __copy_to_user(void *dst, const void *src, unsigned size)
static inline int __copy_to_user(void __user *dst, const void *src, unsigned size)
{
int ret = 0;
if (!__builtin_constant_p(size))
return copy_user_generic(dst,src,size);
return copy_user_generic((void *)dst,src,size);
switch (size) {
case 1:__put_user_asm(*(u8*)src,(u8 *)dst,ret,"b","b","iq",1);
return ret;
......@@ -295,16 +309,16 @@ static inline int __copy_to_user(void *dst, const void *src, unsigned size)
__put_user_asm(1[(u64*)src],1+(u64*)dst,ret,"q","","ir",8);
return ret;
default:
return copy_user_generic(dst,src,size);
return copy_user_generic((void *)dst,src,size);
}
}
static inline int __copy_in_user(void *dst, const void *src, unsigned size)
static inline int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
{
int ret = 0;
if (!__builtin_constant_p(size))
return copy_user_generic(dst,src,size);
return copy_user_generic((void *)dst,(void *)src,size);
switch (size) {
case 1: {
u8 tmp;
......@@ -336,15 +350,15 @@ static inline int __copy_in_user(void *dst, const void *src, unsigned size)
return ret;
}
default:
return copy_user_generic(dst,src,size);
return copy_user_generic((void *)dst,(void *)src,size);
}
}
long strncpy_from_user(char *dst, const char *src, long count);
long __strncpy_from_user(char *dst, const char *src, long count);
long strnlen_user(const char *str, long n);
long strlen_user(const char *str);
unsigned long clear_user(void *mem, unsigned long len);
unsigned long __clear_user(void *mem, unsigned long len);
long strncpy_from_user(char *dst, const char __user *src, long count);
long __strncpy_from_user(char *dst, const char __user *src, long count);
long strnlen_user(const char __user *str, long n);
long strlen_user(const char __user *str);
unsigned long clear_user(void __user *mem, unsigned long len);
unsigned long __clear_user(void __user *mem, unsigned long len);
#endif /* __X86_64_UACCESS_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment