Re: [PATCH 12/23] bpf: handle the compat string in bpf_trace_copy_string better

From: Yonghong Song
Date: Thu May 28 2020 - 13:07:37 EST




On 5/27/20 9:39 PM, Christoph Hellwig wrote:
On Wed, May 27, 2020 at 07:26:30PM -0700, Yonghong Song wrote:
--- a/kernel/trace/bpf_trace.c~xxx
+++ a/kernel/trace/bpf_trace.c
@@ -588,15 +588,22 @@ BPF_CALL_5(bpf_seq_printf, struct seq_fi
}
if (fmt[i] == 's') {
+ void *unsafe_ptr;
+
/* try our best to copy */
if (memcpy_cnt >= MAX_SEQ_PRINTF_MAX_MEMCPY) {
err = -E2BIG;
goto out;
}
- err = strncpy_from_unsafe(bufs->buf[memcpy_cnt],
- (void *) (long) args[fmt_cnt],
- MAX_SEQ_PRINTF_STR_LEN);
+ unsafe_ptr = (void *)(long)args[fmt_cnt];
+ if ((unsigned long)unsafe_ptr < TASK_SIZE) {
+ err = strncpy_from_user_nofault(
+ bufs->buf[memcpy_cnt], unsafe_ptr,
+ MAX_SEQ_PRINTF_STR_LEN);
+ } else {
+ err = -EFAULT;
+ }

This probably not right.
The pointer stored at args[fmt_cnt] is a kernel pointer,
but it could be an invalid address and we do not want to fault.
Not sure whether it exists or not, we should use
strncpy_from_kernel_nofault()?

If you know it is a kernel pointer with this series it should be
strncpy_from_kernel_nofault. But even before the series it should have
been strncpy_from_unsafe_strict.

The use of strncpy_from_unsafe() mimics old bpf_trace_printk() implementation which just changed to _strict version:
https://lkml.org/lkml/2020/5/18/1309

Agreed that we should change to strncpy_from_unsafe_strict().
I can submit a patch for this.

Thanks!