diff options
author | Peter Zijlstra <peterz@infradead.org> | 2020-12-09 17:08:45 +0100 |
---|---|---|
committer | Peter Zijlstra <peterz@infradead.org> | 2020-12-09 17:08:45 +0100 |
commit | 2b3c99ee6389d33aff91d9e7a55465d7d1332bbd (patch) | |
tree | 9e1e5d839d80c95854007c958f2c367290bf1090 /lib | |
parent | refcount: Fix a kernel-doc markup (diff) | |
parent | rwsem: Implement down_read_interruptible (diff) | |
download | linux-2b3c99ee6389d33aff91d9e7a55465d7d1332bbd.tar.xz linux-2b3c99ee6389d33aff91d9e7a55465d7d1332bbd.zip |
Merge branch 'locking/rwsem'
Diffstat (limited to 'lib')
-rw-r--r-- | lib/strncpy_from_user.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/lib/strncpy_from_user.c b/lib/strncpy_from_user.c index e6d5fcc2cdf3..122d8d0e253c 100644 --- a/lib/strncpy_from_user.c +++ b/lib/strncpy_from_user.c @@ -35,17 +35,32 @@ static inline long do_strncpy_from_user(char *dst, const char __user *src, goto byte_at_a_time; while (max >= sizeof(unsigned long)) { - unsigned long c, data; + unsigned long c, data, mask; /* Fall back to byte-at-a-time if we get a page fault */ unsafe_get_user(c, (unsigned long __user *)(src+res), byte_at_a_time); - *(unsigned long *)(dst+res) = c; + /* + * Note that we mask out the bytes following the NUL. This is + * important to do because string oblivious code may read past + * the NUL. For those routines, we don't want to give them + * potentially random bytes after the NUL in `src`. + * + * One example of such code is BPF map keys. BPF treats map keys + * as an opaque set of bytes. Without the post-NUL mask, any BPF + * maps keyed by strings returned from strncpy_from_user() may + * have multiple entries for semantically identical strings. + */ if (has_zero(c, &data, &constants)) { data = prep_zero_mask(c, data, &constants); data = create_zero_mask(data); + mask = zero_bytemask(data); + *(unsigned long *)(dst+res) = c & mask; return res + find_zero(data); } + + *(unsigned long *)(dst+res) = c; + res += sizeof(unsigned long); max -= sizeof(unsigned long); } |