tracing: Fixes for v6.17
Subsystems (4)
cover tracing: Fixes for v6.17
tracing fixes for v6.17
- Fix buffer overflow in osnoise_cpu_write()
The allocated buffer to read user space did not add a nul terminating byte after copying from user the string. It then reads the string, and if user space did not add a nul byte, the read will continue beyond the string. Add a nul terminating byte after reading the string.
- Fix missing check for lockdown on tracing
There's a path from kprobe events or uprobe events that can update the tracing system even if lockdown on tracing is activate. Add a check in the dynamic event path.
- Add a recursion check for the function graph return path
Now that fprobes can hook to the function graph tracer and call different code between the entry and the exit, the exit code may now call functions that are not called in entry. This means that the exit handler can possibly trigger recursion that is not caught and cause the system to crash. Add the same recursion checks in the function exit handler as exists in the entry handler path.
git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git
trace/fixes
Head SHA1: 0db0934e7f9bb624ed98a665890dbe249f65b8fd
Masami Hiramatsu (Google) (2):
tracing: dynevent: Add a missing lockdown check on dynevent
tracing: fgraph: Protect return handler from recursion loop
Wang Liang (1):
tracing/osnoise: Fix slab-out-of-bounds in _parse_integer_limit()
----
kernel/trace/fgraph.c | 12 ++++++++++++ kernel/trace/trace_dynevent.c | 4 ++++ kernel/trace/trace_osnoise.c | 3 ++- 3 files changed, 18 insertions(+), 1 deletion(-)
PATCH 1/3 tracing/osnoise: Fix slab-out-of-bounds in _parse_integer_limit()
From: Wang Liang <[email protected]>
When config osnoise cpus by write() syscall, the following KASAN splat may be observed:
BUG: KASAN: slab-out-of-bounds in _parse_integer_limit+0x103/0x130 Read of size 1 at addr ffff88810121e3a1 by task test/447 CPU: 1 UID: 0 PID: 447 Comm: test Not tainted 6.17.0-rc6-dirty #288 PREEMPT(voluntary) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 Call Trace: <TASK> dump_stack_lvl+0x55/0x70 print_report+0xcb/0x610 kasan_report+0xb8/0xf0 _parse_integer_limit+0x103/0x130 bitmap_parselist+0x16d/0x6f0 osnoise_cpus_write+0x116/0x2d0 vfs_write+0x21e/0xcc0 ksys_write+0xee/0x1c0 do_syscall_64+0xa8/0x2a0 entry_SYSCALL_64_after_hwframe+0x77/0x7f </TASK>
This issue can be reproduced by below code:
const char *cpulist = "1";
int fd=open("/sys/kernel/debug/tracing/osnoise/cpus", O_WRONLY); write(fd, cpulist, strlen(cpulist));
Function bitmap_parselist() was called to parse cpulist, it require that the parameter 'buf' must be terminated with a '\0' or '\n'. Fix this issue by adding a '\0' to 'buf' in osnoise_cpus_write().
--- kernel/trace/trace_osnoise.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/trace/trace_osnoise.c +2 -1
@@ -2325,12 +2325,13 @@ osnoise_cpus_write(struct file *filp, const char __user *ubuf, size_t count,if (count <1 )return 0 ; - buf =kmalloc (count,GFP_KERNEL ); + buf =kmalloc (count +1 ,GFP_KERNEL );if (!buf)return -ENOMEM ;if (copy_from_user (buf, ubuf, count))return -EFAULT ; + buf[count] ='\0' ;if (!zalloc_cpumask_var (&osnoise_cpumask_new,GFP_KERNEL ))return -ENOMEM ;
Signature · 1 line
2.50.1
PATCH 2/3 tracing: dynevent: Add a missing lockdown check on dynevent
In reply to Steven RostedtFrom: "Masami Hiramatsu (Google)" <[email protected]>
Since dynamic_events interface on tracefs is compatible with kprobe_events and uprobe_events, it should also check the lockdown status and reject if it is set.
--- kernel/trace/trace_dynevent.c | 4 ++++ 1 file changed, 4 insertions(+)
kernel/trace/trace_dynevent.c +4 -0
@@ -230,6 +230,10 @@ static int dyn_event_open(struct inode *inode, struct file *file) {int ret; + ret =security_locked_down (LOCKDOWN_TRACEFS ); +if (ret) +return ret; + ret =tracing_check_open_get_tr (NULL );if (ret)return ret;
Signature · 1 line
2.50.1
PATCH 3/3 tracing: fgraph: Protect return handler from recursion loop
In reply to Steven RostedtFrom: "Masami Hiramatsu (Google)" <[email protected]>
function_graph_enter_regs() prevents itself from recursion by ftrace_test_recursion_trylock(), but __ftrace_return_to_handler(), which is called at the exit, does not prevent such recursion. Therefore, while it can prevent recursive calls from fgraph_ops::entryfunc(), it is not able to prevent recursive calls to fgraph from fgraph_ops::retfunc(), resulting in a recursive loop. This can lead an unexpected recursion bug reported by Menglong.
is_endbr() is called in __ftrace_return_to_handler -> fprobe_return
-> kprobe_multi_link_exit_handler -> is_endbr.
To fix this issue, acquire ftrace_test_recursion_trylock() in the __ftrace_return_to_handler() after unwind the shadow stack to mark this section must prevent recursive call of fgraph inside user-defined fgraph_ops::retfunc().
This is essentially a fix to commit 4346ba160409 ("fprobe: Rewrite fprobe on function-graph tracer"), because before that fgraph was only used from the function graph tracer. Fprobe allowed user to run any callbacks from fgraph after that commit.
--- kernel/trace/fgraph.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
kernel/trace/fgraph.c +12 -0
@@ -815,6 +815,7 @@ __ftrace_return_to_handler(struct ftrace_regs *fregs, unsigned long frame_pointeunsigned long bitmap;unsigned long ret;int offset; +int bit;int i; ret_stack =ftrace_pop_return_trace (&trace, &ret, frame_pointer, &offset);
@@ -829,6 +830,15 @@ __ftrace_return_to_handler(struct ftrace_regs *fregs, unsigned long frame_pointeif (fregs)ftrace_regs_set_instruction_pointer (fregs, ret); + bit =ftrace_test_recursion_trylock (trace.func, ret); +/* +* This can fail because ftrace_test_recursion_trylock() allows one nest +* call. If we are already in a nested call, then we don't probe this and +* just return the original return address. +*/ +if (unlikely (bit <0 )) + goto out; +#ifdef CONFIG_FUNCTION_GRAPH_RETVAL trace.retval =ftrace_regs_get_return_value (fregs);#endif
@@ -852,6 +862,8 @@ __ftrace_return_to_handler(struct ftrace_regs *fregs, unsigned long frame_pointe } } +ftrace_test_recursion_unlock (bit); +out:/* * The ftrace_graph_return() may still access the current * ret_stack structure, we need to make sure the update of
Signature · 1 line
2.50.1