Skip to content

feat: filter events by PID tree - #42

Open
kemingy wants to merge 4 commits into
tensorchord:mainfrom
kemingy:fix/pid-tree-filter-lifecycle
Open

kemingy wants to merge 4 commits into
tensorchord:mainfrom
kemingy:fix/pid-tree-filter-lifecycle

Conversation

@kemingy

@kemingy kemingy commented Sep 9, 2026

Copy link
Copy Markdown
Member

Summary

  • add -pid to restrict eBPF events to a host process and its existing/future descendants
  • share one tracked-PID map across all probes and maintain it from fork/exit tracepoints
  • reconcile descendants after lifecycle hooks attach to cover startup forks
  • keep a process TGID tracked until its final thread exits
  • add unit coverage for descendant traversal

Closes #33

Validation

  • go test ./internal/pidfilter
  • golangci-lint run ./internal/pidfilter/...
  • git diff --check
  • make gen_ebpf was attempted, but this macOS host lacks llvm-strip and a Clang BPF target; Linux CI should run the full generation/build/test workflow.

@kemingy
kemingy force-pushed the fix/pid-tree-filter-lifecycle branch from 417ffed to 8516ad7 Compare September 9, 2026 00:32
Signed-off-by: Keming <kemingy94@gmail.com>
@kemingy
kemingy force-pushed the fix/pid-tree-filter-lifecycle branch from 8516ad7 to 308abf9 Compare September 9, 2026 00:33
@kemingy
kemingy requested a balanced review from Copilot September 9, 2026 00:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Lifecycle races can permanently retain or resurrect stale PIDs, allowing unrelated processes to pass the filter.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds host PID-tree filtering across WatchU’s eBPF probes.

Changes:

  • Adds -pid, descendant discovery, and fork/exit tracking.
  • Shares filtering state across all probes.
  • Updates bindings, documentation, and traversal tests.
File summaries
File Description
README.md Documents PID filtering.
cmd/main.go Configures and distributes the filter.
internal/pidfilter/filter.go Implements filter state and reconciliation.
internal/pidfilter/filter_test.go Tests descendant traversal.
headers/pid_filter.h Defines the shared eBPF map and helpers.
execve/exec.bpf.c Tracks lifecycle events and filters exec activity.
execve/probe.go Integrates lifecycle tracking.
execve/exec_x86_bpfel.go Updates x86 generated bindings.
execve/exec_arm64_bpfel.go Updates ARM64 generated bindings.
fileop/fileop.bpf.c Filters file events.
fileop/probe.go Injects the shared map.
fileop/fileop_x86_bpfel.go Updates x86 generated bindings.
fileop/fileop_arm64_bpfel.go Updates ARM64 generated bindings.
postgres/pg.bpf.c Filters PostgreSQL events.
postgres/probe.go Injects the shared map.
postgres/pg_x86_bpfel.go Updates x86 generated bindings.
postgres/pg_arm64_bpfel.go Updates ARM64 generated bindings.
stdio/stdio.bpf.c Filters stdio events.
stdio/probe.go Injects the shared map.
stdio/stdio_x86_bpfel.go Updates x86 generated bindings.
stdio/stdio_arm64_bpfel.go Updates ARM64 generated bindings.
tcpconn/tcpconn.bpf.c Filters connection initiation.
tcpconn/probe.go Injects the shared map.
tcpconn/tcpconn_x86_bpfel.go Updates x86 generated bindings.
tcpconn/tcpconn_arm64_bpfel.go Updates ARM64 generated bindings.
tls/ssl_common.h Filters emitted TLS events.
tls/ssl.bpf.c Filters OpenSSL entry probes.
tls/boring.bpf.c Filters BoringSSL entry probes.
tls/probe.go Propagates the filter to TLS probes.
tls/openssl.go Injects the map into OpenSSL probes.
tls/boring.go Injects the map into BoringSSL probes.
tls/ssl_x86_bpfel.go Updates x86 generated bindings.
tls/ssl_arm64_bpfel.go Updates ARM64 generated bindings.
tls/boring_x86_bpfel.go Updates x86 generated bindings.
tls/boring_arm64_bpfel.go Updates ARM64 generated bindings.
Review details

Files not reviewed (12)

  • execve/exec_arm64_bpfel.go: Generated file
  • execve/exec_x86_bpfel.go: Generated file
  • fileop/fileop_arm64_bpfel.go: Generated file
  • fileop/fileop_x86_bpfel.go: Generated file
  • postgres/pg_arm64_bpfel.go: Generated file
  • postgres/pg_x86_bpfel.go: Generated file
  • stdio/stdio_arm64_bpfel.go: Generated file
  • stdio/stdio_x86_bpfel.go: Generated file
  • tcpconn/tcpconn_arm64_bpfel.go: Generated file
  • tcpconn/tcpconn_x86_bpfel.go: Generated file
  • tls/boring_arm64_bpfel.go: Generated file
  • tls/boring_x86_bpfel.go: Generated file
  • Files reviewed: 23/35 changed files
  • Comments generated: 5
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread execve/probe.go Resolved
Comment thread internal/pidfilter/filter.go Resolved
Comment thread internal/pidfilter/filter.go Resolved
Comment thread cmd/main.go Resolved
Comment thread headers/pid_filter.h Resolved
Signed-off-by: Keming <kemingy94@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Startup reconciliation can permanently miss newly forked descendants, and the disabled path unnecessarily allocates another 4 MiB kernel ring buffer.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Files not reviewed (12)

  • execve/exec_arm64_bpfel.go: Generated file
  • execve/exec_x86_bpfel.go: Generated file
  • fileop/fileop_arm64_bpfel.go: Generated file
  • fileop/fileop_x86_bpfel.go: Generated file
  • postgres/pg_arm64_bpfel.go: Generated file
  • postgres/pg_x86_bpfel.go: Generated file
  • stdio/stdio_arm64_bpfel.go: Generated file
  • stdio/stdio_x86_bpfel.go: Generated file
  • tcpconn/tcpconn_arm64_bpfel.go: Generated file
  • tcpconn/tcpconn_x86_bpfel.go: Generated file
  • tls/boring_arm64_bpfel.go: Generated file
  • tls/boring_x86_bpfel.go: Generated file
  • Files reviewed: 23/35 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread internal/pidfilter/filter.go Resolved
Comment thread execve/exec.bpf.c
Comment on lines +219 to +222
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, RING_BUFFER_SIZE);
} pid_events SEC(".maps");

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Valid. Fixed in 9e4128f: lifecycle notifications and their userspace reader were removed. The generated map slot is now a one-entry array placeholder instead of a 4 MiB ring buffer, so the disabled path no longer allocates the lifecycle ring.

Signed-off-by: Keming <kemingy94@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Descendant reconciliation can admit an unrelated process when a child PID is reused between /proc reads.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Files not reviewed (12)

  • execve/exec_arm64_bpfel.go: Generated file
  • execve/exec_x86_bpfel.go: Generated file
  • fileop/fileop_arm64_bpfel.go: Generated file
  • fileop/fileop_x86_bpfel.go: Generated file
  • postgres/pg_arm64_bpfel.go: Generated file
  • postgres/pg_x86_bpfel.go: Generated file
  • stdio/stdio_arm64_bpfel.go: Generated file
  • stdio/stdio_x86_bpfel.go: Generated file
  • tcpconn/tcpconn_arm64_bpfel.go: Generated file
  • tcpconn/tcpconn_x86_bpfel.go: Generated file
  • tls/boring_arm64_bpfel.go: Generated file
  • tls/boring_x86_bpfel.go: Generated file
  • Files reviewed: 23/35 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment on lines +186 to +191
for _, childPID := range readProcessChildren(pid) {
childIdentity, ok := readProcessIdentity(childPID)
if !ok {
continue
}
if err := f.seedProcess(childPID, childIdentity, seen); err != nil {
return nil
}

func readProcessChildren(pid uint32) []uint32 {
Signed-off-by: Keming <kemingy94@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: support pid tree filtering for eBPF

2 participants