cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

uaccess.h (5639B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef __ASM_GENERIC_UACCESS_H
      3#define __ASM_GENERIC_UACCESS_H
      4
      5/*
      6 * User space memory access functions, these should work
      7 * on any machine that has kernel and user data in the same
      8 * address space, e.g. all NOMMU machines.
      9 */
     10#include <linux/string.h>
     11#include <asm-generic/access_ok.h>
     12
     13#ifdef CONFIG_UACCESS_MEMCPY
     14#include <asm/unaligned.h>
     15
     16static __always_inline int
     17__get_user_fn(size_t size, const void __user *from, void *to)
     18{
     19	BUILD_BUG_ON(!__builtin_constant_p(size));
     20
     21	switch (size) {
     22	case 1:
     23		*(u8 *)to = *((u8 __force *)from);
     24		return 0;
     25	case 2:
     26		*(u16 *)to = get_unaligned((u16 __force *)from);
     27		return 0;
     28	case 4:
     29		*(u32 *)to = get_unaligned((u32 __force *)from);
     30		return 0;
     31	case 8:
     32		*(u64 *)to = get_unaligned((u64 __force *)from);
     33		return 0;
     34	default:
     35		BUILD_BUG();
     36		return 0;
     37	}
     38
     39}
     40#define __get_user_fn(sz, u, k)	__get_user_fn(sz, u, k)
     41
     42static __always_inline int
     43__put_user_fn(size_t size, void __user *to, void *from)
     44{
     45	BUILD_BUG_ON(!__builtin_constant_p(size));
     46
     47	switch (size) {
     48	case 1:
     49		*(u8 __force *)to = *(u8 *)from;
     50		return 0;
     51	case 2:
     52		put_unaligned(*(u16 *)from, (u16 __force *)to);
     53		return 0;
     54	case 4:
     55		put_unaligned(*(u32 *)from, (u32 __force *)to);
     56		return 0;
     57	case 8:
     58		put_unaligned(*(u64 *)from, (u64 __force *)to);
     59		return 0;
     60	default:
     61		BUILD_BUG();
     62		return 0;
     63	}
     64}
     65#define __put_user_fn(sz, u, k)	__put_user_fn(sz, u, k)
     66
     67#define __get_kernel_nofault(dst, src, type, err_label)			\
     68do {									\
     69	*((type *)dst) = get_unaligned((type *)(src));			\
     70	if (0) /* make sure the label looks used to the compiler */	\
     71		goto err_label;						\
     72} while (0)
     73
     74#define __put_kernel_nofault(dst, src, type, err_label)			\
     75do {									\
     76	put_unaligned(*((type *)src), (type *)(dst));			\
     77	if (0) /* make sure the label looks used to the compiler */	\
     78		goto err_label;						\
     79} while (0)
     80
     81static inline __must_check unsigned long
     82raw_copy_from_user(void *to, const void __user * from, unsigned long n)
     83{
     84	memcpy(to, (const void __force *)from, n);
     85	return 0;
     86}
     87
     88static inline __must_check unsigned long
     89raw_copy_to_user(void __user *to, const void *from, unsigned long n)
     90{
     91	memcpy((void __force *)to, from, n);
     92	return 0;
     93}
     94#define INLINE_COPY_FROM_USER
     95#define INLINE_COPY_TO_USER
     96#endif /* CONFIG_UACCESS_MEMCPY */
     97
     98/*
     99 * These are the main single-value transfer routines.  They automatically
    100 * use the right size if we just have the right pointer type.
    101 * This version just falls back to copy_{from,to}_user, which should
    102 * provide a fast-path for small values.
    103 */
    104#define __put_user(x, ptr) \
    105({								\
    106	__typeof__(*(ptr)) __x = (x);				\
    107	int __pu_err = -EFAULT;					\
    108        __chk_user_ptr(ptr);                                    \
    109	switch (sizeof (*(ptr))) {				\
    110	case 1:							\
    111	case 2:							\
    112	case 4:							\
    113	case 8:							\
    114		__pu_err = __put_user_fn(sizeof (*(ptr)),	\
    115					 ptr, &__x);		\
    116		break;						\
    117	default:						\
    118		__put_user_bad();				\
    119		break;						\
    120	 }							\
    121	__pu_err;						\
    122})
    123
    124#define put_user(x, ptr)					\
    125({								\
    126	void __user *__p = (ptr);				\
    127	might_fault();						\
    128	access_ok(__p, sizeof(*ptr)) ?		\
    129		__put_user((x), ((__typeof__(*(ptr)) __user *)__p)) :	\
    130		-EFAULT;					\
    131})
    132
    133#ifndef __put_user_fn
    134
    135static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
    136{
    137	return unlikely(raw_copy_to_user(ptr, x, size)) ? -EFAULT : 0;
    138}
    139
    140#define __put_user_fn(sz, u, k)	__put_user_fn(sz, u, k)
    141
    142#endif
    143
    144extern int __put_user_bad(void) __attribute__((noreturn));
    145
    146#define __get_user(x, ptr)					\
    147({								\
    148	int __gu_err = -EFAULT;					\
    149	__chk_user_ptr(ptr);					\
    150	switch (sizeof(*(ptr))) {				\
    151	case 1: {						\
    152		unsigned char __x = 0;				\
    153		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
    154					 ptr, &__x);		\
    155		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
    156		break;						\
    157	};							\
    158	case 2: {						\
    159		unsigned short __x = 0;				\
    160		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
    161					 ptr, &__x);		\
    162		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
    163		break;						\
    164	};							\
    165	case 4: {						\
    166		unsigned int __x = 0;				\
    167		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
    168					 ptr, &__x);		\
    169		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
    170		break;						\
    171	};							\
    172	case 8: {						\
    173		unsigned long long __x = 0;			\
    174		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
    175					 ptr, &__x);		\
    176		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
    177		break;						\
    178	};							\
    179	default:						\
    180		__get_user_bad();				\
    181		break;						\
    182	}							\
    183	__gu_err;						\
    184})
    185
    186#define get_user(x, ptr)					\
    187({								\
    188	const void __user *__p = (ptr);				\
    189	might_fault();						\
    190	access_ok(__p, sizeof(*ptr)) ?		\
    191		__get_user((x), (__typeof__(*(ptr)) __user *)__p) :\
    192		((x) = (__typeof__(*(ptr)))0,-EFAULT);		\
    193})
    194
    195#ifndef __get_user_fn
    196static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
    197{
    198	return unlikely(raw_copy_from_user(x, ptr, size)) ? -EFAULT : 0;
    199}
    200
    201#define __get_user_fn(sz, u, k)	__get_user_fn(sz, u, k)
    202
    203#endif
    204
    205extern int __get_user_bad(void) __attribute__((noreturn));
    206
    207/*
    208 * Zero Userspace
    209 */
    210#ifndef __clear_user
    211static inline __must_check unsigned long
    212__clear_user(void __user *to, unsigned long n)
    213{
    214	memset((void __force *)to, 0, n);
    215	return 0;
    216}
    217#endif
    218
    219static inline __must_check unsigned long
    220clear_user(void __user *to, unsigned long n)
    221{
    222	might_fault();
    223	if (!access_ok(to, n))
    224		return n;
    225
    226	return __clear_user(to, n);
    227}
    228
    229#include <asm/extable.h>
    230
    231__must_check long strncpy_from_user(char *dst, const char __user *src,
    232				    long count);
    233__must_check long strnlen_user(const char __user *src, long n);
    234
    235#endif /* __ASM_GENERIC_UACCESS_H */