linux/include/asm-arm/uaccess.h
<<
>>
Prefs
   1/*
   2 *  linux/include/asm-arm/uaccess.h
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 */
   8#ifndef _ASMARM_UACCESS_H
   9#define _ASMARM_UACCESS_H
  10
  11/*
  12 * User space memory access functions
  13 */
  14#include <linux/sched.h>
  15#include <asm/errno.h>
  16#include <asm/memory.h>
  17#include <asm/domain.h>
  18#include <asm/system.h>
  19
  20#define VERIFY_READ 0
  21#define VERIFY_WRITE 1
  22
  23/*
  24 * The exception table consists of pairs of addresses: the first is the
  25 * address of an instruction that is allowed to fault, and the second is
  26 * the address at which the program should continue.  No registers are
  27 * modified, so it is entirely up to the continuation code to figure out
  28 * what to do.
  29 *
  30 * All the routines below use bits of fixup code that are out of line
  31 * with the main instruction path.  This means when everything is well,
  32 * we don't even have to jump over them.  Further, they do not intrude
  33 * on our cache or tlb entries.
  34 */
  35
  36struct exception_table_entry
  37{
  38        unsigned long insn, fixup;
  39};
  40
  41extern int fixup_exception(struct pt_regs *regs);
  42
  43/*
  44 * These two are intentionally not defined anywhere - if the kernel
  45 * code generates any references to them, that's a bug.
  46 */
  47extern int __get_user_bad(void);
  48extern int __put_user_bad(void);
  49
  50/*
  51 * Note that this is actually 0x1,0000,0000
  52 */
  53#define KERNEL_DS       0x00000000
  54#define get_ds()        (KERNEL_DS)
  55
  56#ifdef CONFIG_MMU
  57
  58#define USER_DS         TASK_SIZE
  59#define get_fs()        (current_thread_info()->addr_limit)
  60
  61static inline void set_fs(mm_segment_t fs)
  62{
  63        current_thread_info()->addr_limit = fs;
  64        modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
  65}
  66
  67#define segment_eq(a,b) ((a) == (b))
  68
  69#define __addr_ok(addr) ({ \
  70        unsigned long flag; \
  71        __asm__("cmp %2, %0; movlo %0, #0" \
  72                : "=&r" (flag) \
  73                : "0" (current_thread_info()->addr_limit), "r" (addr) \
  74                : "cc"); \
  75        (flag == 0); })
  76
  77/* We use 33-bit arithmetic here... */
  78#define __range_ok(addr,size) ({ \
  79        unsigned long flag, roksum; \
  80        __chk_user_ptr(addr);   \
  81        __asm__("adds %1, %2, %3; sbcccs %1, %1, %0; movcc %0, #0" \
  82                : "=&r" (flag), "=&r" (roksum) \
  83                : "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_limit) \
  84                : "cc"); \
  85        flag; })
  86
  87/*
  88 * Single-value transfer routines.  They automatically use the right
  89 * size if we just have the right pointer type.  Note that the functions
  90 * which read from user space (*get_*) need to take care not to leak
  91 * kernel data even if the calling code is buggy and fails to check
  92 * the return value.  This means zeroing out the destination variable
  93 * or buffer on error.  Normally this is done out of line by the
  94 * fixup code, but there are a few places where it intrudes on the
  95 * main code path.  When we only write to user space, there is no
  96 * problem.
  97 */
  98extern int __get_user_1(void *);
  99extern int __get_user_2(void *);
 100extern int __get_user_4(void *);
 101
 102#define __get_user_x(__r2,__p,__e,__s,__i...)                           \
 103           __asm__ __volatile__ (                                       \
 104                __asmeq("%0", "r0") __asmeq("%1", "r2")                 \
 105                "bl     __get_user_" #__s                               \
 106                : "=&r" (__e), "=r" (__r2)                              \
 107                : "0" (__p)                                             \
 108                : __i, "cc")
 109
 110#define get_user(x,p)                                                   \
 111        ({                                                              \
 112                register const typeof(*(p)) __user *__p asm("r0") = (p);\
 113                register unsigned long __r2 asm("r2");                  \
 114                register int __e asm("r0");                             \
 115                switch (sizeof(*(__p))) {                               \
 116                case 1:                                                 \
 117                        __get_user_x(__r2, __p, __e, 1, "lr");          \
 118                        break;                                          \
 119                case 2:                                                 \
 120                        __get_user_x(__r2, __p, __e, 2, "r3", "lr");    \
 121                        break;                                          \
 122                case 4:                                                 \
 123                        __get_user_x(__r2, __p, __e, 4, "lr");          \
 124                        break;                                          \
 125                default: __e = __get_user_bad(); break;                 \
 126                }                                                       \
 127                x = (typeof(*(p))) __r2;                                \
 128                __e;                                                    \
 129        })
 130
 131extern int __put_user_1(void *, unsigned int);
 132extern int __put_user_2(void *, unsigned int);
 133extern int __put_user_4(void *, unsigned int);
 134extern int __put_user_8(void *, unsigned long long);
 135
 136#define __put_user_x(__r2,__p,__e,__s)                                  \
 137           __asm__ __volatile__ (                                       \
 138                __asmeq("%0", "r0") __asmeq("%2", "r2")                 \
 139                "bl     __put_user_" #__s                               \
 140                : "=&r" (__e)                                           \
 141                : "0" (__p), "r" (__r2)                                 \
 142                : "ip", "lr", "cc")
 143
 144#define put_user(x,p)                                                   \
 145        ({                                                              \
 146                register const typeof(*(p)) __r2 asm("r2") = (x);       \
 147                register const typeof(*(p)) __user *__p asm("r0") = (p);\
 148                register int __e asm("r0");                             \
 149                switch (sizeof(*(__p))) {                               \
 150                case 1:                                                 \
 151                        __put_user_x(__r2, __p, __e, 1);                \
 152                        break;                                          \
 153                case 2:                                                 \
 154                        __put_user_x(__r2, __p, __e, 2);                \
 155                        break;                                          \
 156                case 4:                                                 \
 157                        __put_user_x(__r2, __p, __e, 4);                \
 158                        break;                                          \
 159                case 8:                                                 \
 160                        __put_user_x(__r2, __p, __e, 8);                \
 161                        break;                                          \
 162                default: __e = __put_user_bad(); break;                 \
 163                }                                                       \
 164                __e;                                                    \
 165        })
 166
 167#else /* CONFIG_MMU */
 168
 169/*
 170 * uClinux has only one addr space, so has simplified address limits.
 171 */
 172#define USER_DS                 KERNEL_DS
 173
 174#define segment_eq(a,b)         (1)
 175#define __addr_ok(addr)         (1)
 176#define __range_ok(addr,size)   (0)
 177#define get_fs()                (KERNEL_DS)
 178
 179static inline void set_fs(mm_segment_t fs)
 180{
 181}
 182
 183#define get_user(x,p)   __get_user(x,p)
 184#define put_user(x,p)   __put_user(x,p)
 185
 186#endif /* CONFIG_MMU */
 187
 188#define access_ok(type,addr,size)       (__range_ok(addr,size) == 0)
 189
 190/*
 191 * The "__xxx" versions of the user access functions do not verify the
 192 * address space - it must have been done previously with a separate
 193 * "access_ok()" call.
 194 *
 195 * The "xxx_error" versions set the third argument to EFAULT if an
 196 * error occurs, and leave it unchanged on success.  Note that these
 197 * versions are void (ie, don't return a value as such).
 198 */
 199#define __get_user(x,ptr)                                               \
 200({                                                                      \
 201        long __gu_err = 0;                                              \
 202        __get_user_err((x),(ptr),__gu_err);                             \
 203        __gu_err;                                                       \
 204})
 205
 206#define __get_user_error(x,ptr,err)                                     \
 207({                                                                      \
 208        __get_user_err((x),(ptr),err);                                  \
 209        (void) 0;                                                       \
 210})
 211
 212#define __get_user_err(x,ptr,err)                                       \
 213do {                                                                    \
 214        unsigned long __gu_addr = (unsigned long)(ptr);                 \
 215        unsigned long __gu_val;                                         \
 216        __chk_user_ptr(ptr);                                            \
 217        switch (sizeof(*(ptr))) {                                       \
 218        case 1: __get_user_asm_byte(__gu_val,__gu_addr,err);    break;  \
 219        case 2: __get_user_asm_half(__gu_val,__gu_addr,err);    break;  \
 220        case 4: __get_user_asm_word(__gu_val,__gu_addr,err);    break;  \
 221        default: (__gu_val) = __get_user_bad();                         \
 222        }                                                               \
 223        (x) = (__typeof__(*(ptr)))__gu_val;                             \
 224} while (0)
 225
 226#define __get_user_asm_byte(x,addr,err)                         \
 227        __asm__ __volatile__(                                   \
 228        "1:     ldrbt   %1,[%2],#0\n"                           \
 229        "2:\n"                                                  \
 230        "       .section .fixup,\"ax\"\n"                       \
 231        "       .align  2\n"                                    \
 232        "3:     mov     %0, %3\n"                               \
 233        "       mov     %1, #0\n"                               \
 234        "       b       2b\n"                                   \
 235        "       .previous\n"                                    \
 236        "       .section __ex_table,\"a\"\n"                    \
 237        "       .align  3\n"                                    \
 238        "       .long   1b, 3b\n"                               \
 239        "       .previous"                                      \
 240        : "+r" (err), "=&r" (x)                                 \
 241        : "r" (addr), "i" (-EFAULT)                             \
 242        : "cc")
 243
 244#ifndef __ARMEB__
 245#define __get_user_asm_half(x,__gu_addr,err)                    \
 246({                                                              \
 247        unsigned long __b1, __b2;                               \
 248        __get_user_asm_byte(__b1, __gu_addr, err);              \
 249        __get_user_asm_byte(__b2, __gu_addr + 1, err);          \
 250        (x) = __b1 | (__b2 << 8);                               \
 251})
 252#else
 253#define __get_user_asm_half(x,__gu_addr,err)                    \
 254({                                                              \
 255        unsigned long __b1, __b2;                               \
 256        __get_user_asm_byte(__b1, __gu_addr, err);              \
 257        __get_user_asm_byte(__b2, __gu_addr + 1, err);          \
 258        (x) = (__b1 << 8) | __b2;                               \
 259})
 260#endif
 261
 262#define __get_user_asm_word(x,addr,err)                         \
 263        __asm__ __volatile__(                                   \
 264        "1:     ldrt    %1,[%2],#0\n"                           \
 265        "2:\n"                                                  \
 266        "       .section .fixup,\"ax\"\n"                       \
 267        "       .align  2\n"                                    \
 268        "3:     mov     %0, %3\n"                               \
 269        "       mov     %1, #0\n"                               \
 270        "       b       2b\n"                                   \
 271        "       .previous\n"                                    \
 272        "       .section __ex_table,\"a\"\n"                    \
 273        "       .align  3\n"                                    \
 274        "       .long   1b, 3b\n"                               \
 275        "       .previous"                                      \
 276        : "+r" (err), "=&r" (x)                                 \
 277        : "r" (addr), "i" (-EFAULT)                             \
 278        : "cc")
 279
 280#define __put_user(x,ptr)                                               \
 281({                                                                      \
 282        long __pu_err = 0;                                              \
 283        __put_user_err((x),(ptr),__pu_err);                             \
 284        __pu_err;                                                       \
 285})
 286
 287#define __put_user_error(x,ptr,err)                                     \
 288({                                                                      \
 289        __put_user_err((x),(ptr),err);                                  \
 290        (void) 0;                                                       \
 291})
 292
 293#define __put_user_err(x,ptr,err)                                       \
 294do {                                                                    \
 295        unsigned long __pu_addr = (unsigned long)(ptr);                 \
 296        __typeof__(*(ptr)) __pu_val = (x);                              \
 297        __chk_user_ptr(ptr);                                            \
 298        switch (sizeof(*(ptr))) {                                       \
 299        case 1: __put_user_asm_byte(__pu_val,__pu_addr,err);    break;  \
 300        case 2: __put_user_asm_half(__pu_val,__pu_addr,err);    break;  \
 301        case 4: __put_user_asm_word(__pu_val,__pu_addr,err);    break;  \
 302        case 8: __put_user_asm_dword(__pu_val,__pu_addr,err);   break;  \
 303        default: __put_user_bad();                                      \
 304        }                                                               \
 305} while (0)
 306
 307#define __put_user_asm_byte(x,__pu_addr,err)                    \
 308        __asm__ __volatile__(                                   \
 309        "1:     strbt   %1,[%2],#0\n"                           \
 310        "2:\n"                                                  \
 311        "       .section .fixup,\"ax\"\n"                       \
 312        "       .align  2\n"                                    \
 313        "3:     mov     %0, %3\n"                               \
 314        "       b       2b\n"                                   \
 315        "       .previous\n"                                    \
 316        "       .section __ex_table,\"a\"\n"                    \
 317        "       .align  3\n"                                    \
 318        "       .long   1b, 3b\n"                               \
 319        "       .previous"                                      \
 320        : "+r" (err)                                            \
 321        : "r" (x), "r" (__pu_addr), "i" (-EFAULT)               \
 322        : "cc")
 323
 324#ifndef __ARMEB__
 325#define __put_user_asm_half(x,__pu_addr,err)                    \
 326({                                                              \
 327        unsigned long __temp = (unsigned long)(x);              \
 328        __put_user_asm_byte(__temp, __pu_addr, err);            \
 329        __put_user_asm_byte(__temp >> 8, __pu_addr + 1, err);   \
 330})
 331#else
 332#define __put_user_asm_half(x,__pu_addr,err)                    \
 333({                                                              \
 334        unsigned long __temp = (unsigned long)(x);              \
 335        __put_user_asm_byte(__temp >> 8, __pu_addr, err);       \
 336        __put_user_asm_byte(__temp, __pu_addr + 1, err);        \
 337})
 338#endif
 339
 340#define __put_user_asm_word(x,__pu_addr,err)                    \
 341        __asm__ __volatile__(                                   \
 342        "1:     strt    %1,[%2],#0\n"                           \
 343        "2:\n"                                                  \
 344        "       .section .fixup,\"ax\"\n"                       \
 345        "       .align  2\n"                                    \
 346        "3:     mov     %0, %3\n"                               \
 347        "       b       2b\n"                                   \
 348        "       .previous\n"                                    \
 349        "       .section __ex_table,\"a\"\n"                    \
 350        "       .align  3\n"                                    \
 351        "       .long   1b, 3b\n"                               \
 352        "       .previous"                                      \
 353        : "+r" (err)                                            \
 354        : "r" (x), "r" (__pu_addr), "i" (-EFAULT)               \
 355        : "cc")
 356
 357#ifndef __ARMEB__
 358#define __reg_oper0     "%R2"
 359#define __reg_oper1     "%Q2"
 360#else
 361#define __reg_oper0     "%Q2"
 362#define __reg_oper1     "%R2"
 363#endif
 364
 365#define __put_user_asm_dword(x,__pu_addr,err)                   \
 366        __asm__ __volatile__(                                   \
 367        "1:     strt    " __reg_oper1 ", [%1], #4\n"            \
 368        "2:     strt    " __reg_oper0 ", [%1], #0\n"            \
 369        "3:\n"                                                  \
 370        "       .section .fixup,\"ax\"\n"                       \
 371        "       .align  2\n"                                    \
 372        "4:     mov     %0, %3\n"                               \
 373        "       b       3b\n"                                   \
 374        "       .previous\n"                                    \
 375        "       .section __ex_table,\"a\"\n"                    \
 376        "       .align  3\n"                                    \
 377        "       .long   1b, 4b\n"                               \
 378        "       .long   2b, 4b\n"                               \
 379        "       .previous"                                      \
 380        : "+r" (err), "+r" (__pu_addr)                          \
 381        : "r" (x), "i" (-EFAULT)                                \
 382        : "cc")
 383
 384
 385#ifdef CONFIG_MMU
 386extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n);
 387extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n);
 388extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n);
 389#else
 390#define __copy_from_user(to,from,n)     (memcpy(to, (void __force *)from, n), 0)
 391#define __copy_to_user(to,from,n)       (memcpy((void __force *)to, from, n), 0)
 392#define __clear_user(addr,n)            (memset((void __force *)addr, 0, n), 0)
 393#endif
 394
 395extern unsigned long __must_check __strncpy_from_user(char *to, const char __user *from, unsigned long count);
 396extern unsigned long __must_check __strnlen_user(const char __user *s, long n);
 397
 398static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
 399{
 400        if (access_ok(VERIFY_READ, from, n))
 401                n = __copy_from_user(to, from, n);
 402        else /* security hole - plug it */
 403                memzero(to, n);
 404        return n;
 405}
 406
 407static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
 408{
 409        if (access_ok(VERIFY_WRITE, to, n))
 410                n = __copy_to_user(to, from, n);
 411        return n;
 412}
 413
 414#define __copy_to_user_inatomic __copy_to_user
 415#define __copy_from_user_inatomic __copy_from_user
 416
 417static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
 418{
 419        if (access_ok(VERIFY_WRITE, to, n))
 420                n = __clear_user(to, n);
 421        return n;
 422}
 423
 424static inline long __must_check strncpy_from_user(char *dst, const char __user *src, long count)
 425{
 426        long res = -EFAULT;
 427        if (access_ok(VERIFY_READ, src, 1))
 428                res = __strncpy_from_user(dst, src, count);
 429        return res;
 430}
 431
 432#define strlen_user(s)  strnlen_user(s, ~0UL >> 1)
 433
 434static inline long __must_check strnlen_user(const char __user *s, long n)
 435{
 436        unsigned long res = 0;
 437
 438        if (__addr_ok(s))
 439                res = __strnlen_user(s, n);
 440
 441        return res;
 442}
 443
 444#endif /* _ASMARM_UACCESS_H */
 445