]> Pileus Git - ~andy/linux/blob - arch/x86/lib/usercopy.c
staging: comedi: Add helper macro for comedi usb driver boilerplate
[~andy/linux] / arch / x86 / lib / usercopy.c
1 /*
2  * User address space access functions.
3  *
4  *  For licencing details see kernel-base/COPYING
5  */
6
7 #include <linux/highmem.h>
8 #include <linux/module.h>
9
10 #include <asm/word-at-a-time.h>
11
12 /*
13  * best effort, GUP based copy_from_user() that is NMI-safe
14  */
15 unsigned long
16 copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
17 {
18         unsigned long offset, addr = (unsigned long)from;
19         unsigned long size, len = 0;
20         struct page *page;
21         void *map;
22         int ret;
23
24         do {
25                 ret = __get_user_pages_fast(addr, 1, 0, &page);
26                 if (!ret)
27                         break;
28
29                 offset = addr & (PAGE_SIZE - 1);
30                 size = min(PAGE_SIZE - offset, n - len);
31
32                 map = kmap_atomic(page);
33                 memcpy(to, map+offset, size);
34                 kunmap_atomic(map);
35                 put_page(page);
36
37                 len  += size;
38                 to   += size;
39                 addr += size;
40
41         } while (len < n);
42
43         return len;
44 }
45 EXPORT_SYMBOL_GPL(copy_from_user_nmi);
46
47 static inline unsigned long count_bytes(unsigned long mask)
48 {
49         mask = (mask - 1) & ~mask;
50         mask >>= 7;
51         return count_masked_bytes(mask);
52 }
53
54 /*
55  * Do a strncpy, return length of string without final '\0'.
56  * 'count' is the user-supplied count (return 'count' if we
57  * hit it), 'max' is the address space maximum (and we return
58  * -EFAULT if we hit it).
59  */
60 static inline long do_strncpy_from_user(char *dst, const char __user *src, long count, unsigned long max)
61 {
62         long res = 0;
63
64         /*
65          * Truncate 'max' to the user-specified limit, so that
66          * we only have one limit we need to check in the loop
67          */
68         if (max > count)
69                 max = count;
70
71         while (max >= sizeof(unsigned long)) {
72                 unsigned long c;
73
74                 /* Fall back to byte-at-a-time if we get a page fault */
75                 if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
76                         break;
77                 /* This can write a few bytes past the NUL character, but that's ok */
78                 *(unsigned long *)(dst+res) = c;
79                 c = has_zero(c);
80                 if (c)
81                         return res + count_bytes(c);
82                 res += sizeof(unsigned long);
83                 max -= sizeof(unsigned long);
84         }
85
86         while (max) {
87                 char c;
88
89                 if (unlikely(__get_user(c,src+res)))
90                         return -EFAULT;
91                 dst[res] = c;
92                 if (!c)
93                         return res;
94                 res++;
95                 max--;
96         }
97
98         /*
99          * Uhhuh. We hit 'max'. But was that the user-specified maximum
100          * too? If so, that's ok - we got as much as the user asked for.
101          */
102         if (res >= count)
103                 return res;
104
105         /*
106          * Nope: we hit the address space limit, and we still had more
107          * characters the caller would have wanted. That's an EFAULT.
108          */
109         return -EFAULT;
110 }
111
112 /**
113  * strncpy_from_user: - Copy a NUL terminated string from userspace.
114  * @dst:   Destination address, in kernel space.  This buffer must be at
115  *         least @count bytes long.
116  * @src:   Source address, in user space.
117  * @count: Maximum number of bytes to copy, including the trailing NUL.
118  *
119  * Copies a NUL-terminated string from userspace to kernel space.
120  *
121  * On success, returns the length of the string (not including the trailing
122  * NUL).
123  *
124  * If access to userspace fails, returns -EFAULT (some data may have been
125  * copied).
126  *
127  * If @count is smaller than the length of the string, copies @count bytes
128  * and returns @count.
129  */
130 long
131 strncpy_from_user(char *dst, const char __user *src, long count)
132 {
133         unsigned long max_addr, src_addr;
134
135         if (unlikely(count <= 0))
136                 return 0;
137
138         max_addr = current_thread_info()->addr_limit.seg;
139         src_addr = (unsigned long)src;
140         if (likely(src_addr < max_addr)) {
141                 unsigned long max = max_addr - src_addr;
142                 return do_strncpy_from_user(dst, src, count, max);
143         }
144         return -EFAULT;
145 }
146 EXPORT_SYMBOL(strncpy_from_user);