projects/linux·blob master · refs

81 lines · 2.0 KiB

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#if !defined(INLINE_COPY_USER)
16unsigned long _copy_from_user(void *to, const void __user *from, unsigned long n)
17{
18 return _inline_copy_from_user(to, from, n);
19}
20EXPORT_SYMBOL(_copy_from_user);
21
22unsigned long _copy_to_user(void __user *to, const void *from, unsigned long n)
23{
24 return _inline_copy_to_user(to, from, n);
25}
26EXPORT_SYMBOL(_copy_to_user);
27#endif
28
29/**
30 * check_zeroed_user: check if a userspace buffer only contains zero bytes
31 * @from: Source address, in userspace.
32 * @size: Size of buffer.
33 *
34 * This is effectively shorthand for "memchr_inv(from, 0, size) == NULL" for
35 * userspace addresses (and is more efficient because we don't care where the
36 * first non-zero byte is).
37 *
38 * Returns:
39 * * 0: There were non-zero bytes present in the buffer.
40 * * 1: The buffer was full of zero bytes.
41 * * -EFAULT: access to userspace failed.
42 */
43int check_zeroed_user(const void __user *from, size_t size)
44{
45 unsigned long val;
46 uintptr_t align = (uintptr_t) from % sizeof(unsigned long);
47
48 if (unlikely(size == 0))
49 return 1;
50
51 from -= align;
52 size += align;
53
54 if (!user_read_access_begin(from, size))
55 return -EFAULT;
56
57 unsafe_get_user(val, (unsigned long __user *) from, err_fault);
58 if (align)
59 val &= ~aligned_byte_mask(align);
60
61 while (size > sizeof(unsigned long)) {
62 if (unlikely(val))
63 goto done;
64
65 from += sizeof(unsigned long);
66 size -= sizeof(unsigned long);
67
68 unsafe_get_user(val, (unsigned long __user *) from, err_fault);
69 }
70
71 if (size < sizeof(unsigned long))
72 val &= aligned_byte_mask(size);
73
74done:
75 user_read_access_end();
76 return (val == 0);
77err_fault:
78 user_read_access_end();
79 return -EFAULT;
80}
81EXPORT_SYMBOL(check_zeroed_user);