linux/include/asm-generic/uaccess.h
<<
>>
Prefs
   1#ifndef __ASM_GENERIC_UACCESS_H
   2#define __ASM_GENERIC_UACCESS_H
   3
   4/*
   5 * User space memory access functions, these should work
   6 * on a ny machine that has kernel and user data in the same
   7 * address space, e.g. all NOMMU machines.
   8 */
   9#include <linux/sched.h>
  10#include <linux/mm.h>
  11#include <linux/string.h>
  12
  13#include <asm/segment.h>
  14
  15#define MAKE_MM_SEG(s)  ((mm_segment_t) { (s) })
  16
  17#ifndef KERNEL_DS
  18#define KERNEL_DS       MAKE_MM_SEG(~0UL)
  19#endif
  20
  21#ifndef USER_DS
  22#define USER_DS         MAKE_MM_SEG(TASK_SIZE - 1)
  23#endif
  24
  25#ifndef get_fs
  26#define get_ds()        (KERNEL_DS)
  27#define get_fs()        (current_thread_info()->addr_limit)
  28
  29static inline void set_fs(mm_segment_t fs)
  30{
  31        current_thread_info()->addr_limit = fs;
  32}
  33#endif
  34
  35#define segment_eq(a, b) ((a).seg == (b).seg)
  36
  37#define VERIFY_READ     0
  38#define VERIFY_WRITE    1
  39
  40#define access_ok(type, addr, size) __access_ok((unsigned long)(addr),(size))
  41
  42/*
  43 * The architecture should really override this if possible, at least
  44 * doing a check on the get_fs()
  45 */
  46#ifndef __access_ok
  47static inline int __access_ok(unsigned long addr, unsigned long size)
  48{
  49        return 1;
  50}
  51#endif
  52
  53/*
  54 * The exception table consists of pairs of addresses: the first is the
  55 * address of an instruction that is allowed to fault, and the second is
  56 * the address at which the program should continue.  No registers are
  57 * modified, so it is entirely up to the continuation code to figure out
  58 * what to do.
  59 *
  60 * All the routines below use bits of fixup code that are out of line
  61 * with the main instruction path.  This means when everything is well,
  62 * we don't even have to jump over them.  Further, they do not intrude
  63 * on our cache or tlb entries.
  64 */
  65
  66struct exception_table_entry
  67{
  68        unsigned long insn, fixup;
  69};
  70
  71/* Returns 0 if exception not found and fixup otherwise.  */
  72extern unsigned long search_exception_table(unsigned long);
  73
  74/*
  75 * architectures with an MMU should override these two
  76 */
  77#ifndef __copy_from_user
  78static inline __must_check long __copy_from_user(void *to,
  79                const void __user * from, unsigned long n)
  80{
  81        if (__builtin_constant_p(n)) {
  82                switch(n) {
  83                case 1:
  84                        *(u8 *)to = *(u8 __force *)from;
  85                        return 0;
  86                case 2:
  87                        *(u16 *)to = *(u16 __force *)from;
  88                        return 0;
  89                case 4:
  90                        *(u32 *)to = *(u32 __force *)from;
  91                        return 0;
  92#ifdef CONFIG_64BIT
  93                case 8:
  94                        *(u64 *)to = *(u64 __force *)from;
  95                        return 0;
  96#endif
  97                default:
  98                        break;
  99                }
 100        }
 101
 102        memcpy(to, (const void __force *)from, n);
 103        return 0;
 104}
 105#endif
 106
 107#ifndef __copy_to_user
 108static inline __must_check long __copy_to_user(void __user *to,
 109                const void *from, unsigned long n)
 110{
 111        if (__builtin_constant_p(n)) {
 112                switch(n) {
 113                case 1:
 114                        *(u8 __force *)to = *(u8 *)from;
 115                        return 0;
 116                case 2:
 117                        *(u16 __force *)to = *(u16 *)from;
 118                        return 0;
 119                case 4:
 120                        *(u32 __force *)to = *(u32 *)from;
 121                        return 0;
 122#ifdef CONFIG_64BIT
 123                case 8:
 124                        *(u64 __force *)to = *(u64 *)from;
 125                        return 0;
 126#endif
 127                default:
 128                        break;
 129                }
 130        }
 131
 132        memcpy((void __force *)to, from, n);
 133        return 0;
 134}
 135#endif
 136
 137/*
 138 * These are the main single-value transfer routines.  They automatically
 139 * use the right size if we just have the right pointer type.
 140 * This version just falls back to copy_{from,to}_user, which should
 141 * provide a fast-path for small values.
 142 */
 143#define __put_user(x, ptr) \
 144({                                                              \
 145        __typeof__(*(ptr)) __x = (x);                           \
 146        int __pu_err = -EFAULT;                                 \
 147        __chk_user_ptr(ptr);                                    \
 148        switch (sizeof (*(ptr))) {                              \
 149        case 1:                                                 \
 150        case 2:                                                 \
 151        case 4:                                                 \
 152        case 8:                                                 \
 153                __pu_err = __put_user_fn(sizeof (*(ptr)),       \
 154                                         ptr, &__x);            \
 155                break;                                          \
 156        default:                                                \
 157                __put_user_bad();                               \
 158                break;                                          \
 159         }                                                      \
 160        __pu_err;                                               \
 161})
 162
 163#define put_user(x, ptr)                                        \
 164({                                                              \
 165        might_sleep();                                          \
 166        access_ok(VERIFY_WRITE, ptr, sizeof(*ptr)) ?            \
 167                __put_user(x, ptr) :                            \
 168                -EFAULT;                                        \
 169})
 170
 171static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
 172{
 173        size = __copy_to_user(ptr, x, size);
 174        return size ? -EFAULT : size;
 175}
 176
 177extern int __put_user_bad(void) __attribute__((noreturn));
 178
 179#define __get_user(x, ptr)                                      \
 180({                                                              \
 181        int __gu_err = -EFAULT;                                 \
 182        __chk_user_ptr(ptr);                                    \
 183        switch (sizeof(*(ptr))) {                               \
 184        case 1: {                                               \
 185                unsigned char __x;                              \
 186                __gu_err = __get_user_fn(sizeof (*(ptr)),       \
 187                                         ptr, &__x);            \
 188                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 189                break;                                          \
 190        };                                                      \
 191        case 2: {                                               \
 192                unsigned short __x;                             \
 193                __gu_err = __get_user_fn(sizeof (*(ptr)),       \
 194                                         ptr, &__x);            \
 195                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 196                break;                                          \
 197        };                                                      \
 198        case 4: {                                               \
 199                unsigned int __x;                               \
 200                __gu_err = __get_user_fn(sizeof (*(ptr)),       \
 201                                         ptr, &__x);            \
 202                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 203                break;                                          \
 204        };                                                      \
 205        case 8: {                                               \
 206                unsigned long long __x;                         \
 207                __gu_err = __get_user_fn(sizeof (*(ptr)),       \
 208                                         ptr, &__x);            \
 209                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 210                break;                                          \
 211        };                                                      \
 212        default:                                                \
 213                __get_user_bad();                               \
 214                break;                                          \
 215        }                                                       \
 216        __gu_err;                                               \
 217})
 218
 219#define get_user(x, ptr)                                        \
 220({                                                              \
 221        might_sleep();                                          \
 222        access_ok(VERIFY_READ, ptr, sizeof(*ptr)) ?             \
 223                __get_user(x, ptr) :                            \
 224                -EFAULT;                                        \
 225})
 226
 227static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
 228{
 229        size = __copy_from_user(x, ptr, size);
 230        return size ? -EFAULT : size;
 231}
 232
 233extern int __get_user_bad(void) __attribute__((noreturn));
 234
 235#ifndef __copy_from_user_inatomic
 236#define __copy_from_user_inatomic __copy_from_user
 237#endif
 238
 239#ifndef __copy_to_user_inatomic
 240#define __copy_to_user_inatomic __copy_to_user
 241#endif
 242
 243static inline long copy_from_user(void *to,
 244                const void __user * from, unsigned long n)
 245{
 246        might_sleep();
 247        if (access_ok(VERIFY_READ, from, n))
 248                return __copy_from_user(to, from, n);
 249        else
 250                return n;
 251}
 252
 253static inline long copy_to_user(void __user *to,
 254                const void *from, unsigned long n)
 255{
 256        might_sleep();
 257        if (access_ok(VERIFY_WRITE, to, n))
 258                return __copy_to_user(to, from, n);
 259        else
 260                return n;
 261}
 262
 263/*
 264 * Copy a null terminated string from userspace.
 265 */
 266#ifndef __strncpy_from_user
 267static inline long
 268__strncpy_from_user(char *dst, const char __user *src, long count)
 269{
 270        char *tmp;
 271        strncpy(dst, (const char __force *)src, count);
 272        for (tmp = dst; *tmp && count > 0; tmp++, count--)
 273                ;
 274        return (tmp - dst);
 275}
 276#endif
 277
 278static inline long
 279strncpy_from_user(char *dst, const char __user *src, long count)
 280{
 281        if (!access_ok(VERIFY_READ, src, 1))
 282                return -EFAULT;
 283        return __strncpy_from_user(dst, src, count);
 284}
 285
 286/*
 287 * Return the size of a string (including the ending 0)
 288 *
 289 * Return 0 on exception, a value greater than N if too long
 290 */
 291#ifndef strnlen_user
 292static inline long strnlen_user(const char __user *src, long n)
 293{
 294        if (!access_ok(VERIFY_READ, src, 1))
 295                return 0;
 296        return strlen((void * __force)src) + 1;
 297}
 298#endif
 299
 300static inline long strlen_user(const char __user *src)
 301{
 302        return strnlen_user(src, 32767);
 303}
 304
 305/*
 306 * Zero Userspace
 307 */
 308#ifndef __clear_user
 309static inline __must_check unsigned long
 310__clear_user(void __user *to, unsigned long n)
 311{
 312        memset((void __force *)to, 0, n);
 313        return 0;
 314}
 315#endif
 316
 317static inline __must_check unsigned long
 318clear_user(void __user *to, unsigned long n)
 319{
 320        might_sleep();
 321        if (!access_ok(VERIFY_WRITE, to, n))
 322                return n;
 323
 324        return __clear_user(to, n);
 325}
 326
 327#endif /* __ASM_GENERIC_UACCESS_H */
 328