Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef __ASM_GENERIC_UACCESS_H
0003 #define __ASM_GENERIC_UACCESS_H
0004 
0005 /*
0006  * User space memory access functions, these should work
0007  * on any machine that has kernel and user data in the same
0008  * address space, e.g. all NOMMU machines.
0009  */
0010 #include <linux/string.h>
0011 #include <asm-generic/access_ok.h>
0012 
0013 #ifdef CONFIG_UACCESS_MEMCPY
0014 #include <asm/unaligned.h>
0015 
0016 static __always_inline int
0017 __get_user_fn(size_t size, const void __user *from, void *to)
0018 {
0019     BUILD_BUG_ON(!__builtin_constant_p(size));
0020 
0021     switch (size) {
0022     case 1:
0023         *(u8 *)to = *((u8 __force *)from);
0024         return 0;
0025     case 2:
0026         *(u16 *)to = get_unaligned((u16 __force *)from);
0027         return 0;
0028     case 4:
0029         *(u32 *)to = get_unaligned((u32 __force *)from);
0030         return 0;
0031     case 8:
0032         *(u64 *)to = get_unaligned((u64 __force *)from);
0033         return 0;
0034     default:
0035         BUILD_BUG();
0036         return 0;
0037     }
0038 
0039 }
0040 #define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k)
0041 
0042 static __always_inline int
0043 __put_user_fn(size_t size, void __user *to, void *from)
0044 {
0045     BUILD_BUG_ON(!__builtin_constant_p(size));
0046 
0047     switch (size) {
0048     case 1:
0049         *(u8 __force *)to = *(u8 *)from;
0050         return 0;
0051     case 2:
0052         put_unaligned(*(u16 *)from, (u16 __force *)to);
0053         return 0;
0054     case 4:
0055         put_unaligned(*(u32 *)from, (u32 __force *)to);
0056         return 0;
0057     case 8:
0058         put_unaligned(*(u64 *)from, (u64 __force *)to);
0059         return 0;
0060     default:
0061         BUILD_BUG();
0062         return 0;
0063     }
0064 }
0065 #define __put_user_fn(sz, u, k) __put_user_fn(sz, u, k)
0066 
0067 #define __get_kernel_nofault(dst, src, type, err_label)         \
0068 do {                                    \
0069     *((type *)dst) = get_unaligned((type *)(src));          \
0070     if (0) /* make sure the label looks used to the compiler */ \
0071         goto err_label;                     \
0072 } while (0)
0073 
0074 #define __put_kernel_nofault(dst, src, type, err_label)         \
0075 do {                                    \
0076     put_unaligned(*((type *)src), (type *)(dst));           \
0077     if (0) /* make sure the label looks used to the compiler */ \
0078         goto err_label;                     \
0079 } while (0)
0080 
0081 static inline __must_check unsigned long
0082 raw_copy_from_user(void *to, const void __user * from, unsigned long n)
0083 {
0084     memcpy(to, (const void __force *)from, n);
0085     return 0;
0086 }
0087 
0088 static inline __must_check unsigned long
0089 raw_copy_to_user(void __user *to, const void *from, unsigned long n)
0090 {
0091     memcpy((void __force *)to, from, n);
0092     return 0;
0093 }
0094 #define INLINE_COPY_FROM_USER
0095 #define INLINE_COPY_TO_USER
0096 #endif /* CONFIG_UACCESS_MEMCPY */
0097 
0098 /*
0099  * These are the main single-value transfer routines.  They automatically
0100  * use the right size if we just have the right pointer type.
0101  * This version just falls back to copy_{from,to}_user, which should
0102  * provide a fast-path for small values.
0103  */
0104 #define __put_user(x, ptr) \
0105 ({                              \
0106     __typeof__(*(ptr)) __x = (x);               \
0107     int __pu_err = -EFAULT;                 \
0108         __chk_user_ptr(ptr);                                    \
0109     switch (sizeof (*(ptr))) {              \
0110     case 1:                         \
0111     case 2:                         \
0112     case 4:                         \
0113     case 8:                         \
0114         __pu_err = __put_user_fn(sizeof (*(ptr)),   \
0115                      ptr, &__x);        \
0116         break;                      \
0117     default:                        \
0118         __put_user_bad();               \
0119         break;                      \
0120      }                          \
0121     __pu_err;                       \
0122 })
0123 
0124 #define put_user(x, ptr)                    \
0125 ({                              \
0126     void __user *__p = (ptr);               \
0127     might_fault();                      \
0128     access_ok(__p, sizeof(*ptr)) ?      \
0129         __put_user((x), ((__typeof__(*(ptr)) __user *)__p)) :   \
0130         -EFAULT;                    \
0131 })
0132 
0133 #ifndef __put_user_fn
0134 
0135 static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
0136 {
0137     return unlikely(raw_copy_to_user(ptr, x, size)) ? -EFAULT : 0;
0138 }
0139 
0140 #define __put_user_fn(sz, u, k) __put_user_fn(sz, u, k)
0141 
0142 #endif
0143 
0144 extern int __put_user_bad(void) __attribute__((noreturn));
0145 
0146 #define __get_user(x, ptr)                  \
0147 ({                              \
0148     int __gu_err = -EFAULT;                 \
0149     __chk_user_ptr(ptr);                    \
0150     switch (sizeof(*(ptr))) {               \
0151     case 1: {                       \
0152         unsigned char __x = 0;              \
0153         __gu_err = __get_user_fn(sizeof (*(ptr)),   \
0154                      ptr, &__x);        \
0155         (x) = *(__force __typeof__(*(ptr)) *) &__x; \
0156         break;                      \
0157     };                          \
0158     case 2: {                       \
0159         unsigned short __x = 0;             \
0160         __gu_err = __get_user_fn(sizeof (*(ptr)),   \
0161                      ptr, &__x);        \
0162         (x) = *(__force __typeof__(*(ptr)) *) &__x; \
0163         break;                      \
0164     };                          \
0165     case 4: {                       \
0166         unsigned int __x = 0;               \
0167         __gu_err = __get_user_fn(sizeof (*(ptr)),   \
0168                      ptr, &__x);        \
0169         (x) = *(__force __typeof__(*(ptr)) *) &__x; \
0170         break;                      \
0171     };                          \
0172     case 8: {                       \
0173         unsigned long long __x = 0;         \
0174         __gu_err = __get_user_fn(sizeof (*(ptr)),   \
0175                      ptr, &__x);        \
0176         (x) = *(__force __typeof__(*(ptr)) *) &__x; \
0177         break;                      \
0178     };                          \
0179     default:                        \
0180         __get_user_bad();               \
0181         break;                      \
0182     }                           \
0183     __gu_err;                       \
0184 })
0185 
0186 #define get_user(x, ptr)                    \
0187 ({                              \
0188     const void __user *__p = (ptr);             \
0189     might_fault();                      \
0190     access_ok(__p, sizeof(*ptr)) ?      \
0191         __get_user((x), (__typeof__(*(ptr)) __user *)__p) :\
0192         ((x) = (__typeof__(*(ptr)))0,-EFAULT);      \
0193 })
0194 
0195 #ifndef __get_user_fn
0196 static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
0197 {
0198     return unlikely(raw_copy_from_user(x, ptr, size)) ? -EFAULT : 0;
0199 }
0200 
0201 #define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k)
0202 
0203 #endif
0204 
0205 extern int __get_user_bad(void) __attribute__((noreturn));
0206 
0207 /*
0208  * Zero Userspace
0209  */
0210 #ifndef __clear_user
0211 static inline __must_check unsigned long
0212 __clear_user(void __user *to, unsigned long n)
0213 {
0214     memset((void __force *)to, 0, n);
0215     return 0;
0216 }
0217 #endif
0218 
0219 static inline __must_check unsigned long
0220 clear_user(void __user *to, unsigned long n)
0221 {
0222     might_fault();
0223     if (!access_ok(to, n))
0224         return n;
0225 
0226     return __clear_user(to, n);
0227 }
0228 
0229 #include <asm/extable.h>
0230 
0231 __must_check long strncpy_from_user(char *dst, const char __user *src,
0232                     long count);
0233 __must_check long strnlen_user(const char __user *src, long n);
0234 
0235 #endif /* __ASM_GENERIC_UACCESS_H */