Skip to content

in_ebpf: add tcp trace#11646

Open
cosmo0920 wants to merge 4 commits intomasterfrom
cosmo0920-add-tcp-ebpf-trace
Open

in_ebpf: add tcp trace#11646
cosmo0920 wants to merge 4 commits intomasterfrom
cosmo0920-add-tcp-ebpf-trace

Conversation

@cosmo0920
Copy link
Copy Markdown
Contributor

@cosmo0920 cosmo0920 commented Apr 1, 2026

TCP/IP also provides eBPF entrypoints so we can provide this type of traces.
At first, we can provide connect, accept/accept4, and listen.


Enter [N/A] in the box, if an item is not applicable to your change.

Testing
Before we can approve your change; please submit the following in a comment:

  • Example configuration file for the change
% sudo bin/fluent-bit -i ebpf -ptrace=trace_tcp -o stdout -v 
  • Debug log output from testing the change
Fluent Bit v5.0.2
* Copyright (C) 2015-2026 The Fluent Bit Authors
* Fluent Bit is a CNCF graduated project under the Fluent organization
* https://fluentbit.io

______ _                  _    ______ _ _           _____  _____ 
|  ___| |                | |   | ___ (_) |         |  ___||  _  |
| |_  | |_   _  ___ _ __ | |_  | |_/ /_| |_  __   _|___ \ | |/' |
|  _| | | | | |/ _ \ '_ \| __| | ___ \ | __| \ \ / /   \ \|  /| |
| |   | | |_| |  __/ | | | |_  | |_/ / | |_   \ V //\__/ /\ |_/ /
\_|   |_|\__,_|\___|_| |_|\__| \____/|_|\__|   \_/ \____(_)\___/


[2026/04/01 18:26:31.026] [ info] Configuration:
[2026/04/01 18:26:31.026] [ info]  flush time     | 1.000000 seconds
[2026/04/01 18:26:31.026] [ info]  grace          | 5 seconds
[2026/04/01 18:26:31.026] [ info]  daemon         | 0
[2026/04/01 18:26:31.027] [ info] ___________
[2026/04/01 18:26:31.027] [ info]  inputs:
[2026/04/01 18:26:31.027] [ info]      ebpf
[2026/04/01 18:26:31.027] [ info] ___________
[2026/04/01 18:26:31.027] [ info]  filters:
[2026/04/01 18:26:31.027] [ info] ___________
[2026/04/01 18:26:31.027] [ info]  outputs:
[2026/04/01 18:26:31.027] [ info]      stdout.0
[2026/04/01 18:26:31.027] [ info] ___________
[2026/04/01 18:26:31.027] [ info]  collectors:
[2026/04/01 18:26:31.027] [ info] [fluent bit] version=5.0.2, commit=4b13f75267, pid=2670859
[2026/04/01 18:26:31.027] [debug] [engine] coroutine stack size: 24576 bytes (24.0K)
[2026/04/01 18:26:31.027] [ info] [storage] ver=1.5.4, type=memory, sync=normal, checksum=off, max_chunks_up=128
[2026/04/01 18:26:31.027] [ info] [simd    ] SSE2
[2026/04/01 18:26:31.027] [ info] [cmetrics] version=2.1.1
[2026/04/01 18:26:31.027] [ info] [ctraces ] version=0.7.1
[2026/04/01 18:26:31.027] [ info] [input:ebpf:ebpf.0] initializing
[2026/04/01 18:26:31.027] [ info] [input:ebpf:ebpf.0] storage_strategy='memory' (memory only)
[2026/04/01 18:26:31.027] [debug] [ebpf:ebpf.0] created event channels: read=21 write=22
[2026/04/01 18:26:31.027] [debug] [input:ebpf:ebpf.0] initializing eBPF input plugin
[2026/04/01 18:26:31.027] [debug] [input:ebpf:ebpf.0] processing trace: trace_tcp
[2026/04/01 18:26:31.027] [debug] [input:ebpf:ebpf.0] setting up trace configuration for: trace_tcp
[2026/04/01 18:26:31.050] [debug] [input:ebpf:ebpf.0] attaching BPF program for trace: trace_tcp
[2026/04/01 18:26:31.052] [debug] [input:ebpf:ebpf.0] registering trace handler for: trace_tcp
[2026/04/01 18:26:31.052] [ info] [input:ebpf:ebpf.0] registered trace handler for: trace_tcp
[2026/04/01 18:26:31.052] [ info] [input:ebpf:ebpf.0] trace configuration completed for: trace_tcp
[2026/04/01 18:26:31.052] [debug] [input:ebpf:ebpf.0] setting up collector with poll interval: 1000 ms
[2026/04/01 18:26:31.052] [ info] [input:ebpf:ebpf.0] eBPF input plugin initialized successfully
[2026/04/01 18:26:31.053] [debug] [stdout:stdout.0] created event channels: read=57 write=58
[2026/04/01 18:26:31.063] [ info] [sp] stream processor started
[2026/04/01 18:26:31.063] [ info] [output:stdout:stdout.0] worker #0 started
[2026/04/01 18:26:31.063] [ info] [engine] Shutdown Grace Period=5, Shutdown Input Grace Period=2
[2026/04/01 18:26:31.480] [debug] [input:ebpf:ebpf.0] collecting events from ring buffers
[2026/04/01 18:26:31.480] [debug] [input:ebpf:ebpf.0] consuming events from ring buffer trace_tcp
[2026/04/01 18:26:31.480] [debug] [input:ebpf:ebpf.0] successfully consumed events from ring buffer trace_tcp
[2026/04/01 18:26:32.480] [debug] [task] created task=0x7f120807a8f0 id=0 OK
[2026/04/01 18:26:32.480] [debug] [output:stdout:stdout.0] task_id=0 assigned to thread #0
[2026/04/01 18:26:32.480] [debug] [input:ebpf:ebpf.0] collecting events from ring buffers
[2026/04/01 18:26:32.480] [debug] [input:ebpf:ebpf.0] consuming events from ring buffer trace_tcp
[0] ebpf.0: [[1775035591.480677377, {}], {"event_type"=>"connect", "pid"=>2670863, "tid"=>2670863, "comm"=>"(sd-bright)", "fd"=>3, "remote_port"=>0, "remote_version"=>0, "remote_addr_v4"=>0, "error_raw"=>0}]
[2026/04/01 18:26:32.480] [debug] [out flush] cb_destroy coro_id=0
[2026/04/01 18:26:32.480] [debug] [input:ebpf:ebpf.0] successfully consumed events from ring buffer trace_tcp
[2026/04/01 18:26:32.480] [debug] [task] destroy task=0x7f120807a8f0 (task_id=0)
[2026/04/01 18:26:33.480] [debug] [task] created task=0x7f120803a7e0 id=0 OK
[2026/04/01 18:26:33.480] [debug] [output:stdout:stdout.0] task_id=0 assigned to thread #0
[2026/04/01 18:26:33.480] [debug] [input:ebpf:ebpf.0] collecting events from ring buffers
[2026/04/01 18:26:33.480] [debug] [input:ebpf:ebpf.0] consuming events from ring buffer trace_tcp
[0] ebpf.0: [[1775035592.480762088, {}], {"event_type"=>"connect", "pid"=>2487426, "tid"=>2487426, "comm"=>"ibus-engine-moz", "fd"=>12, "remote_port"=>0, "remote_version"=>0, "remote_addr_v4"=>0, "error_raw"=>0}]
[1] ebpf.0: [[1775035592.480830521, {}], {"event_type"=>"connect", "pid"=>2487426, "tid"=>2487426, "comm"=>"ibus-engine-moz", "fd"=>12, "remote_port"=>0, "remote_version"=>0, "remote_addr_v4"=>0, "error_raw"=>0}]
[2] ebpf.0: [[1775035592.480866189, {}], {"event_type"=>"accept", "pid"=>2487536, "tid"=>2487543, "comm"=>"IPCServer", "fd"=>4, "new_fd"=>6, "peer_port"=>0, "peer_version"=>0, "peer_addr_v4"=>0, "error_raw"=>0}]
[3] ebpf.0: [[1775035592.480880374, {}], {"event_type"=>"connect", "pid"=>2487426, "tid"=>2487426, "comm"=>"ibus-engine-moz", "fd"=>12, "remote_port"=>0, "remote_version"=>0, "remote_addr_v4"=>0, "error_raw"=>0}]
[4] ebpf.0: [[1775035592.480892161, {}], {"event_type"=>"accept", "pid"=>2487536, "tid"=>2487543, "comm"=>"IPCServer", "fd"=>4, "new_fd"=>6, "peer_port"=>0, "peer_version"=>0, "peer_addr_v4"=>0, "error_raw"=>0}]
[5] ebpf.0: [[1775035592.480904143, {}], {"event_type"=>"connect", "pid"=>2487426, "tid"=>2487426, "comm"=>"ibus-engine-moz", "fd"=>12, "remote_port"=>0, "remote_version"=>0, "remote_addr_v4"=>0, "error_raw"=>0}]
[6] ebpf.0: [[1775035592.480914692, {}], {"event_type"=>"accept", "pid"=>2487536, "tid"=>2487543, "comm"=>"IPCServer", "fd"=>4, "new_fd"=>6, "peer_port"=>0, "peer_version"=>0, "peer_addr_v4"=>0, "error_raw"=>0}]
[2026/04/01 18:26:33.480] [debug] [input:ebpf:ebpf.0] successfully consumed events from ring buffer trace_tcp
[2026/04/01 18:26:33.480] [debug] [out flush] cb_destroy coro_id=1
[2026/04/01 18:26:33.480] [debug] [task] destroy task=0x7f120803a7e0 (task_id=0)
[2026/04/01 18:26:34.480] [debug] [task] created task=0x7f120803ab50 id=0 OK
[2026/04/01 18:26:34.480] [debug] [output:stdout:stdout.0] task_id=0 assigned to thread #0
[2026/04/01 18:26:34.480] [debug] [input:ebpf:ebpf.0] collecting events from ring buffers
[2026/04/01 18:26:34.480] [debug] [input:ebpf:ebpf.0] consuming events from ring buffer trace_tcp
[0] ebpf.0: [[1775035593.480442229, {}], {"event_type"=>"connect", "pid"=>2670864, "tid"=>2670864, "comm"=>"(sd-bright)", "fd"=>3, "remote_port"=>0, "remote_version"=>0, "remote_addr_v4"=>0, "error_raw"=>0}]
[1] ebpf.0: [[1775035593.480493369, {}], {"event_type"=>"connect", "pid"=>2489959, "tid"=>2649284, "comm"=>"DNS Res~ver #37", "fd"=>120, "remote_port"=>53, "remote_version"=>4, "remote_addr_v4"=>889192575, "error_raw"=>0}]
[2] ebpf.0: [[1775035593.480499655, {}], {"event_type"=>"connect", "pid"=>2587146, "tid"=>2587146, "comm"=>"systemd-resolve", "fd"=>21, "remote_port"=>53, "remote_version"=>6, "remote_addr_v6_0"=>33022, "remote_addr_v6_1"=>0, "remote_addr_v6_2"=>4283103474, "remote_addr_v6_3"=>1620279806, "error_raw"=>0}]
[3] ebpf.0: [[1775035593.480504896, {}], {"event_type"=>"connect", "pid"=>2670865, "tid"=>2670865, "comm"=>"(sd-bright)", "fd"=>3, "remote_port"=>0, "remote_version"=>0, "remote_addr_v4"=>0, "error_raw"=>0}]
[2026/04/01 18:26:34.480] [debug] [input:ebpf:ebpf.0] successfully consumed events from ring buffer trace_tcp
[2026/04/01 18:26:34.480] [debug] [out flush] cb_destroy coro_id=2
[2026/04/01 18:26:34.480] [debug] [task] destroy task=0x7f120803ab50 (task_id=0)
[2026/04/01 18:26:35.480] [debug] [task] created task=0x7f120803ad20 id=0 OK
[2026/04/01 18:26:35.480] [debug] [output:stdout:stdout.0] task_id=0 assigned to thread #0
[0] ebpf.0: [[1775035594.480375066, {}], {"event_type"=>"connect", "pid"=>2670868, "tid"=>2670868, "comm"=>"(sd-bright)", "fd"=>3, "remote_port"=>0, "remote_version"=>0, "remote_addr_v4"=>0, "error_raw"=>0}]
[2026/04/01 18:26:35.480] [debug] [input:ebpf:ebpf.0] collecting events from ring buffers
[2026/04/01 18:26:35.480] [debug] [input:ebpf:ebpf.0] consuming events from ring buffer trace_tcp
[1] ebpf.0: [[1775035594.480410451, {}], {"event_type"=>"connect", "pid"=>2487426, "tid"=>2487426, "comm"=>"ibus-engine-moz", "fd"=>12, "remote_port"=>0, "remote_version"=>0, "remote_addr_v4"=>0, "error_raw"=>0}]
[2026/04/01 18:26:35.480] [debug] [input:ebpf:ebpf.0] successfully consumed events from ring buffer trace_tcp
[2] ebpf.0: [[1775035594.480417195, {}], {"event_type"=>"accept", "pid"=>2487536, "tid"=>2487543, "comm"=>"IPCServer", "fd"=>4, "new_fd"=>6, "peer_port"=>0, "peer_version"=>0, "peer_addr_v4"=>0, "error_raw"=>0}]
[3] ebpf.0: [[1775035594.480422698, {}], {"event_type"=>"connect", "pid"=>2487426, "tid"=>2487426, "comm"=>"ibus-engine-moz", "fd"=>12, "remote_port"=>0, "remote_version"=>0, "remote_addr_v4"=>0, "error_raw"=>0}]
[4] ebpf.0: [[1775035594.480427614, {}], {"event_type"=>"accept", "pid"=>2487536, "tid"=>2487543, "comm"=>"IPCServer", "fd"=>4, "new_fd"=>6, "peer_port"=>0, "peer_version"=>0, "peer_addr_v4"=>0, "error_raw"=>0}]
[2026/04/01 18:26:35.481] [debug] [out flush] cb_destroy coro_id=3
[2026/04/01 18:26:35.481] [debug] [task] destroy task=0x7f120803ad20 (task_id=0)
[2026/04/01 18:26:36.480] [debug] [task] created task=0x7f120803ad20 id=0 OK
[2026/04/01 18:26:36.480] [debug] [output:stdout:stdout.0] task_id=0 assigned to thread #0
[0] ebpf.0: [[1775035595.480812866, {}], {"event_type"=>"connect", "pid"=>2489959, "tid"=>2490048, "comm"=>"Socket Thread", "fd"=>165, "remote_port"=>443, "remote_version"=>4, "remote_addr_v4"=>3952361644, "error_raw"=>115}]
[2026/04/01 18:26:36.480] [debug] [input:ebpf:ebpf.0] collecting events from ring buffers
[2026/04/01 18:26:36.480] [debug] [input:ebpf:ebpf.0] consuming events from ring buffer trace_tcp
[1] ebpf.0: [[1775035595.480884739, {}], {"event_type"=>"connect", "pid"=>2670870, "tid"=>2670870, "comm"=>"(sd-bright)", "fd"=>3, "remote_port"=>0, "remote_version"=>0, "remote_addr_v4"=>0, "error_raw"=>0}]
[2026/04/01 18:26:36.480] [debug] [input:ebpf:ebpf.0] successfully consumed events from ring buffer trace_tcp
[2026/04/01 18:26:36.480] [debug] [out flush] cb_destroy coro_id=4
[2026/04/01 18:26:36.480] [debug] [task] destroy task=0x7f120803ad20 (task_id=0)
[2026/04/01 18:26:37.480] [debug] [task] created task=0x7f120803ad20 id=0 OK
[0] ebpf.0: [[1775035596.480520962, {}], {"event_type"=>"connect", "pid"=>2670872, "tid"=>2670872, "comm"=>"(sd-bright)", "fd"=>3, "remote_port"=>0, "remote_version"=>0, "remote_addr_v4"=>0, "error_raw"=>0}]
[2026/04/01 18:26:37.480] [debug] [output:stdout:stdout.0] task_id=0 assigned to thread #0
[2026/04/01 18:26:37.480] [debug] [input:ebpf:ebpf.0] collecting events from ring buffers
[2026/04/01 18:26:37.480] [debug] [input:ebpf:ebpf.0] consuming events from ring buffer trace_tcp
[2026/04/01 18:26:37.480] [debug] [input:ebpf:ebpf.0] successfully consumed events from ring buffer trace_tcp
[2026/04/01 18:26:37.480] [debug] [out flush] cb_destroy coro_id=5
[2026/04/01 18:26:37.480] [debug] [task] destroy task=0x7f120803ad20 (task_id=0)
^C[2026/04/01 18:26:38] [engine] caught signal (SIGINT)
[0] ebpf.0: [[1775035597.480450608, {}], {"event_type"=>"connect", "pid"=>2670873, "tid"=>2670873, "comm"=>"(sd-bright)", "fd"=>3, "remote_port"=>0, "remote_version"=>0, "remote_addr_v4"=>0, "error_raw"=>0}]
[2026/04/01 18:26:38.170] [debug] [task] created task=0x7f120803acd0 id=0 OK
[2026/04/01 18:26:38.170] [debug] [output:stdout:stdout.0] task_id=0 assigned to thread #0
[2026/04/01 18:26:38.170] [ warn] [engine] service will shutdown in max 5 seconds
[2026/04/01 18:26:38.170] [debug] [engine] task 0 already scheduled to run, not re-scheduling it.
[2026/04/01 18:26:38.170] [ info] [engine] pausing all inputs..
[2026/04/01 18:26:38.170] [ info] [input] pausing ebpf.0
[2026/04/01 18:26:38.170] [debug] [input:ebpf:ebpf.0] collector paused
[2026/04/01 18:26:38.170] [debug] [out flush] cb_destroy coro_id=6
[2026/04/01 18:26:38.170] [debug] [task] destroy task=0x7f120803acd0 (task_id=0)
[2026/04/01 18:26:38.480] [ info] [engine] service has stopped (0 pending tasks)
[2026/04/01 18:26:38.480] [ info] [input] pausing ebpf.0
[2026/04/01 18:26:38.480] [debug] [input:ebpf:ebpf.0] collector paused
[2026/04/01 18:26:38.480] [ info] [output:stdout:stdout.0] thread worker #0 stopping...
[2026/04/01 18:26:38.480] [ info] [output:stdout:stdout.0] thread worker #0 stopped
[2026/04/01 18:26:38.782] [ info] [input:ebpf:ebpf.0] eBPF input plugin exited
  • Attached Valgrind output that shows no leaks or memory corruption was found
==2655783== 
==2655783== HEAP SUMMARY:
==2655783==     in use at exit: 0 bytes in 0 blocks
==2655783==   total heap usage: 3,820 allocs, 3,820 frees, 17,135,287 bytes allocated
==2655783== 
==2655783== All heap blocks were freed -- no leaks are possible
==2655783== 
==2655783== Use --track-origins=yes to see where uninitialised values come from
==2655783== For lists of detected and suppressed errors, rerun with: -s
==2655783== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

If this is a change to packaging of containers or native binaries then please confirm it works for all targets.

  • Run local packaging test showing all targets (including any new ones) build.
  • Set ok-package-test label to test for all targets (requires maintainer to do).

Documentation

  • Documentation required for this feature

Backporting

  • Backport to latest stable release.

Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.

Summary by CodeRabbit

  • New Features

    • Added TCP syscall tracing for listen, accept and connect with event emission.
  • Improvements

    • Added TCP event types and human-readable labels; richer payloads (fd, backlog/new_fd, peer/remote addresses, error).
    • Enhanced resource lifecycle handling and conditional cleanup during init/exit to avoid leaks on failures.
  • Tests

    • Added runtime tests validating TCP event encoding for IPv4 and IPv6 and handler behavior.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0220375130

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 1, 2026

📝 Walkthrough

Walkthrough

Adds TCP tracing to the in_ebpf plugin: new TCP event types and payloads, a TCP eBPF tracepoint program capturing listen/accept/connect, handler/encoder to emit Fluent Bit records, trace context updates to track eBPF skeletons, and runtime tests for encoding.

Changes

Cohort / File(s) Summary
Trace registration & lifecycle
plugins/in_ebpf/in_ebpf.c
trace_register() signature extended to accept/store skel and skel_destroy; trace setup/teardown paths now destroy stored skeletons when present; error paths free ring buffers and destroy skeletons; Trace description updated to include tcp.
Core trace types & encoder
plugins/in_ebpf/traces/includes/common/events.h, plugins/in_ebpf/traces/includes/common/encoder.h
Added EVENT_TYPE_LISTEN/ACCEPT/CONNECT, tcp_addr and per-event structs; extended event.details union; event_type_to_string() now maps new types to "listen", "accept", "connect".
TCP eBPF program
plugins/in_ebpf/traces/tcp/bpf.c
New tracepoint enter/exit handlers for listen/accept/accept4/connect; per-thread maps to correlate entry/exit; parses sockaddrs, sets error_raw, emits structured events via events map; license added.
TCP handler & header
plugins/in_ebpf/traces/tcp/handler.c, plugins/in_ebpf/traces/tcp/handler.h
New trace_tcp_handler() and encode_tcp_event() to validate and serialize TCP events into Fluent Bit log records (LISTEN/ACCEPT/CONNECT); encoder writes IPv4/IPv6 address fields.
Trace context wiring
plugins/in_ebpf/traces/traces.h
struct trace_context now stores void *skel and trace_skel_destroy_func_t skel_destroy; includes TCP skeleton header and adds DEFINE_GET_BPF_OBJECT(trace_tcp).
Tests & CI wiring
tests/runtime/CMakeLists.txt, tests/runtime/in_ebpf_tcp_handler.c
Added runtime test target and test file exercising TCP event encoding (LISTEN/ACCEPT/CONNECT) across IPv4/IPv6 scenarios.

Sequence Diagram

sequenceDiagram
    participant Kernel as Kernel (eBPF)
    participant Maps as Maps / Events Buffer
    participant Handler as TCP Handler
    participant Encoder as Log Encoder
    participant FB as Fluent Bit

    Kernel->>Maps: save per-thread syscall args (enter)
    Kernel->>Maps: reserve & submit event (exit)
    Handler->>Maps: consume event
    Handler->>Handler: validate & dispatch by event type
    Handler->>Encoder: encode_tcp_event(ev)
    Encoder->>FB: commit encoded record
    FB->>FB: append to input buffer
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • edsiper

Poem

🐰 I hopped through syscalls, sniffed ports in the night,

I gathered peers and ports and shaped them just right.
From maps to encoder, a padded log bouquet,
I hopped, I encoded, and sent them on their way. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'in_ebpf: add tcp trace' directly and clearly summarizes the main change: adding TCP trace support to the eBPF input plugin.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cosmo0920-add-tcp-ebpf-trace

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
plugins/in_ebpf/traces/tcp/handler.h (1)

8-10: Missing include for struct event forward declaration.

The encode_tcp_event function declaration uses const struct event *ev, but this header does not include events.h or provide a forward declaration for struct event. This could cause compilation errors if this header is included before events.h.

♻️ Proposed fix
 `#include` <fluent-bit/flb_input_plugin.h>
 `#include` <fluent-bit/flb_log_event_encoder.h>
+
+#include "common/events.h"
 
 int trace_tcp_handler(void *ctx, void *data, size_t data_sz);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/in_ebpf/traces/tcp/handler.h` around lines 8 - 10, The header
declares encode_tcp_event(...) with a parameter const struct event *ev but
doesn't provide a forward declaration or include for struct event, which can
cause compile errors; fix by adding a forward declaration "struct event;" at the
top of this header (or include the header that defines it, e.g., events.h) so
encode_tcp_event's prototype is valid when this file is included.
plugins/in_ebpf/traces/tcp/handler.c (1)

11-49: Consider making the addr parameter const.

The encode_tcp_addr function does not modify the tcp_addr structure, but the parameter is not declared const. This creates a const-correctness issue when called with addresses from a const struct event * (lines 98 and 113 cast away const).

♻️ Proposed fix
 static int encode_tcp_addr(struct flb_log_event_encoder *log_encoder,
                            const char *key_prefix,
-                           struct tcp_addr *addr)
+                           const struct tcp_addr *addr)
 {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/in_ebpf/traces/tcp/handler.c` around lines 11 - 49, Change the
encode_tcp_addr signature to take a pointer-to-const (i.e., make the addr
parameter "const struct tcp_addr *addr") and update its implementation
accordingly; then remove the casts at call sites that currently cast away const
(calls passing (struct tcp_addr *) should pass the const pointer directly).
Ensure any prototype/declaration for encode_tcp_addr is updated to match
(function name encode_tcp_addr) so callers (previously casting away const)
compile without const casts.
plugins/in_ebpf/traces/tcp/bpf.c (1)

160-173: Confirm reserved struct event records start zeroed.

These exit handlers submit sizeof(*event) but only populate the active union member. If gadget_reserve_buf() behaves like a normal ring-buffer reserve, unused union/padding bytes—and details.accept.peer on failed accepts or NULL peer buffers—can carry stale data into user space. Clearing the record, or at least the active payload, makes this safe regardless of helper semantics.

🧹 Safer fill pattern
     event = gadget_reserve_buf(&events, sizeof(*event));
     if (!event) {
         bpf_map_delete_elem(&accepts, &tid);
         return 0;
     }

+    __builtin_memset(event, 0, sizeof(*event));
     fill_common(event, args->mntns_id);

Also applies to: 219-235, 308-321

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/in_ebpf/traces/tcp/bpf.c` around lines 160 - 173, The reserved event
record returned by gadget_reserve_buf may contain stale union/padding
bytes—ensure the record is zeroed before populating only the active union
member: after calling gadget_reserve_buf(&events, sizeof(*event)) and before
fill_common(), explicitly zero the reserved memory for *event (or at minimum
zero the specific active payload such as event->details.listen and
event->details.accept.peer) so no stale data is submitted; update the same
pattern around the other exit handlers that call gadget_reserve_buf and
gadget_submit_buf (refer to gadget_reserve_buf, fill_common, gadget_submit_buf
and the event->details.* union usage).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/in_ebpf/traces/tcp/bpf.c`:
- Around line 35-40: parse_sockaddr() currently reads full sockaddr structures
without respecting the syscall-provided length and uses an
uninitialized/unchecked family value; fix by reading and saving the
user-supplied length from accept_args.upeer_addrlen at syscall entry (store it
in the per-CPU/map context used for exit handling), initialize and set 'family'
only after a successful bpf_probe_read_user() call (check return and bail/mark
failure if it fails), and then pass that saved length into parse_sockaddr() so
it bounds reads to the user buffer size; ensure every
bpf_probe_read_user()/bpf_probe_read() return is checked and handle errors by
skipping parsing or using a safe default (e.g., AF_UNSPEC) so no over-reads
occur.

---

Nitpick comments:
In `@plugins/in_ebpf/traces/tcp/bpf.c`:
- Around line 160-173: The reserved event record returned by gadget_reserve_buf
may contain stale union/padding bytes—ensure the record is zeroed before
populating only the active union member: after calling
gadget_reserve_buf(&events, sizeof(*event)) and before fill_common(), explicitly
zero the reserved memory for *event (or at minimum zero the specific active
payload such as event->details.listen and event->details.accept.peer) so no
stale data is submitted; update the same pattern around the other exit handlers
that call gadget_reserve_buf and gadget_submit_buf (refer to gadget_reserve_buf,
fill_common, gadget_submit_buf and the event->details.* union usage).

In `@plugins/in_ebpf/traces/tcp/handler.c`:
- Around line 11-49: Change the encode_tcp_addr signature to take a
pointer-to-const (i.e., make the addr parameter "const struct tcp_addr *addr")
and update its implementation accordingly; then remove the casts at call sites
that currently cast away const (calls passing (struct tcp_addr *) should pass
the const pointer directly). Ensure any prototype/declaration for
encode_tcp_addr is updated to match (function name encode_tcp_addr) so callers
(previously casting away const) compile without const casts.

In `@plugins/in_ebpf/traces/tcp/handler.h`:
- Around line 8-10: The header declares encode_tcp_event(...) with a parameter
const struct event *ev but doesn't provide a forward declaration or include for
struct event, which can cause compile errors; fix by adding a forward
declaration "struct event;" at the top of this header (or include the header
that defines it, e.g., events.h) so encode_tcp_event's prototype is valid when
this file is included.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3eab3cf1-426f-4cd1-b00b-f631f0b92bf2

📥 Commits

Reviewing files that changed from the base of the PR and between 66ffbe4 and f0c81cc.

📒 Files selected for processing (9)
  • plugins/in_ebpf/in_ebpf.c
  • plugins/in_ebpf/traces/includes/common/encoder.h
  • plugins/in_ebpf/traces/includes/common/events.h
  • plugins/in_ebpf/traces/tcp/bpf.c
  • plugins/in_ebpf/traces/tcp/handler.c
  • plugins/in_ebpf/traces/tcp/handler.h
  • plugins/in_ebpf/traces/traces.h
  • tests/runtime/CMakeLists.txt
  • tests/runtime/in_ebpf_tcp_handler.c

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
plugins/in_ebpf/traces/tcp/bpf.c (1)

88-123: ⚠️ Potential issue | 🟠 Major

parse_sockaddr() still has issues flagged in prior review: uninitialized family and unchecked bpf_probe_read_user return.

The family variable at line 91 is declared but not explicitly initialized. If bpf_probe_read_user at line 103 fails, family contains undefined stack data, leading to incorrect address-family detection. The return value of bpf_probe_read_user should be checked.

Additionally, the function reads full sockaddr_in/sockaddr_in6 structures without consulting the user-provided address length, which could cause over-reads when the buffer is smaller than the structure size.

🐛 Proposed fix for initialization and error checking
 static __always_inline void parse_sockaddr(const struct sockaddr *addr,
                                            struct tcp_addr *out)
 {
-    sa_family_t family;
+    sa_family_t family = 0;
+    int ret;

     if (!out) {
         return;
     }

     __builtin_memset(out, 0, sizeof(*out));

     if (!addr) {
         return;
     }

-    bpf_probe_read_user(&family, sizeof(family), &addr->sa_family);
+    ret = bpf_probe_read_user(&family, sizeof(family), &addr->sa_family);
+    if (ret < 0) {
+        return;  /* leave out zeroed */
+    }

     if (family == AF_INET) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/in_ebpf/traces/tcp/bpf.c` around lines 88 - 123, parse_sockaddr
leaves family uninitialized and ignores bpf_probe_read_user return values and
potential user buffer sizes; fix by initializing sa_family_t family = 0,
checking the return of bpf_probe_read_user when reading &addr->sa_family and
returning early on error, and similarly check returns when reading the full
sockaddr_in/sockaddr_in6 into local in4/in6; to avoid over-reads add an argument
for the user buffer length (e.g., socklen_t addr_len) or otherwise use a safe
length check and only probe_read_user up to min(addr_len, sizeof(struct
sockaddr_in)) / min(addr_len, sizeof(struct sockaddr_in6)) before copying into
out (update call sites accordingly), keeping all changes inside parse_sockaddr
and using the existing symbols family, bpf_probe_read_user, in4, in6, and
tcp_addr.
🧹 Nitpick comments (2)
plugins/in_ebpf/traces/tcp/handler.c (2)

38-66: Consider validating addr->version before encoding address fields.

If addr->version is neither 4 nor 6 (e.g., due to corrupted data or an uninitialized struct from a failed bpf_probe_read_user), the code falls through to the IPv4 branch and encodes potentially garbage data. An explicit check could improve robustness.

♻️ Suggested defensive check
-    if (addr->version == 6) {
+    if (addr->version == 6) {
         int i;

         for (i = 0; i < 4; i++) {
             snprintf(key, sizeof(key), "%s_addr_v6_%d", key_prefix, i);
             ret = flb_log_event_encoder_append_body_cstring(log_encoder, key);
             if (ret != FLB_EVENT_ENCODER_SUCCESS) {
                 return -1;
             }

             ret = flb_log_event_encoder_append_body_uint32(log_encoder,
                                                            addr->addr_raw.v6[i]);
             if (ret != FLB_EVENT_ENCODER_SUCCESS) {
                 return -1;
             }
         }
     }
-    else {
+    else if (addr->version == 4) {
         snprintf(key, sizeof(key), "%s_addr_v4", key_prefix);
         ret = flb_log_event_encoder_append_body_cstring(log_encoder, key);
         if (ret != FLB_EVENT_ENCODER_SUCCESS) {
             return -1;
         }

         ret = flb_log_event_encoder_append_body_uint32(log_encoder, addr->addr_raw.v4);
         if (ret != FLB_EVENT_ENCODER_SUCCESS) {
             return -1;
         }
     }
+    else {
+        /* Unknown IP version - skip address encoding or return error */
+        return -1;
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/in_ebpf/traces/tcp/handler.c` around lines 38 - 66, Validate
addr->version before encoding: in the function using addr, check explicitly that
addr->version is either 6 or 4 (e.g., if (addr->version == 6) { ... } else if
(addr->version == 4) { ... } else { handle error }) and handle any other value
by logging/returning an error (return -1) or skipping encoding to avoid emitting
garbage; update the branches around addr->version, key_prefix, log_encoder, and
calls to flb_log_event_encoder_append_body_uint32 /
flb_log_event_encoder_append_body_cstring to rely on this explicit check.

71-73: Unused parameter ins.

The ins parameter is declared but never used within encode_tcp_event(). Consider removing it or marking it as unused to avoid compiler warnings.

♻️ Option 1: Remove unused parameter
-int encode_tcp_event(struct flb_input_instance *ins,
-                     struct flb_log_event_encoder *log_encoder,
+int encode_tcp_event(struct flb_log_event_encoder *log_encoder,
                      const struct event *ev)

Note: This would require updating the call site at line 176 and any test code.

♻️ Option 2: Mark as unused
 int encode_tcp_event(struct flb_input_instance *ins,
                      struct flb_log_event_encoder *log_encoder,
                      const struct event *ev)
 {
     int ret;
+    (void) ins;  /* unused, kept for API consistency */
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/in_ebpf/traces/tcp/handler.c` around lines 71 - 73, The parameter
`ins` in function encode_tcp_event is declared but unused; either remove it from
the signature and update all call sites that pass that argument (including the
caller that invokes encode_tcp_event) or keep the parameter and mark it
explicitly unused to suppress warnings (e.g., add a cast/unused macro like
(void)ins or FLB_UNUSED(ins) at the top of encode_tcp_event); choose the marking
approach if you want to avoid touching callers, or remove the parameter if you
prefer a cleaner API and will update all callers/tests accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/in_ebpf/traces/tcp/handler.c`:
- Around line 181-188: The code returns immediately on flb_input_log_append
failure without calling flb_log_event_encoder_reset, leaving
encoder->output_buffer/state stale; update the handler to ensure
flb_log_event_encoder_reset(encoder) is invoked whether flb_input_log_append
succeeds or fails (e.g., call reset before returning on ret == -1 or use a
single exit path that resets the encoder), referencing flb_input_log_append,
flb_log_event_encoder_reset, encoder and event_ctx->ins to locate and modify the
failing branch.

---

Duplicate comments:
In `@plugins/in_ebpf/traces/tcp/bpf.c`:
- Around line 88-123: parse_sockaddr leaves family uninitialized and ignores
bpf_probe_read_user return values and potential user buffer sizes; fix by
initializing sa_family_t family = 0, checking the return of bpf_probe_read_user
when reading &addr->sa_family and returning early on error, and similarly check
returns when reading the full sockaddr_in/sockaddr_in6 into local in4/in6; to
avoid over-reads add an argument for the user buffer length (e.g., socklen_t
addr_len) or otherwise use a safe length check and only probe_read_user up to
min(addr_len, sizeof(struct sockaddr_in)) / min(addr_len, sizeof(struct
sockaddr_in6)) before copying into out (update call sites accordingly), keeping
all changes inside parse_sockaddr and using the existing symbols family,
bpf_probe_read_user, in4, in6, and tcp_addr.

---

Nitpick comments:
In `@plugins/in_ebpf/traces/tcp/handler.c`:
- Around line 38-66: Validate addr->version before encoding: in the function
using addr, check explicitly that addr->version is either 6 or 4 (e.g., if
(addr->version == 6) { ... } else if (addr->version == 4) { ... } else { handle
error }) and handle any other value by logging/returning an error (return -1) or
skipping encoding to avoid emitting garbage; update the branches around
addr->version, key_prefix, log_encoder, and calls to
flb_log_event_encoder_append_body_uint32 /
flb_log_event_encoder_append_body_cstring to rely on this explicit check.
- Around line 71-73: The parameter `ins` in function encode_tcp_event is
declared but unused; either remove it from the signature and update all call
sites that pass that argument (including the caller that invokes
encode_tcp_event) or keep the parameter and mark it explicitly unused to
suppress warnings (e.g., add a cast/unused macro like (void)ins or
FLB_UNUSED(ins) at the top of encode_tcp_event); choose the marking approach if
you want to avoid touching callers, or remove the parameter if you prefer a
cleaner API and will update all callers/tests accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 078e1c7c-f53e-41b7-bd4c-eb4167620c31

📥 Commits

Reviewing files that changed from the base of the PR and between f0c81cc and b83e0b9.

📒 Files selected for processing (9)
  • plugins/in_ebpf/in_ebpf.c
  • plugins/in_ebpf/traces/includes/common/encoder.h
  • plugins/in_ebpf/traces/includes/common/events.h
  • plugins/in_ebpf/traces/tcp/bpf.c
  • plugins/in_ebpf/traces/tcp/handler.c
  • plugins/in_ebpf/traces/tcp/handler.h
  • plugins/in_ebpf/traces/traces.h
  • tests/runtime/CMakeLists.txt
  • tests/runtime/in_ebpf_tcp_handler.c
✅ Files skipped from review due to trivial changes (1)
  • plugins/in_ebpf/traces/tcp/handler.h
🚧 Files skipped from review as they are similar to previous changes (5)
  • plugins/in_ebpf/traces/includes/common/encoder.h
  • plugins/in_ebpf/traces/traces.h
  • tests/runtime/in_ebpf_tcp_handler.c
  • plugins/in_ebpf/in_ebpf.c
  • plugins/in_ebpf/traces/includes/common/events.h

Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
plugins/in_ebpf/in_ebpf.c (1)

176-180: ⚠️ Potential issue | 🟡 Minor

Incomplete cleanup when a trace setup fails mid-way.

If trace_setup fails after some traces were already successfully registered, the previously registered traces (their ring buffers and skeletons) are not cleaned up before returning -1.

🐛 Proposed fix
         if (trace_setup(ctx, trace_name) != 0) {
             flb_plg_error(ctx->ins, "failed to configure trace: %s", trace_name);
+            for (int i = 0; i < ctx->trace_count; i++) {
+                ring_buffer__free(ctx->traces[i].rb);
+                if (ctx->traces[i].skel_destroy) {
+                    ctx->traces[i].skel_destroy(ctx->traces[i].skel);
+                }
+            }
+            flb_log_event_encoder_destroy(ctx->log_encoder);
+            flb_free(ctx->traces);
             flb_free(ctx);
             return -1;
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/in_ebpf/in_ebpf.c` around lines 176 - 180, When trace_setup(ctx,
trace_name) fails, currently only flb_free(ctx) is called leaving previously
registered traces' resources (ring buffers, skeletons) allocated; update the
error path to iterate over ctx's registered trace list (or call an existing
cleanup helper) to free/unregister each trace's ring buffer and bpf skeleton
before calling flb_free(ctx) and returning -1. Locate the failure block around
trace_setup in in_ebpf.c and ensure functions/structures involved (trace_setup,
ctx->traces or similar, and any unregister/free functions for ring buffers and
skeletons) are used to perform full cleanup of all partially-initialized traces
prior to returning.
🧹 Nitpick comments (2)
plugins/in_ebpf/in_ebpf.c (1)

35-39: Potential memory leak if flb_realloc fails.

If flb_realloc fails, the original ctx->traces pointer is lost, leaking any previously allocated trace contexts. This is a pre-existing pattern, but worth noting.

♻️ Suggested fix
-    ctx->traces = flb_realloc(ctx->traces, sizeof(struct trace_context) * (ctx->trace_count + 1));
-    if (!ctx->traces) {
+    struct trace_context *new_traces;
+    new_traces = flb_realloc(ctx->traces, sizeof(struct trace_context) * (ctx->trace_count + 1));
+    if (!new_traces) {
         flb_plg_error(ctx->ins, "failed to allocate memory for trace handlers");
         return -1;
     }
+    ctx->traces = new_traces;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/in_ebpf/in_ebpf.c` around lines 35 - 39, The current call to
flb_realloc directly assigns to ctx->traces which can leak the original buffer
on failure; instead, call flb_realloc into a temporary pointer (e.g., tmp),
check if tmp is NULL, and only assign tmp back to ctx->traces after a successful
realloc; on failure log via flb_plg_error(ctx->ins, ...) and return -1 without
modifying or freeing ctx->traces so existing trace contexts are preserved;
update the allocation logic around ctx->traces, ctx->trace_count and the
flb_realloc call accordingly.
tests/runtime/in_ebpf_tcp_handler.c (1)

42-48: Decoder is allocated but never used.

The flb_log_event_decoder is created and destroyed but not used in any test assertions. If the intent is to validate the encoded output, consider adding decode verification; otherwise, remove it to simplify the test.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/runtime/in_ebpf_tcp_handler.c` around lines 42 - 48, The decoder
(ctx->decoder created via flb_log_event_decoder_create) is unnecessary if you
aren't asserting on encoded output; either remove the ctx->decoder allocation
and its subsequent cleanup (and related flb_log_event_decoder_destroy calls) to
simplify the test, or actually use it to validate encoding by retrieving the
encoder buffer and running the decoder (use flb_log_event_decoder_decode or the
appropriate decode API on the payload from the encoder) and add assertions
against decoded records; update or remove the matching cleanup alongside
flb_log_event_encoder_destroy and flb_free(ctx->ins)/flb_free(ctx) accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/runtime/in_ebpf_tcp_handler.c`:
- Around line 85-87: The test currently calls init_test_context() into ctx and
uses TEST_CHECK(ctx != NULL) but continues on failure; update the test to stop
execution if ctx is NULL by checking the return value after TEST_CHECK and
returning from the test (or calling the test framework’s abort/cleanup helper).
Concretely, after the TEST_CHECK(ctx != NULL) invocation for the ctx produced by
init_test_context(), add an explicit if (!ctx) return (or call the existing test
cleanup/abort routine) to avoid dereferencing ctx in subsequent code paths that
follow in this test function.

---

Outside diff comments:
In `@plugins/in_ebpf/in_ebpf.c`:
- Around line 176-180: When trace_setup(ctx, trace_name) fails, currently only
flb_free(ctx) is called leaving previously registered traces' resources (ring
buffers, skeletons) allocated; update the error path to iterate over ctx's
registered trace list (or call an existing cleanup helper) to free/unregister
each trace's ring buffer and bpf skeleton before calling flb_free(ctx) and
returning -1. Locate the failure block around trace_setup in in_ebpf.c and
ensure functions/structures involved (trace_setup, ctx->traces or similar, and
any unregister/free functions for ring buffers and skeletons) are used to
perform full cleanup of all partially-initialized traces prior to returning.

---

Nitpick comments:
In `@plugins/in_ebpf/in_ebpf.c`:
- Around line 35-39: The current call to flb_realloc directly assigns to
ctx->traces which can leak the original buffer on failure; instead, call
flb_realloc into a temporary pointer (e.g., tmp), check if tmp is NULL, and only
assign tmp back to ctx->traces after a successful realloc; on failure log via
flb_plg_error(ctx->ins, ...) and return -1 without modifying or freeing
ctx->traces so existing trace contexts are preserved; update the allocation
logic around ctx->traces, ctx->trace_count and the flb_realloc call accordingly.

In `@tests/runtime/in_ebpf_tcp_handler.c`:
- Around line 42-48: The decoder (ctx->decoder created via
flb_log_event_decoder_create) is unnecessary if you aren't asserting on encoded
output; either remove the ctx->decoder allocation and its subsequent cleanup
(and related flb_log_event_decoder_destroy calls) to simplify the test, or
actually use it to validate encoding by retrieving the encoder buffer and
running the decoder (use flb_log_event_decoder_decode or the appropriate decode
API on the payload from the encoder) and add assertions against decoded records;
update or remove the matching cleanup alongside flb_log_event_encoder_destroy
and flb_free(ctx->ins)/flb_free(ctx) accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 59038b17-65c6-4382-adfd-6db73e1ea30f

📥 Commits

Reviewing files that changed from the base of the PR and between b83e0b9 and 8757c04.

📒 Files selected for processing (9)
  • plugins/in_ebpf/in_ebpf.c
  • plugins/in_ebpf/traces/includes/common/encoder.h
  • plugins/in_ebpf/traces/includes/common/events.h
  • plugins/in_ebpf/traces/tcp/bpf.c
  • plugins/in_ebpf/traces/tcp/handler.c
  • plugins/in_ebpf/traces/tcp/handler.h
  • plugins/in_ebpf/traces/traces.h
  • tests/runtime/CMakeLists.txt
  • tests/runtime/in_ebpf_tcp_handler.c
✅ Files skipped from review due to trivial changes (2)
  • plugins/in_ebpf/traces/tcp/handler.h
  • plugins/in_ebpf/traces/tcp/handler.c
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/runtime/CMakeLists.txt
  • plugins/in_ebpf/traces/includes/common/encoder.h
  • plugins/in_ebpf/traces/includes/common/events.h

Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
plugins/in_ebpf/in_ebpf.c (2)

198-208: ⚠️ Potential issue | 🟡 Minor

Free ctx->traces in this unwind branch too.

This path now destroys each ring buffer and skeleton, but it still returns without freeing the trace-context array itself.

💡 Proposed fix
     if (ctx->coll_fd < 0) {
         flb_plg_error(ctx->ins, "failed to set up collector");
         for (int i = 0; i < ctx->trace_count; i++) {
             ring_buffer__free(ctx->traces[i].rb);
             if (ctx->traces[i].skel_destroy) {
                 ctx->traces[i].skel_destroy(ctx->traces[i].skel);
             }
         }
         flb_log_event_encoder_destroy(ctx->log_encoder);
+        flb_free(ctx->traces);
         flb_free(ctx);
         return -1;
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/in_ebpf/in_ebpf.c` around lines 198 - 208, The unwind branch that
handles ctx->coll_fd < 0 frees each trace's ring buffer and skeleton and
destroys the log encoder but neglects to free the trace-context array itself;
after the loop that calls ring_buffer__free and skel_destroy for each
ctx->traces[i], add a call to free the trace array (e.g., free or flb_free on
ctx->traces) before flb_log_event_encoder_destroy and flb_free(ctx), ensuring
you reference ctx->traces and ctx->trace_count so the correct buffer is
released.

26-45: ⚠️ Potential issue | 🔴 Critical

Fix realloc failure handling in trace_register().

The code directly assigns the flb_realloc() result to ctx->traces:

ctx->traces = flb_realloc(ctx->traces, sizeof(struct trace_context) * (ctx->trace_count + 1));
if (!ctx->traces) {
    flb_plg_error(ctx->ins, "failed to allocate memory for trace handlers");
    return -1;
}

flb_realloc() is a wrapper around standard realloc(), which returns NULL on failure. When this happens, ctx->traces is set to NULL, but ctx->trace_count remains non-zero. The unwind loop in in_ebpf_init() later dereferences ctx->traces[i], causing a crash.

Use a temporary pointer to preserve the old allocation on failure:

Proposed fix
 int trace_register(struct flb_in_ebpf_context *ctx, const char *name,
                    void *skel, struct bpf_object *obj,
                    trace_skel_destroy_func_t skel_destroy,
                    trace_event_handler_t handler) {
     struct trace_context *trace;
+    struct trace_context *tmp;
     struct bpf_map *map, *events_map;
     int map_fd;
 
     flb_plg_debug(ctx->ins, "registering trace handler for: %s", name);
-    ctx->traces = flb_realloc(ctx->traces, sizeof(struct trace_context) * (ctx->trace_count + 1));
-    if (!ctx->traces) {
+    tmp = flb_realloc(ctx->traces,
+                      sizeof(struct trace_context) * (ctx->trace_count + 1));
+    if (!tmp) {
         flb_plg_error(ctx->ins, "failed to allocate memory for trace handlers");
         return -1;
     }
+    ctx->traces = tmp;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/in_ebpf/in_ebpf.c` around lines 26 - 45, The realloc result in
trace_register() is assigned directly to ctx->traces which loses the old pointer
on failure; change this to use a temporary pointer (e.g., new_traces) to call
flb_realloc(ctx->traces, sizeof(struct trace_context) * (ctx->trace_count + 1)),
check if new_traces is NULL, log and return -1 without modifying ctx->traces if
allocation fails, and only assign ctx->traces = new_traces and increment
ctx->trace_count after successful allocation; this preserves the original
ctx->traces used by the in_ebpf_init() unwind loop and avoids null dereferences.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/in_ebpf/in_ebpf.c`:
- Around line 263-265: The help text for the "Trace" config entry in
plugins/in_ebpf/in_ebpf.c advertises trace names without the required "trace_"
prefix, causing "unknown trace name" errors; update the help string associated
with the FLB_CONFIG_MAP_STR entry for "Trace" to list the actual registered
trace names (e.g., trace_bind, trace_malloc, trace_signal, trace_vfs, trace_tcp)
so examples in --help match the trace registration used by the plugin.

---

Outside diff comments:
In `@plugins/in_ebpf/in_ebpf.c`:
- Around line 198-208: The unwind branch that handles ctx->coll_fd < 0 frees
each trace's ring buffer and skeleton and destroys the log encoder but neglects
to free the trace-context array itself; after the loop that calls
ring_buffer__free and skel_destroy for each ctx->traces[i], add a call to free
the trace array (e.g., free or flb_free on ctx->traces) before
flb_log_event_encoder_destroy and flb_free(ctx), ensuring you reference
ctx->traces and ctx->trace_count so the correct buffer is released.
- Around line 26-45: The realloc result in trace_register() is assigned directly
to ctx->traces which loses the old pointer on failure; change this to use a
temporary pointer (e.g., new_traces) to call flb_realloc(ctx->traces,
sizeof(struct trace_context) * (ctx->trace_count + 1)), check if new_traces is
NULL, log and return -1 without modifying ctx->traces if allocation fails, and
only assign ctx->traces = new_traces and increment ctx->trace_count after
successful allocation; this preserves the original ctx->traces used by the
in_ebpf_init() unwind loop and avoids null dereferences.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c573c483-0613-40d1-a058-15e1db34d520

📥 Commits

Reviewing files that changed from the base of the PR and between 8757c04 and b89e68b.

📒 Files selected for processing (1)
  • plugins/in_ebpf/in_ebpf.c

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant