summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@kernel.org>2020-11-19 10:45:55 -0800
committerAlexei Starovoitov <ast@kernel.org>2020-11-19 11:58:15 -0800
commit14d6d86c210aea1a83c19a8f6391ecabcbefed94 (patch)
tree5eadde2770ff55b99a77d39e56e9b3dc322ce628 /kernel
parent1fd6cee127e2ddff36d648573d7566aafb0d0b77 (diff)
parentc8a36aedf3e24768e94d87fdcdd37684bd241c44 (diff)
Merge branch 'Fix bpf_probe_read_user_str() overcopying'
Daniel Xu says: ==================== 6ae08ae3dea2 ("bpf: Add probe_read_{user, kernel} and probe_read_{user, kernel}_str helpers") introduced a subtle bug where bpf_probe_read_user_str() would potentially copy a few extra bytes after the NUL terminator. This issue is particularly nefarious when strings are used as map keys, as seemingly identical strings can occupy multiple entries in a map. This patchset fixes the issue and introduces a selftest to prevent future regressions. v6 -> v7: * Add comments v5 -> v6: * zero-pad up to sizeof(unsigned long) after NUL v4 -> v5: * don't read potentially uninitialized memory v3 -> v4: * directly pass userspace pointer to prog * test more strings of different length v2 -> v3: * set pid filter before attaching prog in selftest * use long instead of int as bpf_probe_read_user_str() retval * style changes v1 -> v2: * add Fixes: tag * add selftest ==================== Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/bpf_trace.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 5113fd423cdf..048c655315f1 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -181,6 +181,16 @@ bpf_probe_read_user_str_common(void *dst, u32 size,
{
int ret;
+ /*
+ * NB: We rely on strncpy_from_user() not copying junk past the NUL
+ * terminator into `dst`.
+ *
+ * strncpy_from_user() does long-sized strides in the fast path. If the
+ * strncpy does not mask out the bytes after the NUL in `unsafe_ptr`,
+ * then there could be junk after the NUL in `dst`. If user takes `dst`
+ * and keys a hash map with it, then semantically identical strings can
+ * occupy multiple entries in the map.
+ */
ret = strncpy_from_user_nofault(dst, unsafe_ptr, size);
if (unlikely(ret < 0))
memset(dst, 0, size);