From ca1b216ba92d007c1aa4aa1e46aa6270c8caadaf Mon Sep 17 00:00:00 2001 From: Rong Tao Date: Mon, 1 Jul 2024 21:51:10 +0800 Subject: [PATCH] codegen: Fix segfault of CodegenLLVM::generateProbe() If it is dummy, then the visit() operation should not be executed. For example, on aarch64, there is no syscalls:sys_{enter,exit}_open tracepoint, however, opensnoop.bt tool will try to attch them and visit args's field. We expect to get a warning, but instead we get a segmentation fault. As follows: $ sudo gdb bpftrace ... (gdb) set args opensnoop.bt (gdb) r opensnoop.bt:22-24: WARNING: tracepoint not found: syscalls:sys_enter_open opensnoop.bt:28-30: WARNING: tracepoint not found: syscalls:sys_exit_open Thread 1 "bpftrace" received signal SIGSEGV, Segmentation fault. 0x000000000052bbd8 in __gnu_cxx::__normal_iterator > >::__normal_iterator (this=0xffffffffb0b8, __i=) at /usr/include/c++/14/bits/stl_iterator.h:1068 1068 : _M_current(__i) { } (gdb) bt #0 0x000000000052bbd8 in __gnu_cxx::__normal_iterator > >::__normal_iterator (this=0xffffffffb0b8, __i=) at /usr/include/c++/14/bits/stl_iterator.h:1068 #1 0x0000000000525bdc in std::vector >::begin (this=0x10) at /usr/include/c++/14/bits/stl_vector.h:884 #2 0x000000000059ce8c in bpftrace::Struct::GetField (this=0x0, name="filename") at /home/rongtao/Git/bpftrace/bpftrace/src/struct.cpp:131 #3 0x00000000005a70a0 in bpftrace::SizedType::GetField (this=0xe9b998, name="filename") at /home/rongtao/Git/bpftrace/bpftrace/src/types.cpp:538 #4 0x00000000007c7178 in bpftrace::ast::CodegenLLVM::visit (this=0xffffffffc650, acc=...) at /home/rongtao/Git/bpftrace/bpftrace/src/ast/passes/codegen_llvm.cpp:1973 #5 0x0000000000847db0 in bpftrace::ast::FieldAccess::accept (this=0xe9be30, v=...) at /home/rongtao/Git/bpftrace/bpftrace/src/ast/ast.cpp:31 #6 0x00000000007d2404 in bpftrace::ast::CodegenLLVM::accept (this=0xffffffffc650, node=0xe9be30) at /home/rongtao/Git/bpftrace/bpftrace/src/ast/passes/codegen_llvm.cpp:3778 #7 0x00000000007c8bec in bpftrace::ast::CodegenLLVM::visit (this=0xffffffffc650, assignment=...) at /home/rongtao/Git/bpftrace/bpftrace/src/ast/passes/codegen_llvm.cpp:2218 #8 0x0000000000847eb4 in bpftrace::ast::AssignMapStatement::accept (this=0xffffe4429250, v=...) at /home/rongtao/Git/bpftrace/bpftrace/src/ast/ast.cpp:36 #9 0x00000000007d2404 in bpftrace::ast::CodegenLLVM::accept (this=0xffffffffc650, node=0xffffe4429250) at /home/rongtao/Git/bpftrace/bpftrace/src/ast/passes/codegen_llvm.cpp:3778 #10 0x00000000007ca4c4 in bpftrace::ast::CodegenLLVM::generateProbe (this=0xffffffffc650, probe=..., full_func_id="dummy", name="dummy", func_type=0xff2b50, usdt_location_index=std::optional [no contained value], dummy=true) at /home/rongtao/Git/bpftrace/bpftrace/src/ast/passes/codegen_llvm.cpp:2539 #11 0x00000000007cb4e4 in bpftrace::ast::CodegenLLVM::visit (this=0xffffffffc650, probe=...) at /home/rongtao/Git/bpftrace/bpftrace/src/ast/passes/codegen_llvm.cpp:2734 #12 0x00000000008480f0 in bpftrace::ast::Probe::accept (this=0xffffe4427650, v=...) at /home/rongtao/Git/bpftrace/bpftrace/src/ast/ast.cpp:47 #13 0x00000000007d2404 in bpftrace::ast::CodegenLLVM::accept (this=0xffffffffc650, node=0xffffe4427650) at /home/rongtao/Git/bpftrace/bpftrace/src/ast/passes/codegen_llvm.cpp:3778 #14 0x00000000007cb7a4 in bpftrace::ast::CodegenLLVM::visit (this=0xffffffffc650, program=...) at /home/rongtao/Git/bpftrace/bpftrace/src/ast/passes/codegen_llvm.cpp:2752 #15 0x000000000084818c in bpftrace::ast::Program::accept (this=0xe90f50, v=...) at /home/rongtao/Git/bpftrace/bpftrace/src/ast/ast.cpp:50 #16 0x00000000007d2404 in bpftrace::ast::CodegenLLVM::accept (this=0xffffffffc650, node=0xe90f50) at /home/rongtao/Git/bpftrace/bpftrace/src/ast/passes/codegen_llvm.cpp:3778 #17 0x00000000007d03fc in bpftrace::ast::CodegenLLVM::generate_ir (this=0xffffffffc650) at /home/rongtao/Git/bpftrace/bpftrace/src/ast/passes/codegen_llvm.cpp:3450 #18 0x0000000000478138 in main (argc=2, argv=0xfffffffff4c8) at /home/rongtao/Git/bpftrace/bpftrace/src/main.cpp:898 We can simplify opensnoop.bt to: tracepoint:syscalls:sys_enter_open_not_exist, tracepoint:syscalls:sys_enter_openat { @ = args.filename; } This will produce the following error: stdin:1:1-45: WARNING: tracepoint not found: syscalls:sys_enter_open_not_exist tracepoint:syscalls:sys_enter_open_not_exist,tracepoint:syscalls:sys_enter_openat {@ = args.filename;} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Segmentation fault We need to generate the dummy probe only for cases when none of the probe attach points exists. Link: https://github.com/bpftrace/bpftrace/pull/3274 Signed-off-by: Viktor Malik Signed-off-by: Rong Tao --- CHANGELOG.md | 2 ++ src/ast/passes/codegen_llvm.cpp | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a92f5e792858..8816d6d35b29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,8 @@ and this project adheres to - Remove the `-dd` CLI option - [#3203](https://github.com/bpftrace/bpftrace/pull/3203) #### Fixed +- Fix segfault for multi-tracepoint probes + - [#3274](https://github.com/bpftrace/bpftrace/pull/3274) #### Security #### Docs - Remove mention of unsupported character literals diff --git a/src/ast/passes/codegen_llvm.cpp b/src/ast/passes/codegen_llvm.cpp index dfc1f66e260f..c48f0dd5fa26 100644 --- a/src/ast/passes/codegen_llvm.cpp +++ b/src/ast/passes/codegen_llvm.cpp @@ -2710,6 +2710,7 @@ void CodegenLLVM::visit(Probe &probe) // We begin by saving state that gets changed by the codegen pass, so we // can restore it for the next pass (printf_id_, time_id_). auto reset_ids = async_ids_.create_reset_ids(); + bool generated = false; for (auto *attach_point : *probe.attach_points) { reset_ids(); current_attach_point_ = attach_point; @@ -2739,16 +2740,18 @@ void CodegenLLVM::visit(Probe &probe) auto match_ap = attach_point->create_expansion_copy(match); add_probe(match_ap, probe, match, func_type); - } - if (matches.empty()) { - generateProbe(probe, "dummy", "dummy", func_type, std::nullopt, true); + generated = true; } } else { if (probe.index() == 0) probe.set_index(getNextIndexForProbe()); add_probe(*attach_point, probe, attach_point->name(), func_type); + generated = true; } } + if (!generated) { + generateProbe(probe, "dummy", "dummy", func_type, std::nullopt, true); + } current_attach_point_ = nullptr; }