uaccess_32.h

来自「linux 内核源代码」· C头文件 代码 · 共 591 行 · 第 1/2 页

H
591
字号
#ifdef CONFIG_X86_WP_WORKS_OK#define __put_user_size(x,ptr,size,retval,errret)			\do {									\	retval = 0;							\	__chk_user_ptr(ptr);						\	switch (size) {							\	case 1: __put_user_asm(x,ptr,retval,"b","b","iq",errret);break;	\	case 2: __put_user_asm(x,ptr,retval,"w","w","ir",errret);break; \	case 4: __put_user_asm(x,ptr,retval,"l","","ir",errret); break;	\	case 8: __put_user_u64((__typeof__(*ptr))(x),ptr,retval); break;\	  default: __put_user_bad();					\	}								\} while (0)#else#define __put_user_size(x,ptr,size,retval,errret)			\do {									\	__typeof__(*(ptr)) __pus_tmp = x;				\	retval = 0;							\									\	if(unlikely(__copy_to_user_ll(ptr, &__pus_tmp, size) != 0))	\		retval = errret;					\} while (0)#endifstruct __large_struct { unsigned long buf[100]; };#define __m(x) (*(struct __large_struct __user *)(x))/* * Tell gcc we read from memory instead of writing: this is because * we do not write to any memory gcc knows about, so there are no * aliasing issues. */#define __put_user_asm(x, addr, err, itype, rtype, ltype, errret)	\	__asm__ __volatile__(						\		"1:	mov"itype" %"rtype"1,%2\n"			\		"2:\n"							\		".section .fixup,\"ax\"\n"				\		"3:	movl %3,%0\n"					\		"	jmp 2b\n"					\		".previous\n"						\		".section __ex_table,\"a\"\n"				\		"	.align 4\n"					\		"	.long 1b,3b\n"					\		".previous"						\		: "=r"(err)						\		: ltype (x), "m"(__m(addr)), "i"(errret), "0"(err))#define __get_user_nocheck(x,ptr,size)				\({								\	long __gu_err;						\	unsigned long __gu_val;					\	__get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\	(x) = (__typeof__(*(ptr)))__gu_val;			\	__gu_err;						\})extern long __get_user_bad(void);#define __get_user_size(x,ptr,size,retval,errret)			\do {									\	retval = 0;							\	__chk_user_ptr(ptr);						\	switch (size) {							\	case 1: __get_user_asm(x,ptr,retval,"b","b","=q",errret);break;	\	case 2: __get_user_asm(x,ptr,retval,"w","w","=r",errret);break;	\	case 4: __get_user_asm(x,ptr,retval,"l","","=r",errret);break;	\	default: (x) = __get_user_bad();				\	}								\} while (0)#define __get_user_asm(x, addr, err, itype, rtype, ltype, errret)	\	__asm__ __volatile__(						\		"1:	mov"itype" %2,%"rtype"1\n"			\		"2:\n"							\		".section .fixup,\"ax\"\n"				\		"3:	movl %3,%0\n"					\		"	xor"itype" %"rtype"1,%"rtype"1\n"		\		"	jmp 2b\n"					\		".previous\n"						\		".section __ex_table,\"a\"\n"				\		"	.align 4\n"					\		"	.long 1b,3b\n"					\		".previous"						\		: "=r"(err), ltype (x)					\		: "m"(__m(addr)), "i"(errret), "0"(err))unsigned long __must_check __copy_to_user_ll(void __user *to,				const void *from, unsigned long n);unsigned long __must_check __copy_from_user_ll(void *to,				const void __user *from, unsigned long n);unsigned long __must_check __copy_from_user_ll_nozero(void *to,				const void __user *from, unsigned long n);unsigned long __must_check __copy_from_user_ll_nocache(void *to,				const void __user *from, unsigned long n);unsigned long __must_check __copy_from_user_ll_nocache_nozero(void *to,				const void __user *from, unsigned long n);/** * __copy_to_user_inatomic: - Copy a block of data into user space, with less checking. * @to:   Destination address, in user space. * @from: Source address, in kernel space. * @n:    Number of bytes to copy. * * Context: User context only. * * Copy data from kernel space to user space.  Caller must check * the specified block with access_ok() before calling this function. * The caller should also make sure he pins the user space address * so that the we don't result in page fault and sleep. * * Here we special-case 1, 2 and 4-byte copy_*_user invocations.  On a fault * we return the initial request size (1, 2 or 4), as copy_*_user should do. * If a store crosses a page boundary and gets a fault, the x86 will not write * anything, so this is accurate. */static __always_inline unsigned long __must_check__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n){	if (__builtin_constant_p(n)) {		unsigned long ret;		switch (n) {		case 1:			__put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret, 1);			return ret;		case 2:			__put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret, 2);			return ret;		case 4:			__put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret, 4);			return ret;		}	}	return __copy_to_user_ll(to, from, n);}/** * __copy_to_user: - Copy a block of data into user space, with less checking. * @to:   Destination address, in user space. * @from: Source address, in kernel space. * @n:    Number of bytes to copy. * * Context: User context only.  This function may sleep. * * Copy data from kernel space to user space.  Caller must check * the specified block with access_ok() before calling this function. * * Returns number of bytes that could not be copied. * On success, this will be zero. */static __always_inline unsigned long __must_check__copy_to_user(void __user *to, const void *from, unsigned long n){       might_sleep();       return __copy_to_user_inatomic(to, from, n);}static __always_inline unsigned long__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n){	/* Avoid zeroing the tail if the copy fails..	 * If 'n' is constant and 1, 2, or 4, we do still zero on a failure,	 * but as the zeroing behaviour is only significant when n is not	 * constant, that shouldn't be a problem.	 */	if (__builtin_constant_p(n)) {		unsigned long ret;		switch (n) {		case 1:			__get_user_size(*(u8 *)to, from, 1, ret, 1);			return ret;		case 2:			__get_user_size(*(u16 *)to, from, 2, ret, 2);			return ret;		case 4:			__get_user_size(*(u32 *)to, from, 4, ret, 4);			return ret;		}	}	return __copy_from_user_ll_nozero(to, from, n);}/** * __copy_from_user: - Copy a block of data from user space, with less checking. * @to:   Destination address, in kernel space. * @from: Source address, in user space. * @n:    Number of bytes to copy. * * Context: User context only.  This function may sleep. * * Copy data from user space to kernel space.  Caller must check * the specified block with access_ok() before calling this function. * * Returns number of bytes that could not be copied. * On success, this will be zero. * * If some data could not be copied, this function will pad the copied * data to the requested size using zero bytes. * * An alternate version - __copy_from_user_inatomic() - may be called from * atomic context and will fail rather than sleep.  In this case the * uncopied bytes will *NOT* be padded with zeros.  See fs/filemap.h * for explanation of why this is needed. */static __always_inline unsigned long__copy_from_user(void *to, const void __user *from, unsigned long n){	might_sleep();	if (__builtin_constant_p(n)) {		unsigned long ret;		switch (n) {		case 1:			__get_user_size(*(u8 *)to, from, 1, ret, 1);			return ret;		case 2:			__get_user_size(*(u16 *)to, from, 2, ret, 2);			return ret;		case 4:			__get_user_size(*(u32 *)to, from, 4, ret, 4);			return ret;		}	}	return __copy_from_user_ll(to, from, n);}#define ARCH_HAS_NOCACHE_UACCESSstatic __always_inline unsigned long __copy_from_user_nocache(void *to,				const void __user *from, unsigned long n){	might_sleep();	if (__builtin_constant_p(n)) {		unsigned long ret;		switch (n) {		case 1:			__get_user_size(*(u8 *)to, from, 1, ret, 1);			return ret;		case 2:			__get_user_size(*(u16 *)to, from, 2, ret, 2);			return ret;		case 4:			__get_user_size(*(u32 *)to, from, 4, ret, 4);			return ret;		}	}	return __copy_from_user_ll_nocache(to, from, n);}static __always_inline unsigned long__copy_from_user_inatomic_nocache(void *to, const void __user *from, unsigned long n){       return __copy_from_user_ll_nocache_nozero(to, from, n);}unsigned long __must_check copy_to_user(void __user *to,				const void *from, unsigned long n);unsigned long __must_check copy_from_user(void *to,				const void __user *from, unsigned long n);long __must_check strncpy_from_user(char *dst, const char __user *src,				long count);long __must_check __strncpy_from_user(char *dst,				const char __user *src, long count);/** * strlen_user: - Get the size of a string in user space. * @str: The string to measure. * * Context: User context only.  This function may sleep. * * Get the size of a NUL-terminated string in user space. * * Returns the size of the string INCLUDING the terminating NUL. * On exception, returns 0. * * If there is a limit on the length of a valid string, you may wish to * consider using strnlen_user() instead. */#define strlen_user(str) strnlen_user(str, LONG_MAX)long strnlen_user(const char __user *str, long n);unsigned long __must_check clear_user(void __user *mem, unsigned long len);unsigned long __must_check __clear_user(void __user *mem, unsigned long len);#endif /* __i386_UACCESS_H */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?