2009-05-14 02:56:37 +04:00
# ifndef __ASM_GENERIC_UACCESS_H
# define __ASM_GENERIC_UACCESS_H
/*
* User space memory access functions , these should work
2013-12-30 13:06:33 +04:00
* on any machine that has kernel and user data in the same
2009-05-14 02:56:37 +04:00
* address space , e . g . all NOMMU machines .
*/
# include <linux/string.h>
# include <asm/segment.h>
# define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
# ifndef KERNEL_DS
# define KERNEL_DS MAKE_MM_SEG(~0UL)
# endif
# ifndef USER_DS
# define USER_DS MAKE_MM_SEG(TASK_SIZE - 1)
# endif
# ifndef get_fs
# define get_ds() (KERNEL_DS)
# define get_fs() (current_thread_info()->addr_limit)
static inline void set_fs ( mm_segment_t fs )
{
current_thread_info ( ) - > addr_limit = fs ;
}
# endif
2013-01-18 13:42:16 +04:00
# ifndef segment_eq
2009-05-14 02:56:37 +04:00
# define segment_eq(a, b) ((a).seg == (b).seg)
2013-01-18 13:42:16 +04:00
# endif
2009-05-14 02:56:37 +04:00
# define access_ok(type, addr, size) __access_ok((unsigned long)(addr),(size))
/*
* The architecture should really override this if possible , at least
* doing a check on the get_fs ( )
*/
# ifndef __access_ok
static inline int __access_ok ( unsigned long addr , unsigned long size )
{
return 1 ;
}
# endif
/*
* These are the main single - value transfer routines . They automatically
* use the right size if we just have the right pointer type .
* This version just falls back to copy_ { from , to } _user , which should
* provide a fast - path for small values .
*/
# define __put_user(x, ptr) \
( { \
__typeof__ ( * ( ptr ) ) __x = ( x ) ; \
int __pu_err = - EFAULT ; \
__chk_user_ptr ( ptr ) ; \
switch ( sizeof ( * ( ptr ) ) ) { \
case 1 : \
case 2 : \
case 4 : \
case 8 : \
__pu_err = __put_user_fn ( sizeof ( * ( ptr ) ) , \
ptr , & __x ) ; \
break ; \
default : \
__put_user_bad ( ) ; \
break ; \
} \
__pu_err ; \
} )
# define put_user(x, ptr) \
( { \
2017-09-04 19:07:24 +03:00
void __user * __p = ( ptr ) ; \
2013-05-26 18:30:36 +04:00
might_fault ( ) ; \
2015-07-16 07:56:06 +03:00
access_ok ( VERIFY_WRITE , __p , sizeof ( * ptr ) ) ? \
2017-09-04 19:07:24 +03:00
__put_user ( ( x ) , ( ( __typeof__ ( * ( ptr ) ) __user * ) __p ) ) : \
2009-05-14 02:56:37 +04:00
- EFAULT ; \
} )
2013-01-18 13:42:16 +04:00
# ifndef __put_user_fn
2009-05-14 02:56:37 +04:00
static inline int __put_user_fn ( size_t size , void __user * ptr , void * x )
{
2017-03-21 04:56:06 +03:00
return unlikely ( raw_copy_to_user ( ptr , x , size ) ) ? - EFAULT : 0 ;
2009-05-14 02:56:37 +04:00
}
2013-01-18 13:42:16 +04:00
# define __put_user_fn(sz, u, k) __put_user_fn(sz, u, k)
# endif
2009-05-14 02:56:37 +04:00
extern int __put_user_bad ( void ) __attribute__ ( ( noreturn ) ) ;
# define __get_user(x, ptr) \
( { \
int __gu_err = - EFAULT ; \
__chk_user_ptr ( ptr ) ; \
switch ( sizeof ( * ( ptr ) ) ) { \
case 1 : { \
2017-03-28 08:02:40 +03:00
unsigned char __x = 0 ; \
2009-05-14 02:56:37 +04:00
__gu_err = __get_user_fn ( sizeof ( * ( ptr ) ) , \
ptr , & __x ) ; \
( x ) = * ( __force __typeof__ ( * ( ptr ) ) * ) & __x ; \
break ; \
} ; \
case 2 : { \
2017-03-28 08:02:40 +03:00
unsigned short __x = 0 ; \
2009-05-14 02:56:37 +04:00
__gu_err = __get_user_fn ( sizeof ( * ( ptr ) ) , \
ptr , & __x ) ; \
( x ) = * ( __force __typeof__ ( * ( ptr ) ) * ) & __x ; \
break ; \
} ; \
case 4 : { \
2017-03-28 08:02:40 +03:00
unsigned int __x = 0 ; \
2009-05-14 02:56:37 +04:00
__gu_err = __get_user_fn ( sizeof ( * ( ptr ) ) , \
ptr , & __x ) ; \
( x ) = * ( __force __typeof__ ( * ( ptr ) ) * ) & __x ; \
break ; \
} ; \
case 8 : { \
2017-03-28 08:02:40 +03:00
unsigned long long __x = 0 ; \
2009-05-14 02:56:37 +04:00
__gu_err = __get_user_fn ( sizeof ( * ( ptr ) ) , \
ptr , & __x ) ; \
( x ) = * ( __force __typeof__ ( * ( ptr ) ) * ) & __x ; \
break ; \
} ; \
default : \
__get_user_bad ( ) ; \
break ; \
} \
__gu_err ; \
} )
# define get_user(x, ptr) \
( { \
2017-09-04 19:07:24 +03:00
const void __user * __p = ( ptr ) ; \
2013-05-26 18:30:36 +04:00
might_fault ( ) ; \
2015-07-16 07:56:06 +03:00
access_ok ( VERIFY_READ , __p , sizeof ( * ptr ) ) ? \
2017-09-04 19:07:24 +03:00
__get_user ( ( x ) , ( __typeof__ ( * ( ptr ) ) __user * ) __p ) : \
2016-08-18 06:19:01 +03:00
( ( x ) = ( __typeof__ ( * ( ptr ) ) ) 0 , - EFAULT ) ; \
2009-05-14 02:56:37 +04:00
} )
2013-01-18 13:42:16 +04:00
# ifndef __get_user_fn
2009-05-14 02:56:37 +04:00
static inline int __get_user_fn ( size_t size , const void __user * ptr , void * x )
{
2017-03-21 04:56:06 +03:00
return unlikely ( raw_copy_from_user ( x , ptr , size ) ) ? - EFAULT : 0 ;
2009-05-14 02:56:37 +04:00
}
2013-01-18 13:42:16 +04:00
# define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k)
# endif
2009-05-14 02:56:37 +04:00
extern int __get_user_bad ( void ) __attribute__ ( ( noreturn ) ) ;
/*
* Copy a null terminated string from userspace .
*/
# ifndef __strncpy_from_user
static inline long
__strncpy_from_user ( char * dst , const char __user * src , long count )
{
char * tmp ;
strncpy ( dst , ( const char __force * ) src , count ) ;
for ( tmp = dst ; * tmp & & count > 0 ; tmp + + , count - - )
;
return ( tmp - dst ) ;
}
# endif
static inline long
strncpy_from_user ( char * dst , const char __user * src , long count )
{
2009-06-14 10:00:03 +04:00
if ( ! access_ok ( VERIFY_READ , src , 1 ) )
2009-05-14 02:56:37 +04:00
return - EFAULT ;
return __strncpy_from_user ( dst , src , count ) ;
}
/*
* Return the size of a string ( including the ending 0 )
*
* Return 0 on exception , a value greater than N if too long
*/
2011-01-15 13:08:09 +03:00
# ifndef __strnlen_user
2011-10-04 17:17:36 +04:00
# define __strnlen_user(s, n) (strnlen((s), (n)) + 1)
2011-01-15 13:08:09 +03:00
# endif
2011-10-04 17:17:36 +04:00
/*
* Unlike strnlen , strnlen_user includes the nul terminator in
* its returned count . Callers should check for a returned value
* greater than N as an indication the string is too long .
*/
2009-05-14 02:56:37 +04:00
static inline long strnlen_user ( const char __user * src , long n )
{
2009-06-14 10:00:02 +04:00
if ( ! access_ok ( VERIFY_READ , src , 1 ) )
return 0 ;
2011-01-15 13:08:09 +03:00
return __strnlen_user ( src , n ) ;
2009-05-14 02:56:37 +04:00
}
/*
* Zero Userspace
*/
# ifndef __clear_user
static inline __must_check unsigned long
__clear_user ( void __user * to , unsigned long n )
{
memset ( ( void __force * ) to , 0 , n ) ;
return 0 ;
}
# endif
static inline __must_check unsigned long
clear_user ( void __user * to , unsigned long n )
{
2013-05-26 18:30:36 +04:00
might_fault ( ) ;
2009-06-14 10:00:03 +04:00
if ( ! access_ok ( VERIFY_WRITE , to , n ) )
2009-05-14 02:56:37 +04:00
return n ;
return __clear_user ( to , n ) ;
}
2016-12-25 09:22:09 +03:00
# include <asm/extable.h>
2009-05-14 02:56:37 +04:00
# endif /* __ASM_GENERIC_UACCESS_H */