Blame view

lib/usercopy.c 2.19 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
f5a1a536f   Aleksa Sarai   lib: introduce co...
2
  #include <linux/bitops.h>
4d0e9df5e   Albert van der Linde   lib, uaccess: add...
3
  #include <linux/fault-inject-usercopy.h>
76d6f06c3   Marco Elver   copy_to_user, cop...
4
5
  #include <linux/instrumented.h>
  #include <linux/uaccess.h>
d597580d3   Al Viro   generic ...copy_....
6
7
8
9
10
11
12
  
  /* out-of-line parts */
  
  #ifndef INLINE_COPY_FROM_USER
  unsigned long _copy_from_user(void *to, const void __user *from, unsigned long n)
  {
  	unsigned long res = n;
9c5f6908d   Al Viro   copy_{from,to}_us...
13
  	might_fault();
4d0e9df5e   Albert van der Linde   lib, uaccess: add...
14
  	if (!should_fail_usercopy() && likely(access_ok(from, n))) {
76d6f06c3   Marco Elver   copy_to_user, cop...
15
  		instrument_copy_from_user(to, from, n);
d597580d3   Al Viro   generic ...copy_....
16
  		res = raw_copy_from_user(to, from, n);
9c5f6908d   Al Viro   copy_{from,to}_us...
17
  	}
d597580d3   Al Viro   generic ...copy_....
18
19
20
21
22
23
24
25
  	if (unlikely(res))
  		memset(to + (n - res), 0, res);
  	return res;
  }
  EXPORT_SYMBOL(_copy_from_user);
  #endif
  
  #ifndef INLINE_COPY_TO_USER
a0e94598e   Christophe Leroy   Fix misannotated ...
26
  unsigned long _copy_to_user(void __user *to, const void *from, unsigned long n)
d597580d3   Al Viro   generic ...copy_....
27
  {
9c5f6908d   Al Viro   copy_{from,to}_us...
28
  	might_fault();
4d0e9df5e   Albert van der Linde   lib, uaccess: add...
29
30
  	if (should_fail_usercopy())
  		return n;
96d4f267e   Linus Torvalds   Remove 'type' arg...
31
  	if (likely(access_ok(to, n))) {
76d6f06c3   Marco Elver   copy_to_user, cop...
32
  		instrument_copy_to_user(to, from, n);
d597580d3   Al Viro   generic ...copy_....
33
  		n = raw_copy_to_user(to, from, n);
9c5f6908d   Al Viro   copy_{from,to}_us...
34
  	}
d597580d3   Al Viro   generic ...copy_....
35
36
37
38
  	return n;
  }
  EXPORT_SYMBOL(_copy_to_user);
  #endif
f5a1a536f   Aleksa Sarai   lib: introduce co...
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
  
  /**
   * check_zeroed_user: check if a userspace buffer only contains zero bytes
   * @from: Source address, in userspace.
   * @size: Size of buffer.
   *
   * This is effectively shorthand for "memchr_inv(from, 0, size) == NULL" for
   * userspace addresses (and is more efficient because we don't care where the
   * first non-zero byte is).
   *
   * Returns:
   *  * 0: There were non-zero bytes present in the buffer.
   *  * 1: The buffer was full of zero bytes.
   *  * -EFAULT: access to userspace failed.
   */
  int check_zeroed_user(const void __user *from, size_t size)
  {
  	unsigned long val;
  	uintptr_t align = (uintptr_t) from % sizeof(unsigned long);
  
  	if (unlikely(size == 0))
  		return 1;
  
  	from -= align;
  	size += align;
41cd78052   Christophe Leroy   uaccess: Selectiv...
64
  	if (!user_read_access_begin(from, size))
f5a1a536f   Aleksa Sarai   lib: introduce co...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  		return -EFAULT;
  
  	unsafe_get_user(val, (unsigned long __user *) from, err_fault);
  	if (align)
  		val &= ~aligned_byte_mask(align);
  
  	while (size > sizeof(unsigned long)) {
  		if (unlikely(val))
  			goto done;
  
  		from += sizeof(unsigned long);
  		size -= sizeof(unsigned long);
  
  		unsafe_get_user(val, (unsigned long __user *) from, err_fault);
  	}
  
  	if (size < sizeof(unsigned long))
  		val &= aligned_byte_mask(size);
  
  done:
41cd78052   Christophe Leroy   uaccess: Selectiv...
85
  	user_read_access_end();
f5a1a536f   Aleksa Sarai   lib: introduce co...
86
87
  	return (val == 0);
  err_fault:
41cd78052   Christophe Leroy   uaccess: Selectiv...
88
  	user_read_access_end();
f5a1a536f   Aleksa Sarai   lib: introduce co...
89
90
91
  	return -EFAULT;
  }
  EXPORT_SYMBOL(check_zeroed_user);