]> Git Repo - linux.git/blob - lib/usercopy.c
block: move the dax flag to queue_limits
[linux.git] / lib / usercopy.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/compiler.h>
3 #include <linux/errno.h>
4 #include <linux/export.h>
5 #include <linux/fault-inject-usercopy.h>
6 #include <linux/instrumented.h>
7 #include <linux/kernel.h>
8 #include <linux/nospec.h>
9 #include <linux/string.h>
10 #include <linux/uaccess.h>
11 #include <linux/wordpart.h>
12
13 /* out-of-line parts */
14
15 #ifndef INLINE_COPY_FROM_USER
16 unsigned long _copy_from_user(void *to, const void __user *from, unsigned long n)
17 {
18         unsigned long res = n;
19         might_fault();
20         if (!should_fail_usercopy() && likely(access_ok(from, n))) {
21                 /*
22                  * Ensure that bad access_ok() speculation will not
23                  * lead to nasty side effects *after* the copy is
24                  * finished:
25                  */
26                 barrier_nospec();
27                 instrument_copy_from_user_before(to, from, n);
28                 res = raw_copy_from_user(to, from, n);
29                 instrument_copy_from_user_after(to, from, n, res);
30         }
31         if (unlikely(res))
32                 memset(to + (n - res), 0, res);
33         return res;
34 }
35 EXPORT_SYMBOL(_copy_from_user);
36 #endif
37
38 #ifndef INLINE_COPY_TO_USER
39 unsigned long _copy_to_user(void __user *to, const void *from, unsigned long n)
40 {
41         might_fault();
42         if (should_fail_usercopy())
43                 return n;
44         if (likely(access_ok(to, n))) {
45                 instrument_copy_to_user(to, from, n);
46                 n = raw_copy_to_user(to, from, n);
47         }
48         return n;
49 }
50 EXPORT_SYMBOL(_copy_to_user);
51 #endif
52
53 /**
54  * check_zeroed_user: check if a userspace buffer only contains zero bytes
55  * @from: Source address, in userspace.
56  * @size: Size of buffer.
57  *
58  * This is effectively shorthand for "memchr_inv(from, 0, size) == NULL" for
59  * userspace addresses (and is more efficient because we don't care where the
60  * first non-zero byte is).
61  *
62  * Returns:
63  *  * 0: There were non-zero bytes present in the buffer.
64  *  * 1: The buffer was full of zero bytes.
65  *  * -EFAULT: access to userspace failed.
66  */
67 int check_zeroed_user(const void __user *from, size_t size)
68 {
69         unsigned long val;
70         uintptr_t align = (uintptr_t) from % sizeof(unsigned long);
71
72         if (unlikely(size == 0))
73                 return 1;
74
75         from -= align;
76         size += align;
77
78         if (!user_read_access_begin(from, size))
79                 return -EFAULT;
80
81         unsafe_get_user(val, (unsigned long __user *) from, err_fault);
82         if (align)
83                 val &= ~aligned_byte_mask(align);
84
85         while (size > sizeof(unsigned long)) {
86                 if (unlikely(val))
87                         goto done;
88
89                 from += sizeof(unsigned long);
90                 size -= sizeof(unsigned long);
91
92                 unsafe_get_user(val, (unsigned long __user *) from, err_fault);
93         }
94
95         if (size < sizeof(unsigned long))
96                 val &= aligned_byte_mask(size);
97
98 done:
99         user_read_access_end();
100         return (val == 0);
101 err_fault:
102         user_read_access_end();
103         return -EFAULT;
104 }
105 EXPORT_SYMBOL(check_zeroed_user);
This page took 0.037263 seconds and 4 git commands to generate.