51 lines
		
	
	
	
		
			1.1 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			51 lines
		
	
	
	
		
			1.1 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
|   | #ifndef UACCESS_H
 | ||
|  | #define UACCESS_H
 | ||
|  | extern void *__user_addr_min, *__user_addr_max; | ||
|  | 
 | ||
|  | #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
 | ||
|  | 
 | ||
|  | static inline void __chk_user_ptr(const volatile void *p, size_t size) | ||
|  | { | ||
|  | 	assert(p >= __user_addr_min && p + size <= __user_addr_max); | ||
|  | } | ||
|  | 
 | ||
|  | #define put_user(x, ptr)					\
 | ||
|  | ({								\ | ||
|  | 	typeof(ptr) __pu_ptr = (ptr);				\ | ||
|  | 	__chk_user_ptr(__pu_ptr, sizeof(*__pu_ptr));		\ | ||
|  | 	ACCESS_ONCE(*(__pu_ptr)) = x;				\ | ||
|  | 	0;							\ | ||
|  | }) | ||
|  | 
 | ||
|  | #define get_user(x, ptr)					\
 | ||
|  | ({								\ | ||
|  | 	typeof(ptr) __pu_ptr = (ptr);				\ | ||
|  | 	__chk_user_ptr(__pu_ptr, sizeof(*__pu_ptr));		\ | ||
|  | 	x = ACCESS_ONCE(*(__pu_ptr));				\ | ||
|  | 	0;							\ | ||
|  | }) | ||
|  | 
 | ||
|  | static void volatile_memcpy(volatile char *to, const volatile char *from,  | ||
|  | 			    unsigned long n) | ||
|  | { | ||
|  | 	while (n--) | ||
|  | 		*(to++) = *(from++); | ||
|  | } | ||
|  | 
 | ||
|  | static inline int copy_from_user(void *to, const void __user volatile *from, | ||
|  | 				 unsigned long n) | ||
|  | { | ||
|  | 	__chk_user_ptr(from, n); | ||
|  | 	volatile_memcpy(to, from, n); | ||
|  | 	return 0; | ||
|  | } | ||
|  | 
 | ||
|  | static inline int copy_to_user(void __user volatile *to, const void *from, | ||
|  | 			       unsigned long n) | ||
|  | { | ||
|  | 	__chk_user_ptr(to, n); | ||
|  | 	volatile_memcpy(to, from, n); | ||
|  | 	return 0; | ||
|  | } | ||
|  | #endif /* UACCESS_H */
 |