linux/arch/arm64/include/asm/uaccess.h
<<
>>
Prefs
   1/*
   2 * Based on arch/arm/include/asm/uaccess.h
   3 *
   4 * Copyright (C) 2012 ARM Ltd.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17 */
  18#ifndef __ASM_UACCESS_H
  19#define __ASM_UACCESS_H
  20
  21/*
  22 * User space memory access functions
  23 */
  24#include <linux/string.h>
  25#include <linux/thread_info.h>
  26
  27#include <asm/ptrace.h>
  28#include <asm/errno.h>
  29#include <asm/memory.h>
  30#include <asm/compiler.h>
  31
  32#define VERIFY_READ 0
  33#define VERIFY_WRITE 1
  34
  35/*
  36 * The exception table consists of pairs of addresses: the first is the
  37 * address of an instruction that is allowed to fault, and the second is
  38 * the address at which the program should continue.  No registers are
  39 * modified, so it is entirely up to the continuation code to figure out
  40 * what to do.
  41 *
  42 * All the routines below use bits of fixup code that are out of line
  43 * with the main instruction path.  This means when everything is well,
  44 * we don't even have to jump over them.  Further, they do not intrude
  45 * on our cache or tlb entries.
  46 */
  47
  48struct exception_table_entry
  49{
  50        unsigned long insn, fixup;
  51};
  52
  53extern int fixup_exception(struct pt_regs *regs);
  54
  55#define KERNEL_DS       (-1UL)
  56#define get_ds()        (KERNEL_DS)
  57
  58#define USER_DS         TASK_SIZE_64
  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}
  65
  66#define segment_eq(a, b)        ((a) == (b))
  67
  68/*
  69 * Return 1 if addr < current->addr_limit, 0 otherwise.
  70 */
  71#define __addr_ok(addr)                                                 \
  72({                                                                      \
  73        unsigned long flag;                                             \
  74        asm("cmp %1, %0; cset %0, lo"                                   \
  75                : "=&r" (flag)                                          \
  76                : "r" (addr), "0" (current_thread_info()->addr_limit)   \
  77                : "cc");                                                \
  78        flag;                                                           \
  79})
  80
  81/*
  82 * Test whether a block of memory is a valid user space address.
  83 * Returns 1 if the range is valid, 0 otherwise.
  84 *
  85 * This is equivalent to the following test:
  86 * (u65)addr + (u65)size <= current->addr_limit
  87 *
  88 * This needs 65-bit arithmetic.
  89 */
  90#define __range_ok(addr, size)                                          \
  91({                                                                      \
  92        unsigned long flag, roksum;                                     \
  93        __chk_user_ptr(addr);                                           \
  94        asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, ls"         \
  95                : "=&r" (flag), "=&r" (roksum)                          \
  96                : "1" (addr), "Ir" (size),                              \
  97                  "r" (current_thread_info()->addr_limit)               \
  98                : "cc");                                                \
  99        flag;                                                           \
 100})
 101
 102#define access_ok(type, addr, size)     __range_ok(addr, size)
 103#define user_addr_max                   get_fs
 104
 105/*
 106 * The "__xxx" versions of the user access functions do not verify the address
 107 * space - it must have been done previously with a separate "access_ok()"
 108 * call.
 109 *
 110 * The "__xxx_error" versions set the third argument to -EFAULT if an error
 111 * occurs, and leave it unchanged on success.
 112 */
 113#define __get_user_asm(instr, reg, x, addr, err)                        \
 114        asm volatile(                                                   \
 115        "1:     " instr "       " reg "1, [%2]\n"                       \
 116        "2:\n"                                                          \
 117        "       .section .fixup, \"ax\"\n"                              \
 118        "       .align  2\n"                                            \
 119        "3:     mov     %w0, %3\n"                                      \
 120        "       mov     %1, #0\n"                                       \
 121        "       b       2b\n"                                           \
 122        "       .previous\n"                                            \
 123        "       .section __ex_table,\"a\"\n"                            \
 124        "       .align  3\n"                                            \
 125        "       .quad   1b, 3b\n"                                       \
 126        "       .previous"                                              \
 127        : "+r" (err), "=&r" (x)                                         \
 128        : "r" (addr), "i" (-EFAULT))
 129
 130#define __get_user_err(x, ptr, err)                                     \
 131do {                                                                    \
 132        unsigned long __gu_val;                                         \
 133        __chk_user_ptr(ptr);                                            \
 134        switch (sizeof(*(ptr))) {                                       \
 135        case 1:                                                         \
 136                __get_user_asm("ldrb", "%w", __gu_val, (ptr), (err));   \
 137                break;                                                  \
 138        case 2:                                                         \
 139                __get_user_asm("ldrh", "%w", __gu_val, (ptr), (err));   \
 140                break;                                                  \
 141        case 4:                                                         \
 142                __get_user_asm("ldr", "%w", __gu_val, (ptr), (err));    \
 143                break;                                                  \
 144        case 8:                                                         \
 145                __get_user_asm("ldr", "%",  __gu_val, (ptr), (err));    \
 146                break;                                                  \
 147        default:                                                        \
 148                BUILD_BUG();                                            \
 149        }                                                               \
 150        (x) = (__force __typeof__(*(ptr)))__gu_val;                     \
 151} while (0)
 152
 153#define __get_user(x, ptr)                                              \
 154({                                                                      \
 155        int __gu_err = 0;                                               \
 156        __get_user_err((x), (ptr), __gu_err);                           \
 157        __gu_err;                                                       \
 158})
 159
 160#define __get_user_error(x, ptr, err)                                   \
 161({                                                                      \
 162        __get_user_err((x), (ptr), (err));                              \
 163        (void)0;                                                        \
 164})
 165
 166#define __get_user_unaligned __get_user
 167
 168#define get_user(x, ptr)                                                \
 169({                                                                      \
 170        __typeof__(*(ptr)) __user *__p = (ptr);                         \
 171        might_fault();                                                  \
 172        access_ok(VERIFY_READ, __p, sizeof(*__p)) ?                     \
 173                __get_user((x), __p) :                                  \
 174                ((x) = 0, -EFAULT);                                     \
 175})
 176
 177#define __put_user_asm(instr, reg, x, addr, err)                        \
 178        asm volatile(                                                   \
 179        "1:     " instr "       " reg "1, [%2]\n"                       \
 180        "2:\n"                                                          \
 181        "       .section .fixup,\"ax\"\n"                               \
 182        "       .align  2\n"                                            \
 183        "3:     mov     %w0, %3\n"                                      \
 184        "       b       2b\n"                                           \
 185        "       .previous\n"                                            \
 186        "       .section __ex_table,\"a\"\n"                            \
 187        "       .align  3\n"                                            \
 188        "       .quad   1b, 3b\n"                                       \
 189        "       .previous"                                              \
 190        : "+r" (err)                                                    \
 191        : "r" (x), "r" (addr), "i" (-EFAULT))
 192
 193#define __put_user_err(x, ptr, err)                                     \
 194do {                                                                    \
 195        __typeof__(*(ptr)) __pu_val = (x);                              \
 196        __chk_user_ptr(ptr);                                            \
 197        switch (sizeof(*(ptr))) {                                       \
 198        case 1:                                                         \
 199                __put_user_asm("strb", "%w", __pu_val, (ptr), (err));   \
 200                break;                                                  \
 201        case 2:                                                         \
 202                __put_user_asm("strh", "%w", __pu_val, (ptr), (err));   \
 203                break;                                                  \
 204        case 4:                                                         \
 205                __put_user_asm("str",  "%w", __pu_val, (ptr), (err));   \
 206                break;                                                  \
 207        case 8:                                                         \
 208                __put_user_asm("str",  "%", __pu_val, (ptr), (err));    \
 209                break;                                                  \
 210        default:                                                        \
 211                BUILD_BUG();                                            \
 212        }                                                               \
 213} while (0)
 214
 215#define __put_user(x, ptr)                                              \
 216({                                                                      \
 217        int __pu_err = 0;                                               \
 218        __put_user_err((x), (ptr), __pu_err);                           \
 219        __pu_err;                                                       \
 220})
 221
 222#define __put_user_error(x, ptr, err)                                   \
 223({                                                                      \
 224        __put_user_err((x), (ptr), (err));                              \
 225        (void)0;                                                        \
 226})
 227
 228#define __put_user_unaligned __put_user
 229
 230#define put_user(x, ptr)                                                \
 231({                                                                      \
 232        __typeof__(*(ptr)) __user *__p = (ptr);                         \
 233        might_fault();                                                  \
 234        access_ok(VERIFY_WRITE, __p, sizeof(*__p)) ?                    \
 235                __put_user((x), __p) :                                  \
 236                -EFAULT;                                                \
 237})
 238
 239extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n);
 240extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n);
 241extern unsigned long __must_check __copy_in_user(void __user *to, const void __user *from, unsigned long n);
 242extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n);
 243
 244static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
 245{
 246        if (access_ok(VERIFY_READ, from, n))
 247                n = __copy_from_user(to, from, n);
 248        else /* security hole - plug it */
 249                memset(to, 0, n);
 250        return n;
 251}
 252
 253static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
 254{
 255        if (access_ok(VERIFY_WRITE, to, n))
 256                n = __copy_to_user(to, from, n);
 257        return n;
 258}
 259
 260static inline unsigned long __must_check copy_in_user(void __user *to, const void __user *from, unsigned long n)
 261{
 262        if (access_ok(VERIFY_READ, from, n) && access_ok(VERIFY_WRITE, to, n))
 263                n = __copy_in_user(to, from, n);
 264        return n;
 265}
 266
 267#define __copy_to_user_inatomic __copy_to_user
 268#define __copy_from_user_inatomic __copy_from_user
 269
 270static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
 271{
 272        if (access_ok(VERIFY_WRITE, to, n))
 273                n = __clear_user(to, n);
 274        return n;
 275}
 276
 277extern long strncpy_from_user(char *dest, const char __user *src, long count);
 278
 279extern __must_check long strlen_user(const char __user *str);
 280extern __must_check long strnlen_user(const char __user *str, long n);
 281
 282#endif /* __ASM_UACCESS_H */
 283