linux/include/asm-generic/uaccess.h
<<
>>
Prefs
   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
  12#include <asm/segment.h>
  13
  14#define MAKE_MM_SEG(s)  ((mm_segment_t) { (s) })
  15
  16#ifndef KERNEL_DS
  17#define KERNEL_DS       MAKE_MM_SEG(~0UL)
  18#endif
  19
  20#ifndef USER_DS
  21#define USER_DS         MAKE_MM_SEG(TASK_SIZE - 1)
  22#endif
  23
  24#ifndef get_fs
  25#define get_ds()        (KERNEL_DS)
  26#define get_fs()        (current_thread_info()->addr_limit)
  27
  28static inline void set_fs(mm_segment_t fs)
  29{
  30        current_thread_info()->addr_limit = fs;
  31}
  32#endif
  33
  34#ifndef segment_eq
  35#define segment_eq(a, b) ((a).seg == (b).seg)
  36#endif
  37
  38#define access_ok(type, addr, size) __access_ok((unsigned long)(addr),(size))
  39
  40/*
  41 * The architecture should really override this if possible, at least
  42 * doing a check on the get_fs()
  43 */
  44#ifndef __access_ok
  45static inline int __access_ok(unsigned long addr, unsigned long size)
  46{
  47        return 1;
  48}
  49#endif
  50
  51/*
  52 * These are the main single-value transfer routines.  They automatically
  53 * use the right size if we just have the right pointer type.
  54 * This version just falls back to copy_{from,to}_user, which should
  55 * provide a fast-path for small values.
  56 */
  57#define __put_user(x, ptr) \
  58({                                                              \
  59        __typeof__(*(ptr)) __x = (x);                           \
  60        int __pu_err = -EFAULT;                                 \
  61        __chk_user_ptr(ptr);                                    \
  62        switch (sizeof (*(ptr))) {                              \
  63        case 1:                                                 \
  64        case 2:                                                 \
  65        case 4:                                                 \
  66        case 8:                                                 \
  67                __pu_err = __put_user_fn(sizeof (*(ptr)),       \
  68                                         ptr, &__x);            \
  69                break;                                          \
  70        default:                                                \
  71                __put_user_bad();                               \
  72                break;                                          \
  73         }                                                      \
  74        __pu_err;                                               \
  75})
  76
  77#define put_user(x, ptr)                                        \
  78({                                                              \
  79        void __user *__p = (ptr);                               \
  80        might_fault();                                          \
  81        access_ok(VERIFY_WRITE, __p, sizeof(*ptr)) ?            \
  82                __put_user((x), ((__typeof__(*(ptr)) __user *)__p)) :   \
  83                -EFAULT;                                        \
  84})
  85
  86#ifndef __put_user_fn
  87
  88static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
  89{
  90        return unlikely(raw_copy_to_user(ptr, x, size)) ? -EFAULT : 0;
  91}
  92
  93#define __put_user_fn(sz, u, k) __put_user_fn(sz, u, k)
  94
  95#endif
  96
  97extern int __put_user_bad(void) __attribute__((noreturn));
  98
  99#define __get_user(x, ptr)                                      \
 100({                                                              \
 101        int __gu_err = -EFAULT;                                 \
 102        __chk_user_ptr(ptr);                                    \
 103        switch (sizeof(*(ptr))) {                               \
 104        case 1: {                                               \
 105                unsigned char __x = 0;                          \
 106                __gu_err = __get_user_fn(sizeof (*(ptr)),       \
 107                                         ptr, &__x);            \
 108                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 109                break;                                          \
 110        };                                                      \
 111        case 2: {                                               \
 112                unsigned short __x = 0;                         \
 113                __gu_err = __get_user_fn(sizeof (*(ptr)),       \
 114                                         ptr, &__x);            \
 115                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 116                break;                                          \
 117        };                                                      \
 118        case 4: {                                               \
 119                unsigned int __x = 0;                           \
 120                __gu_err = __get_user_fn(sizeof (*(ptr)),       \
 121                                         ptr, &__x);            \
 122                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 123                break;                                          \
 124        };                                                      \
 125        case 8: {                                               \
 126                unsigned long long __x = 0;                     \
 127                __gu_err = __get_user_fn(sizeof (*(ptr)),       \
 128                                         ptr, &__x);            \
 129                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 130                break;                                          \
 131        };                                                      \
 132        default:                                                \
 133                __get_user_bad();                               \
 134                break;                                          \
 135        }                                                       \
 136        __gu_err;                                               \
 137})
 138
 139#define get_user(x, ptr)                                        \
 140({                                                              \
 141        const void __user *__p = (ptr);                         \
 142        might_fault();                                          \
 143        access_ok(VERIFY_READ, __p, sizeof(*ptr)) ?             \
 144                __get_user((x), (__typeof__(*(ptr)) __user *)__p) :\
 145                ((x) = (__typeof__(*(ptr)))0,-EFAULT);          \
 146})
 147
 148#ifndef __get_user_fn
 149static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
 150{
 151        return unlikely(raw_copy_from_user(x, ptr, size)) ? -EFAULT : 0;
 152}
 153
 154#define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k)
 155
 156#endif
 157
 158extern int __get_user_bad(void) __attribute__((noreturn));
 159
 160/*
 161 * Copy a null terminated string from userspace.
 162 */
 163#ifndef __strncpy_from_user
 164static inline long
 165__strncpy_from_user(char *dst, const char __user *src, long count)
 166{
 167        char *tmp;
 168        strncpy(dst, (const char __force *)src, count);
 169        for (tmp = dst; *tmp && count > 0; tmp++, count--)
 170                ;
 171        return (tmp - dst);
 172}
 173#endif
 174
 175static inline long
 176strncpy_from_user(char *dst, const char __user *src, long count)
 177{
 178        if (!access_ok(VERIFY_READ, src, 1))
 179                return -EFAULT;
 180        return __strncpy_from_user(dst, src, count);
 181}
 182
 183/*
 184 * Return the size of a string (including the ending 0)
 185 *
 186 * Return 0 on exception, a value greater than N if too long
 187 */
 188#ifndef __strnlen_user
 189#define __strnlen_user(s, n) (strnlen((s), (n)) + 1)
 190#endif
 191
 192/*
 193 * Unlike strnlen, strnlen_user includes the nul terminator in
 194 * its returned count. Callers should check for a returned value
 195 * greater than N as an indication the string is too long.
 196 */
 197static inline long strnlen_user(const char __user *src, long n)
 198{
 199        if (!access_ok(VERIFY_READ, src, 1))
 200                return 0;
 201        return __strnlen_user(src, n);
 202}
 203
 204/*
 205 * Zero Userspace
 206 */
 207#ifndef __clear_user
 208static inline __must_check unsigned long
 209__clear_user(void __user *to, unsigned long n)
 210{
 211        memset((void __force *)to, 0, n);
 212        return 0;
 213}
 214#endif
 215
 216static inline __must_check unsigned long
 217clear_user(void __user *to, unsigned long n)
 218{
 219        might_fault();
 220        if (!access_ok(VERIFY_WRITE, to, n))
 221                return n;
 222
 223        return __clear_user(to, n);
 224}
 225
 226#include <asm/extable.h>
 227
 228#endif /* __ASM_GENERIC_UACCESS_H */
 229