Skip to content

Feat/container uprobe support#39

Open
yoloyyh wants to merge 9 commits intoeunomia-bpf:masterfrom
yoloyyh:feat/container-uprobe-support
Open

Feat/container uprobe support#39
yoloyyh wants to merge 9 commits intoeunomia-bpf:masterfrom
yoloyyh:feat/container-uprobe-support

Conversation

@yoloyyh
Copy link
Copy Markdown

@yoloyyh yoloyyh commented Apr 8, 2026

Add container-aware metadata (namespace PID and container ID) to all eBPF event types (process, file, SSL/TLS) and fix the frontend to correctly display HTTP-parsed SSL events.

Background: When AgentSight traces processes running inside Docker containers, the host PID is meaningless to the user — they need the container-internal (namespace) PID and the container ID to correlate events. This PR adds container metadata extraction at the BPF userspace layer and propagates it through the entire pipeline to the frontend UI.

Key changes:

  1. bpf/container_info.h (new): Shared helper library for container metadata extraction

    • get_ns_pid(): Parses /proc/<pid>/status NSpid line to get the innermost namespace PID
    • get_container_id(): Parses /proc/<pid>/cgroup to extract the 12-char Docker container ID
    • print_container_fields(): Appends ns_pid and container_id JSON fields to event output
  2. bpf/container_utils.h (new): Dynamic uprobe management for container SSL tracing

    • Discovers and attaches uprobes to libssl.so inside container processes at runtime
  3. bpf/process_new.c: Integrated container_info.h — EXEC, EXIT, and FILE_OPEN events now include ns_pid and container_id

  4. bpf/sslsniff.c: Integrated container_info.h — SSL_read/SSL_write events now include container metadata

  5. bpf/process_ext/bpf_common.h: Fixed BPF verifier back-edge error on kernel 5.15 by fully unrolling loops in format_ipv4_port() (kernel 5.15 doesn't support bounded loops)

  6. collector/src/framework/runners/process.rs: Fixed panic on CLOCK_SYNC events from process_new by switching from .map() with panic! to .filter_map() that gracefully skips metadata events

  7. frontend/.../BlockAdapters.tsx:

    • SSL adapter now handles both raw sslsniff events (buf_size/data/function) and http_parser-transformed events (body/headers/method/total_size/message_type)
    • Added container tags and namespace PID display to process, file, and SSL event blocks

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

  • Container process tracing: Ran a Python script inside a Docker container (docker exec) making HTTPS requests to httpbin.org, verified all event types (EXEC, EXIT, FILE_OPEN, SSL request/response) contain correct ns_pid and container_id fields in trace.log
  • Frontend SSL display: Confirmed http_parser events (source=http_parser) now render with correct HTTP method, status code, body content, and size instead of showing empty/0 BYTES
  • BPF verifier: Verified process_new BPF program loads successfully on kernel 5.15 after loop unrolling fix
  • Non-container processes: Verified events from host processes still work correctly (no container fields added when not in a container)

Test Configuration:

  • Kernel: 5.15.x (Ubuntu)
  • Container runtime: Docker (runc)
  • Toolchain: clang/llvm (BPF compilation), Rust (collector), Node.js/Next.js (frontend)

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules
  • I have checked my code and corrected any misspellings

yangyuhui.807 added 2 commits April 8, 2026 11:50
- Add container_info.h: shared helpers for ns_pid and container_id extraction
  from /proc/<pid>/status (NSpid) and /proc/<pid>/cgroup (docker ID)

- sslsniff.c: add container info (ns_pid, container_id) to SSL event JSON output
  Container SSL events now include full metadata for UI display

- process_new.c: add container info to EXEC, EXIT, FILE_OPEN events
  Container processes show namespace PID and container short ID

- bpf_common.h: fix format_ipv4_port BPF verifier back-edge error
  Unroll loops for kernel 5.15 compatibility (no bounded loop support)

- process.rs: fix panic on CLOCK_SYNC events from process_new
  Use filter_map to skip metadata events without pid field

- BlockAdapters.tsx: fix SSL 0 BYTES display bug
  Map sslsniff field names (buf_size/function/data) correctly
  Show container tags (container_id emoji) in SSL/process/file events
  Display actual SSL data preview in fold content

Verified: container python process (PID 3148274, ns_pid 36) in
agentsight-test container correctly shows all event types with
container metadata and full SSL request/response data.
The HTTP parser analyzer transforms raw SSL events, changing the source
from 'ssl' to 'http_parser' and replacing sslsniff fields (buf_size,
data, function) with HTTP-parsed fields (body, headers, method,
total_size, message_type, first_line, etc.).

adaptSSLEvent now detects http_parser events via original_source and
correctly extracts:
- Size from total_size/content_length instead of buf_size
- Direction from message_type (request/response) instead of function
- Fold content from first_line instead of raw data preview
- Expanded content from body (with JSON pretty-print) instead of data

Also adds HTTP/TLS source tag to distinguish event origin.
yangyuhui.807 and others added 5 commits April 13, 2026 16:54
bpf_probe_read_user_str stops at the first null byte, but argv entries
in process memory are separated by null bytes (e.g. 'chmod\0+x\0/path\0').
This caused full_command to only contain argv[0] (e.g. 'chmod') without
any arguments.

Switch to bpf_probe_read_user which reads raw bytes for the entire
arg_start..arg_end range, then replace internal null separators with
spaces to produce the complete command line.

Before: full_command='chmod'
After:  full_command='chmod +x /tmp/test_file.txt'
Some kernel versions cannot track the range of unsigned long through
an if-clamp alone. Adding 'arg_len &= (MAX_COMMAND_LEN - 1)' gives
the verifier a provable upper bound on the read size, fixing -EACCES
load failures on stricter kernels.
fix(bpf): add bitmask constraint for verifier on bpf_probe_read_user
The BPF verifier on kernel 5.15 (1M instruction limit) rejects programs
with loops iterating over MAX_COMMAND_LEN (255) bytes due to state
explosion.  Two loops * 255 iterations with conditional branches easily
exceeded 1,000,000 instructions.

Solution: eliminate ALL loops from the BPF program.  BPF now only:
  1. Reads raw argv bytes with bpf_probe_read_user (constant size)
  2. Stores actual arg_len in e->exit_code (unused for exec events)
  3. Submits the raw event to userspace

Userspace postprocess_full_command() in process_utils.h then:
  1. Copies to a local buffer (ringbuf memory is mmap read-only)
  2. Trims to arg_len to prevent environment variable leakage
  3. Replaces \0 separators between argv entries with spaces

This approach:
  - Stays well under the BPF verifier instruction limit on all kernels
  - Avoids SIGSEGV from writing to read-only ringbuf consumer memory
  - Prevents environment variables from leaking into full_command
  - Captures complete argv (e.g., "chmod +x /tmp/file") instead of
    just argv[0]

Tested on 5.15.120.bsk.3-amd64: BPF loads and runs successfully.
@yoloyyh yoloyyh force-pushed the feat/container-uprobe-support branch from 30edc73 to c25ee54 Compare April 17, 2026 03:46
Signed-off-by: yoloyyh <57630263+yoloyyh@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds container-aware metadata propagation (namespace PID + container ID) through the eBPF → collector → frontend pipeline, and improves SSL event rendering to support both raw TLS events and HTTP-parser-transformed events.

Changes:

  • Introduces userspace helpers for extracting/printing ns_pid and container_id, and integrates them into process/file/SSL event JSON output.
  • Adds dynamic uprobe discovery/attachment for container-specific libssl.so paths and cleans up links on exit.
  • Updates collector/frontend to gracefully handle metadata events and to render HTTP-parsed SSL events correctly, including container tags.

Reviewed changes

Copilot reviewed 11 out of 13 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
bpf/container_info.h New userspace helper for ns_pid/container_id extraction and JSON printing.
bpf/container_utils.h New /proc-based lib discovery + dynamic bpf_link lifecycle management for container uprobes.
bpf/sslsniff.c Uses new container helpers, adds container lib path resolution/scan, prints container fields in JSON, and destroys dynamic links at cleanup.
bpf/process_new.c Prints container fields for relevant event types; uses userspace post-processing for full command line.
bpf/process_new.bpf.c Captures argv block more completely by switching from _str to raw user-memory reads; stores arg length for userspace trimming.
bpf/process.c Uses userspace post-processing for full command line formatting.
bpf/process.bpf.c Same argv capture approach as process_new.bpf.c.
bpf/process_utils.h Adds userspace command-line post-processing helper.
bpf/process_ext/bpf_common.h Fully unrolls IPv4:port formatting to avoid verifier back-edge issues on kernel 5.15.
collector/src/framework/runners/process.rs Skips metadata events by switching to filter_map instead of panicking on missing fields.
frontend/src/components/process-tree/BlockAdapters.tsx Updates SSL adapter to handle both raw TLS and HTTP-parsed events; adds container tags + ns_pid display.
.gitignore Ignores node_modules/.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread bpf/container_info.h
Comment thread collector/src/framework/runners/process.rs
Comment thread frontend/src/components/process-tree/BlockAdapters.tsx Outdated
Comment thread bpf/sslsniff.c Outdated
Comment thread bpf/container_utils.h Outdated
Comment thread bpf/container_info.h
Comment thread bpf/process_new.c
Comment thread bpf/sslsniff.c
Comment thread bpf/container_utils.h Outdated
- container_info.h: add SPDX license identifier
- container_info.h: add #include <sys/types.h> for pid_t
- container_utils.h: fix strncpy NUL-termination (PATH_MAX-1 + explicit NUL)
- container_utils.h: replace 256KB stack array with heap allocation
- sslsniff.c: use libbpf_get_error() instead of NULL check for ERR_PTR
- sslsniff.c: gate container uprobe debug fprintf behind verbose flag
- process_new.c: move #include "container_info.h" to top include block
- process.rs: use current time instead of 0 when timestamp missing
- BlockAdapters.tsx: truncate before regex replace for performance
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants