.. | .. |
---|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
---|
2 | 2 | #include <linux/compiler.h> |
---|
3 | 3 | #include <linux/export.h> |
---|
| 4 | +#include <linux/fault-inject-usercopy.h> |
---|
4 | 5 | #include <linux/kasan-checks.h> |
---|
5 | 6 | #include <linux/thread_info.h> |
---|
6 | 7 | #include <linux/uaccess.h> |
---|
.. | .. |
---|
34 | 35 | goto byte_at_a_time; |
---|
35 | 36 | |
---|
36 | 37 | while (max >= sizeof(unsigned long)) { |
---|
37 | | - unsigned long c, data; |
---|
| 38 | + unsigned long c, data, mask; |
---|
38 | 39 | |
---|
39 | 40 | /* Fall back to byte-at-a-time if we get a page fault */ |
---|
40 | 41 | unsafe_get_user(c, (unsigned long __user *)(src+res), byte_at_a_time); |
---|
41 | 42 | |
---|
42 | | - *(unsigned long *)(dst+res) = c; |
---|
| 43 | + /* |
---|
| 44 | + * Note that we mask out the bytes following the NUL. This is |
---|
| 45 | + * important to do because string oblivious code may read past |
---|
| 46 | + * the NUL. For those routines, we don't want to give them |
---|
| 47 | + * potentially random bytes after the NUL in `src`. |
---|
| 48 | + * |
---|
| 49 | + * One example of such code is BPF map keys. BPF treats map keys |
---|
| 50 | + * as an opaque set of bytes. Without the post-NUL mask, any BPF |
---|
| 51 | + * maps keyed by strings returned from strncpy_from_user() may |
---|
| 52 | + * have multiple entries for semantically identical strings. |
---|
| 53 | + */ |
---|
43 | 54 | if (has_zero(c, &data, &constants)) { |
---|
44 | 55 | data = prep_zero_mask(c, data, &constants); |
---|
45 | 56 | data = create_zero_mask(data); |
---|
| 57 | + mask = zero_bytemask(data); |
---|
| 58 | + *(unsigned long *)(dst+res) = c & mask; |
---|
46 | 59 | return res + find_zero(data); |
---|
47 | 60 | } |
---|
| 61 | + |
---|
| 62 | + *(unsigned long *)(dst+res) = c; |
---|
| 63 | + |
---|
48 | 64 | res += sizeof(unsigned long); |
---|
49 | 65 | max -= sizeof(unsigned long); |
---|
50 | 66 | } |
---|
.. | .. |
---|
98 | 114 | { |
---|
99 | 115 | unsigned long max_addr, src_addr; |
---|
100 | 116 | |
---|
| 117 | + might_fault(); |
---|
| 118 | + if (should_fail_usercopy()) |
---|
| 119 | + return -EFAULT; |
---|
101 | 120 | if (unlikely(count <= 0)) |
---|
102 | 121 | return 0; |
---|
103 | 122 | |
---|
.. | .. |
---|
116 | 135 | |
---|
117 | 136 | kasan_check_write(dst, count); |
---|
118 | 137 | check_object_size(dst, count, false); |
---|
119 | | - if (user_access_begin(VERIFY_READ, src, max)) { |
---|
| 138 | + if (user_read_access_begin(src, max)) { |
---|
120 | 139 | retval = do_strncpy_from_user(dst, src, count, max); |
---|
121 | | - user_access_end(); |
---|
| 140 | + user_read_access_end(); |
---|
122 | 141 | return retval; |
---|
123 | 142 | } |
---|
124 | 143 | } |
---|