linux/arch/x86/lib/usercopy_64.c
<<
>>
Prefs
   1/* 
   2 * User address space access functions.
   3 *
   4 * Copyright 1997 Andi Kleen <ak@muc.de>
   5 * Copyright 1997 Linus Torvalds
   6 * Copyright 2002 Andi Kleen <ak@suse.de>
   7 */
   8#include <linux/module.h>
   9#include <asm/uaccess.h>
  10
  11/*
  12 * Copy a null terminated string from userspace.
  13 */
  14
  15#define __do_strncpy_from_user(dst,src,count,res)                          \
  16do {                                                                       \
  17        long __d0, __d1, __d2;                                             \
  18        might_sleep();                                                     \
  19        __asm__ __volatile__(                                              \
  20                "       testq %1,%1\n"                                     \
  21                "       jz 2f\n"                                           \
  22                "0:     lodsb\n"                                           \
  23                "       stosb\n"                                           \
  24                "       testb %%al,%%al\n"                                 \
  25                "       jz 1f\n"                                           \
  26                "       decq %1\n"                                         \
  27                "       jnz 0b\n"                                          \
  28                "1:     subq %1,%0\n"                                      \
  29                "2:\n"                                                     \
  30                ".section .fixup,\"ax\"\n"                                 \
  31                "3:     movq %5,%0\n"                                      \
  32                "       jmp 2b\n"                                          \
  33                ".previous\n"                                              \
  34                ".section __ex_table,\"a\"\n"                              \
  35                "       .align 8\n"                                        \
  36                "       .quad 0b,3b\n"                                     \
  37                ".previous"                                                \
  38                : "=r"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1),      \
  39                  "=&D" (__d2)                                             \
  40                : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
  41                : "memory");                                               \
  42} while (0)
  43
  44long
  45__strncpy_from_user(char *dst, const char __user *src, long count)
  46{
  47        long res;
  48        __do_strncpy_from_user(dst, src, count, res);
  49        return res;
  50}
  51EXPORT_SYMBOL(__strncpy_from_user);
  52
  53long
  54strncpy_from_user(char *dst, const char __user *src, long count)
  55{
  56        long res = -EFAULT;
  57        if (access_ok(VERIFY_READ, src, 1))
  58                return __strncpy_from_user(dst, src, count);
  59        return res;
  60}
  61EXPORT_SYMBOL(strncpy_from_user);
  62
  63/*
  64 * Zero Userspace
  65 */
  66
  67unsigned long __clear_user(void __user *addr, unsigned long size)
  68{
  69        long __d0;
  70        might_sleep();
  71        /* no memory constraint because it doesn't change any memory gcc knows
  72           about */
  73        asm volatile(
  74                "       testq  %[size8],%[size8]\n"
  75                "       jz     4f\n"
  76                "0:     movq %[zero],(%[dst])\n"
  77                "       addq   %[eight],%[dst]\n"
  78                "       decl %%ecx ; jnz   0b\n"
  79                "4:     movq  %[size1],%%rcx\n"
  80                "       testl %%ecx,%%ecx\n"
  81                "       jz     2f\n"
  82                "1:     movb   %b[zero],(%[dst])\n"
  83                "       incq   %[dst]\n"
  84                "       decl %%ecx ; jnz  1b\n"
  85                "2:\n"
  86                ".section .fixup,\"ax\"\n"
  87                "3:     lea 0(%[size1],%[size8],8),%[size8]\n"
  88                "       jmp 2b\n"
  89                ".previous\n"
  90                ".section __ex_table,\"a\"\n"
  91                "       .align 8\n"
  92                "       .quad 0b,3b\n"
  93                "       .quad 1b,2b\n"
  94                ".previous"
  95                : [size8] "=c"(size), [dst] "=&D" (__d0)
  96                : [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr),
  97                  [zero] "r" (0UL), [eight] "r" (8UL));
  98        return size;
  99}
 100EXPORT_SYMBOL(__clear_user);
 101
 102unsigned long clear_user(void __user *to, unsigned long n)
 103{
 104        if (access_ok(VERIFY_WRITE, to, n))
 105                return __clear_user(to, n);
 106        return n;
 107}
 108EXPORT_SYMBOL(clear_user);
 109
 110/*
 111 * Return the size of a string (including the ending 0)
 112 *
 113 * Return 0 on exception, a value greater than N if too long
 114 */
 115
 116long __strnlen_user(const char __user *s, long n)
 117{
 118        long res = 0;
 119        char c;
 120
 121        while (1) {
 122                if (res>n)
 123                        return n+1;
 124                if (__get_user(c, s))
 125                        return 0;
 126                if (!c)
 127                        return res+1;
 128                res++;
 129                s++;
 130        }
 131}
 132EXPORT_SYMBOL(__strnlen_user);
 133
 134long strnlen_user(const char __user *s, long n)
 135{
 136        if (!access_ok(VERIFY_READ, s, n))
 137                return 0;
 138        return __strnlen_user(s, n);
 139}
 140EXPORT_SYMBOL(strnlen_user);
 141
 142long strlen_user(const char __user *s)
 143{
 144        long res = 0;
 145        char c;
 146
 147        for (;;) {
 148                if (get_user(c, s))
 149                        return 0;
 150                if (!c)
 151                        return res+1;
 152                res++;
 153                s++;
 154        }
 155}
 156EXPORT_SYMBOL(strlen_user);
 157
 158unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len)
 159{
 160        if (access_ok(VERIFY_WRITE, to, len) && access_ok(VERIFY_READ, from, len)) { 
 161                return copy_user_generic((__force void *)to, (__force void *)from, len);
 162        } 
 163        return len;             
 164}
 165EXPORT_SYMBOL(copy_in_user);
 166
 167
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.