• Petr Pavlu's avatar
    function_graph: Fix the ret_stack used by ftrace_graph_ret_addr() · 604b72b3
    Petr Pavlu authored
    When ftrace_graph_ret_addr() is invoked to convert a found stack return
    address to its original value, the function can end up producing the
    following crash:
    
    [   95.442712] BUG: kernel NULL pointer dereference, address: 0000000000000028
    [   95.442720] #PF: supervisor read access in kernel mode
    [   95.442724] #PF: error_code(0x0000) - not-present page
    [   95.442727] PGD 0 P4D 0-
    [   95.442731] Oops: Oops: 0000 [#1] PREEMPT SMP PTI
    [   95.442736] CPU: 1 UID: 0 PID: 2214 Comm: insmod Kdump: loaded Tainted: G           OE K    6.11.0-rc1-default #1 67c62a3b3720562f7e7db5f11c1fdb40b7a2857c
    [   95.442747] Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE, [K]=LIVEPATCH
    [   95.442750] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.2-3-gd478f380-rebuilt.opensuse.org 04/01/2014
    [   95.442754] RIP: 0010:ftrace_graph_ret_addr+0x42/0xc0
    [   95.442766] Code: [...]
    [   95.442773] RSP: 0018:ffff979b80ff7718 EFLAGS: 00010006
    [   95.442776] RAX: ffffffff8ca99b10 RBX: ffff979b80ff7760 RCX: ffff979b80167dc0
    [   95.442780] RDX: ffffffff8ca99b10 RSI: ffff979b80ff7790 RDI: 0000000000000005
    [   95.442783] RBP: 0000000000000001 R08: 0000000000000005 R09: 0000000000000000
    [   95.442786] R10: 0000000000000005 R11: 0000000000000000 R12: ffffffff8e9491e0
    [   95.442790] R13: ffffffff8d6f70f0 R14: ffff979b80167da8 R15: ffff979b80167dc8
    [   95.442793] FS:  00007fbf83895740(0000) GS:ffff8a0afdd00000(0000) knlGS:0000000000000000
    [   95.442797] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    [   95.442800] CR2: 0000000000000028 CR3: 0000000005070002 CR4: 0000000000370ef0
    [   95.442806] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
    [   95.442809] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
    [   95.442816] Call Trace:
    [   95.442823]  <TASK>
    [   95.442896]  unwind_next_frame+0x20d/0x830
    [   95.442905]  arch_stack_walk_reliable+0x94/0xe0
    [   95.442917]  stack_trace_save_tsk_reliable+0x7d/0xe0
    [   95.442922]  klp_check_and_switch_task+0x55/0x1a0
    [   95.442931]  task_call_func+0xd3/0xe0
    [   95.442938]  klp_try_switch_task.part.5+0x37/0x150
    [   95.442942]  klp_try_complete_transition+0x79/0x2d0
    [   95.442947]  klp_enable_patch+0x4db/0x890
    [   95.442960]  do_one_initcall+0x41/0x2e0
    [   95.442968]  do_init_module+0x60/0x220
    [   95.442975]  load_module+0x1ebf/0x1fb0
    [   95.443004]  init_module_from_file+0x88/0xc0
    [   95.443010]  idempotent_init_module+0x190/0x240
    [   95.443015]  __x64_sys_finit_module+0x5b/0xc0
    [   95.443019]  do_syscall_64+0x74/0x160
    [   95.443232]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
    [   95.443236] RIP: 0033:0x7fbf82f2c709
    [   95.443241] Code: [...]
    [   95.443247] RSP: 002b:00007fffd5ea3b88 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
    [   95.443253] RAX: ffffffffffffffda RBX: 000056359c48e750 RCX: 00007fbf82f2c709
    [   95.443257] RDX: 0000000000000000 RSI: 000056356ed4efc5 RDI: 0000000000000003
    [   95.443260] RBP: 000056356ed4efc5 R08: 0000000000000000 R09: 00007fffd5ea3c10
    [   95.443263] R10: 0000000000000003 R11: 0000000000000246 R12: 0000000000000000
    [   95.443267] R13: 000056359c48e6f0 R14: 0000000000000000 R15: 0000000000000000
    [   95.443272]  </TASK>
    [   95.443274] Modules linked in: [...]
    [   95.443385] Unloaded tainted modules: intel_uncore_frequency(E):1 isst_if_common(E):1 skx_edac(E):1
    [   95.443414] CR2: 0000000000000028
    
    The bug can be reproduced with kselftests:
    
     cd linux/tools/testing/selftests
     make TARGETS='ftrace livepatch'
     (cd ftrace; ./ftracetest test.d/ftrace/fgraph-filter.tc)
     (cd livepatch; ./test-livepatch.sh)
    
    The problem is that ftrace_graph_ret_addr() is supposed to operate on the
    ret_stack of a selected task but wrongly accesses the ret_stack of the
    current task. Specifically, the above NULL dereference occurs when
    task->curr_ret_stack is non-zero, but current->ret_stack is NULL.
    
    Correct ftrace_graph_ret_addr() to work with the right ret_stack.
    
    Cc: stable@vger.kernel.org
    Cc: Masami Hiramatsu <mhiramat@kernel.org>
    Cc: Mark Rutland <mark.rutland@arm.com>
    Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
    Reported-by: default avatarMiroslav Benes <mbenes@suse.cz>
    Link: https://lore.kernel.org/20240803131211.17255-1-petr.pavlu@suse.com
    Fixes: 7aa1eaef ("function_graph: Allow multiple users to attach to function graph")
    Signed-off-by: default avatarPetr Pavlu <petr.pavlu@suse.com>
    Signed-off-by: default avatarSteven Rostedt (Google) <rostedt@goodmis.org>
    604b72b3
fgraph.c 37.2 KB