/* * This is the smallest unsigned integer type that can fit a value * (up to 'long long')
*/ #define __inttype(x) __typeof__( \
__typefits(x,char, \
__typefits(x,short, \
__typefits(x,int, \
__typefits(x,long,0ULL)))))
/* * This is used for both get_user() and __get_user() to expand to * the proper special function call that has odd calling conventions * due to returning both a value and an error, and that depends on * the size of the pointer passed in. * * Careful: we have to cast the result to the type of the pointer * for sign reasons. * * The use of _ASM_DX as the register specifier is a bit of a * simplification, as gcc only cares about it as the starting point * and not size: for a 64-bit value it will use %ecx:%edx on 32 bits * (%ecx being the next register in gcc's x86 register sequence), and * %rdx on 64 bits. * * Clang/LLVM cares about the size of the register, but still wants * the base register for something that ends up being a pair.
*/ #define do_get_user_call(fn,x,ptr) \
({ \ int __ret_gu; \ register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX); \
__chk_user_ptr(ptr); \ asmvolatile("call __"#fn"_%c[size]" \
: "=a" (__ret_gu), "=r" (__val_gu), \
ASM_CALL_CONSTRAINT \
: "0" (ptr), [size] "i" (sizeof(*(ptr)))); \
instrument_get_user(__val_gu); \
(x) = (__force __typeof__(*(ptr))) __val_gu; \
__builtin_expect(__ret_gu, 0); \
})
/** * get_user - Get a simple variable from user space. * @x: Variable to store result. * @ptr: Source address, in user space. * * Context: User context only. This function may sleep if pagefaults are * enabled. * * This macro copies a single simple variable from user space to kernel * space. It supports simple types like char and int, but not larger * data types like structures or arrays. * * @ptr must have pointer-to-simple-variable type, and the result of * dereferencing @ptr must be assignable to @x without a cast. * * Return: zero on success, or -EFAULT on error. * On error, the variable @x is set to zero.
*/ #define get_user(x,ptr) ({ might_fault(); do_get_user_call(get_user,x,ptr); })
/** * __get_user - Get a simple variable from user space, with less checking. * @x: Variable to store result. * @ptr: Source address, in user space. * * Context: User context only. This function may sleep if pagefaults are * enabled. * * This macro copies a single simple variable from user space to kernel * space. It supports simple types like char and int, but not larger * data types like structures or arrays. * * @ptr must have pointer-to-simple-variable type, and the result of * dereferencing @ptr must be assignable to @x without a cast. * * Caller must check the pointer with access_ok() before calling this * function. * * Return: zero on success, or -EFAULT on error. * On error, the variable @x is set to zero.
*/ #define __get_user(x,ptr) do_get_user_call(get_user_nocheck,x,ptr)
/* * Strange magic calling convention: pointer in %ecx, * value in %eax(:%edx), return value in %ecx. clobbers %rbx
*/ externvoid __put_user_1(void); externvoid __put_user_2(void); externvoid __put_user_4(void); externvoid __put_user_8(void); externvoid __put_user_nocheck_1(void); externvoid __put_user_nocheck_2(void); externvoid __put_user_nocheck_4(void); externvoid __put_user_nocheck_8(void);
/* * ptr must be evaluated and assigned to the temporary __ptr_pu before * the assignment of x to __val_pu, to avoid any function calls * involved in the ptr expression (possibly implicitly generated due * to KASAN) from clobbering %ax.
*/ #define do_put_user_call(fn,x,ptr) \
({ \ int __ret_pu; \ void __user *__ptr_pu; \ register __typeof__(*(ptr)) __val_pu asm("%"_ASM_AX); \
__typeof__(*(ptr)) __x = (x); /* eval x once */ \
__typeof__(ptr) __ptr = (ptr); /* eval ptr once */ \
__chk_user_ptr(__ptr); \
__ptr_pu = __ptr; \
__val_pu = __x; \ asmvolatile("call __"#fn"_%c[size]" \
: "=c" (__ret_pu), \
ASM_CALL_CONSTRAINT \
: "0" (__ptr_pu), \ "r" (__val_pu), \
[size] "i" (sizeof(*(ptr))) \
:"ebx"); \
instrument_put_user(__x, __ptr, sizeof(*(ptr))); \
__builtin_expect(__ret_pu, 0); \
})
/** * put_user - Write a simple value into user space. * @x: Value to copy to user space. * @ptr: Destination address, in user space. * * Context: User context only. This function may sleep if pagefaults are * enabled. * * This macro copies a single simple value from kernel space to user * space. It supports simple types like char and int, but not larger * data types like structures or arrays. * * @ptr must have pointer-to-simple-variable type, and @x must be assignable * to the result of dereferencing @ptr. * * Return: zero on success, or -EFAULT on error.
*/ #define put_user(x, ptr) ({ might_fault(); do_put_user_call(put_user,x,ptr); })
/** * __put_user - Write a simple value into user space, with less checking. * @x: Value to copy to user space. * @ptr: Destination address, in user space. * * Context: User context only. This function may sleep if pagefaults are * enabled. * * This macro copies a single simple value from kernel space to user * space. It supports simple types like char and int, but not larger * data types like structures or arrays. * * @ptr must have pointer-to-simple-variable type, and @x must be assignable * to the result of dereferencing @ptr. * * Caller must check the pointer with access_ok() before calling this * function. * * Return: zero on success, or -EFAULT on error.
*/ #define __put_user(x, ptr) do_put_user_call(put_user_nocheck,x,ptr)
#define __put_user_size(x, ptr, size, label) \ do { \
__typeof__(*(ptr)) __x = (x); /* eval x once */ \
__typeof__(ptr) __ptr = (ptr); /* eval ptr once */ \
__chk_user_ptr(__ptr); \ switch (size) { \ case 1: \
__put_user_goto(__x, __ptr, "b", "iq", label); \ break; \ case 2: \
__put_user_goto(__x, __ptr, "w", "ir", label); \ break; \ case 4: \
__put_user_goto(__x, __ptr, "l", "ir", label); \ break; \ case 8: \
__put_user_goto_u64(__x, __ptr, label); \ break; \ default: \
__put_user_bad(); \
} \
instrument_put_user(__x, __ptr, size); \
} while (0)
#ifdef CONFIG_X86_32 /* * Unlike the normal CMPXCHG, use output GPR for both success/fail and error. * There are only six GPRs available and four (EAX, EBX, ECX, and EDX) are * hardcoded by CMPXCHG8B, leaving only ESI and EDI. If the compiler uses * both ESI and EDI for the memory operand, compilation will fail if the error * is an input+output as there will be no register available for input.
*/ #define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label) ({ \ int __result; \
__typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \
__typeof__(*(_ptr)) __old = *_old; \
__typeof__(*(_ptr)) __new = (_new); \ asmvolatile("\n" \ "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n" \ "mov $0, %[result]\n\t" \ "setz %b[result]\n" \ "2:\n" \
_ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, \
%[result]) \
: [result] "=q" (__result), \ "+A" (__old), \
[ptr] "+m" (*_ptr) \
: "b" ((u32)__new), \ "c" ((u32)((u64)__new >> 32)) \
: "memory", "cc"); \ if (unlikely(__result < 0)) \ goto label; \ if (unlikely(!__result)) \
*_old = __old; \
likely(__result); }) #endif// CONFIG_X86_32 #endif// CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
/* * 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_goto(x, addr, itype, ltype, label) \ asmgoto("\n" \ "1: mov"itype" %0,%1\n" \
_ASM_EXTABLE_UA(1b, %l2) \
: : ltype(x), "m" (__m(addr)) \
: : label)
externunsignedlong
copy_from_user_nmi(void *to, constvoid __user *from, unsignedlong n); extern __must_check long
strncpy_from_user(char *dst, constchar __user *src, long count);
extern __must_check long strnlen_user(constchar __user *str, long n);
/* * movsl can be slow when source and dest are not both 8-byte aligned
*/ #ifdef CONFIG_X86_INTEL_USERCOPY externstruct movsl_mask { int mask;
} ____cacheline_aligned_in_smp movsl_mask; #endif
#define ARCH_HAS_NOCACHE_UACCESS 1
/* * The "unsafe" user accesses aren't really "unsafe", but the naming * is a big fat warning: you have to not only do the access_ok() * checking before using them, but you have to surround them with the * user_access_begin/end() pair.
*/ static __must_check __always_inline bool user_access_begin(constvoid __user *ptr, size_t len)
{ if (unlikely(!access_ok(ptr,len))) return 0;
__uaccess_begin_nospec(); return 1;
} #define user_access_begin(a,b) user_access_begin(a,b) #define user_access_end() __uaccess_end()
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.