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 < (u65)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, cc"         \
  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
 104/*
 105 * The "__xxx" versions of the user access functions do not verify the address
 106 * space - it must have been done previously with a separate "access_ok()"
 107 * call.
 108 *
 109 * The "__xxx_error" versions set the third argument to -EFAULT if an error
 110 * occurs, and leave it unchanged on success.
 111 */
 112#define __get_user_asm(instr, reg, x, addr, err)                        \
 113        asm volatile(                                                   \
 114        "1:     " instr "       " reg "1, [%2]\n"                       \
 115        "2:\n"                                                          \
 116        "       .section .fixup, \"ax\"\n"                              \
 117        "       .align  2\n"                                            \
 118        "3:     mov     %w0, %3\n"                                      \
 119        "       mov     %1, #0\n"                                       \
 120        "       b       2b\n"                                           \
 121        "       .previous\n"                                            \
 122        "       .section __ex_table,\"a\"\n"                            \
 123        "       .align  3\n"                                            \
 124        "       .quad   1b, 3b\n"                                       \
 125        "       .previous"                                              \
 126        : "+r" (err), "=&r" (x)                                         \
 127        : "r" (addr), "i" (-EFAULT))
 128
 129#define __get_user_err(x, ptr, err)                                     \
 130do {                                                                    \
 131        unsigned long __gu_val;                                         \
 132        __chk_user_ptr(ptr);                                            \
 133        switch (sizeof(*(ptr))) {                                       \
 134        case 1:                                                         \
 135                __get_user_asm("ldrb", "%w", __gu_val, (ptr), (err));   \
 136                break;                                                  \
 137        case 2:                                                         \
 138                __get_user_asm("ldrh", "%w", __gu_val, (ptr), (err));   \
 139                break;                                                  \
 140        case 4:                                                         \
 141                __get_user_asm("ldr", "%w", __gu_val, (ptr), (err));    \
 142                break;                                                  \
 143        case 8:                                                         \
 144                __get_user_asm("ldr", "%",  __gu_val, (ptr), (err));    \
 145                break;                                                  \
 146        default:                                                        \
 147                BUILD_BUG();                                            \
 148        }                                                               \
 149        (x) = (__typeof__(*(ptr)))__gu_val;                             \
 150} while (0)
 151
 152#define __get_user(x, ptr)                                              \
 153({                                                                      \
 154        int __gu_err = 0;                                               \
 155        __get_user_err((x), (ptr), __gu_err);                           \
 156        __gu_err;                                                       \
 157})
 158
 159#define __get_user_error(x, ptr, err)                                   \
 160({                                                                      \
 161        __get_user_err((x), (ptr), (err));                              \
 162        (void)0;                                                        \
 163})
 164
 165#define __get_user_unaligned __get_user
 166
 167#define get_user(x, ptr)                                                \
 168({                                                                      \
 169        might_fault();                                                  \
 170        access_ok(VERIFY_READ, (ptr), sizeof(*(ptr))) ?                 \
 171                __get_user((x), (ptr)) :                                \
 172                ((x) = 0, -EFAULT);                                     \
 173})
 174
 175#define __put_user_asm(instr, reg, x, addr, err)                        \
 176        asm volatile(                                                   \
 177        "1:     " instr "       " reg "1, [%2]\n"                       \
 178        "2:\n"                                                          \
 179        "       .section .fixup,\"ax\"\n"                               \
 180        "       .align  2\n"                                            \
 181        "3:     mov     %w0, %3\n"                                      \
 182        "       b       2b\n"                                           \
 183        "       .previous\n"                                            \
 184        "       .section __ex_table,\"a\"\n"                            \
 185        "       .align  3\n"                                            \
 186        "       .quad   1b, 3b\n"                                       \
 187        "       .previous"                                              \
 188        : "+r" (err)                                                    \
 189        : "r" (x), "r" (addr), "i" (-EFAULT))
 190
 191#define __put_user_err(x, ptr, err)                                     \
 192do {                                                                    \
 193        __typeof__(*(ptr)) __pu_val = (x);                              \
 194        __chk_user_ptr(ptr);                                            \
 195        switch (sizeof(*(ptr))) {                                       \
 196        case 1:                                                         \
 197                __put_user_asm("strb", "%w", __pu_val, (ptr), (err));   \
 198                break;                                                  \
 199        case 2:                                                         \
 200                __put_user_asm("strh", "%w", __pu_val, (ptr), (err));   \
 201                break;                                                  \
 202        case 4:                                                         \
 203                __put_user_asm("str",  "%w", __pu_val, (ptr), (err));   \
 204                break;                                                  \
 205        case 8:                                                         \
 206                __put_user_asm("str",  "%", __pu_val, (ptr), (err));    \
 207                break;                                                  \
 208        default:                                                        \
 209                BUILD_BUG();                                            \
 210        }                                                               \
 211} while (0)
 212
 213#define __put_user(x, ptr)                                              \
 214({                                                                      \
 215        int __pu_err = 0;                                               \
 216        __put_user_err((x), (ptr), __pu_err);                           \
 217        __pu_err;                                                       \
 218})
 219
 220#define __put_user_error(x, ptr, err)                                   \
 221({                                                                      \
 222        __put_user_err((x), (ptr), (err));                              \
 223        (void)0;                                                        \
 224})
 225
 226#define __put_user_unaligned __put_user
 227
 228#define put_user(x, ptr)                                                \
 229({                                                                      \
 230        might_fault();                                                  \
 231        access_ok(VERIFY_WRITE, (ptr), sizeof(*(ptr))) ?                \
 232                __put_user((x), (ptr)) :                                \
 233                -EFAULT;                                                \
 234})
 235
 236extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n);
 237extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n);
 238extern unsigned long __must_check __copy_in_user(void __user *to, const void __user *from, unsigned long n);
 239extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n);
 240
 241extern unsigned long __must_check __strncpy_from_user(char *to, const char __user *from, unsigned long count);
 242extern unsigned long __must_check __strnlen_user(const char __user *s, 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
 277static inline long __must_check strncpy_from_user(char *dst, const char __user *src, long count)
 278{
 279        long res = -EFAULT;
 280        if (access_ok(VERIFY_READ, src, 1))
 281                res = __strncpy_from_user(dst, src, count);
 282        return res;
 283}
 284
 285#define strlen_user(s)  strnlen_user(s, ~0UL >> 1)
 286
 287static inline long __must_check strnlen_user(const char __user *s, long n)
 288{
 289        unsigned long res = 0;
 290
 291        if (__addr_ok(s))
 292                res = __strnlen_user(s, n);
 293
 294        return res;
 295}
 296
 297#endif /* __ASM_UACCESS_H */
 298