| .. | .. |
|---|
| 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 | } |
|---|