Execsnoop Collector - antimetal/system-agent GitHub Wiki
Execsnoop eBPF Collector
Overview
The Execsnoop collector is an eBPF-based performance collector that monitors process execution events in real-time. It captures detailed information about every process that executes on the system, including command-line arguments, parent process relationships, and execution results. This collector is essential for security monitoring, process auditing, and understanding system behavior.
Why Process Execution Tracking is Important
- Security Monitoring: Detect unauthorized or suspicious process executions
- Compliance Auditing: Track all executed commands for audit trails
- Performance Analysis: Understand process spawning patterns and overhead
- Debugging: Trace program execution chains and dependencies
- Container Monitoring: Track process activity within containers
Technical Details
eBPF-Based Architecture
The Execsnoop collector uses eBPF (extended Berkeley Packet Filter) technology to efficiently monitor process executions at the kernel level with minimal overhead.
Key Components:
- CO-RE (Compile Once - Run Everywhere): Ensures portability across different kernel versions
- Ring Buffer: High-performance data transfer from kernel to userspace
- Tracepoint Hooks: Attaches to
sys_enter_execve
andsys_exit_execve
syscall tracepoints
Kernel Requirements
Feature | Minimum Kernel | Notes |
---|---|---|
Basic eBPF support | 4.18+ | Required for BPF programs |
Full CO-RE support | 5.2+ | BTF (BPF Type Format) support |
Ring buffer support | 5.8+ | Required for this collector |
External BTF | 4.18-5.1 | Can use external BTF files |
Collected Metrics
The collector captures the following information for each process execution:
Metric | Type | Description |
---|---|---|
Timestamp |
time.Time |
When the execution was captured |
PID |
int32 |
Process ID of the executed process |
PPID |
int32 |
Parent Process ID |
UID |
uint32 |
User ID that executed the process |
RetVal |
int32 |
Return value of execve (0 = success, negative = error) |
Command |
string |
Command name (up to 16 characters) |
Args |
[]string |
Command-line arguments array |
Data Limits
- Command name: Limited to 16 characters (kernel
TASK_COMM_LEN
) - Individual argument: Up to 128 bytes per argument
- Total arguments: Maximum 60 arguments
- Ring buffer size: 1MB (configurable)
Data Structure
eBPF Program Location
- Source:
ebpf/src/execsnoop.bpf.c
(View in branch) - Compiled objects:
execsnoop-5.15.bpf.o
,execsnoop-6.8.bpf.o
- Type definitions:
ebpf/include/execsnoop_types.h
Go Implementation
- Collector:
pkg/performance/collectors/execsnoop.go
- Generated types:
pkg/performance/collectors/execsnoop_types.go
Event Structure (C/eBPF)
struct execsnoop_event {
__s32 pid;
__s32 ppid;
__u32 uid;
__s32 retval;
__s32 args_count;
__u32 args_size;
char comm[TASK_COMM_LEN];
// Variable length args data follows
};
Event Structure (Go)
type ExecEvent struct {
Timestamp time.Time
PID int32
PPID int32
UID uint32
RetVal int32
Command string
Args []string
}
Configuration
Collector Configuration
The collector can be configured with the following options:
config := performance.CollectionConfig{
// Standard configuration inherited from base collector
}
// Custom BPF object path (optional)
bpfObjectPath := "/custom/path/execsnoop.bpf.o"
collector, err := collectors.NewExecSnoopCollector(logger, config, bpfObjectPath)
BPF Object Path Resolution
- If
bpfObjectPath
parameter is provided, use it directly - Check
ANTIMETAL_BPF_PATH
environment variable - Default to
/usr/local/lib/antimetal/ebpf/execsnoop.bpf.o
Runtime Requirements
- Privileges: Requires root or
CAP_BPF
+CAP_PERFMON
capabilities - Memory lock: Automatically removes memlock limit for BPF operations
- Kernel features: Validates kernel support before starting
Platform Considerations
Kernel Version Support Matrix
Kernel Version | Support Level | Notes |
---|---|---|
< 4.18 | ❌ Not supported | No eBPF support |
4.18 - 5.1 | ⚠️ Partial | Requires external BTF files |
5.2 - 5.7 | ✅ Supported | Full CO-RE support |
5.8+ | ✅ Full support | Ring buffer + all features |
CO-RE Support Levels
- Full: Kernel has built-in BTF, full relocation support
- Partial: External BTF required, limited relocation
- None: No BTF available, CO-RE disabled
Distribution-Specific Notes
- Ubuntu 20.04+: Full support with HWE kernels
- RHEL 8.4+: Full support with backported features
- Amazon Linux 2: Requires kernel 5.10+
- Container environments: Host kernel determines support
Common Issues
eBPF-Specific Troubleshooting
1. Permission Denied
Error: operation not permitted
Solution: Run with root privileges or add capabilities:
sudo setcap cap_bpf,cap_perfmon+ep /path/to/agent
2. Kernel Too Old
Error: kernel version 4.15 is below minimum 5.8
Solution: Upgrade kernel or use a different collector
3. BTF Not Available
Error: failed to load kernel BTF
Solutions:
- Install kernel development headers
- Use external BTF from BTF Hub
- Check
/sys/kernel/btf/vmlinux
exists
4. Ring Buffer Creation Failed
Error: creating ring buffer: invalid argument
Causes:
- Kernel < 5.8 (no ring buffer support)
- Insufficient memory
- Resource limits
5. BPF Program Load Failed
Error: loading BPF collection: invalid argument
Common causes:
- Incompatible BPF object file
- Kernel configuration missing BPF features
- SELinux/AppArmor restrictions
Debug Commands
# Check kernel version and config
uname -r
grep CONFIG_BPF /boot/config-$(uname -r)
# Check BTF availability
ls -la /sys/kernel/btf/vmlinux
# Test BPF functionality
sudo bpftool prog list
sudo bpftool map list
# Check capabilities
getcap /path/to/agent
Examples
Sample Output
[1] PID=12345 PPID=12340 UID=1000 CMD=ls ARGS=[ls -la /tmp] RetVal=0
[2] PID=12346 PPID=12340 UID=1000 CMD=grep ARGS=[grep error /var/log/syslog] RetVal=0
[3] PID=12347 PPID=1 UID=0 CMD=systemd-resolve ARGS=[systemd-resolve --status] RetVal=0
[4] PID=12348 PPID=12340 UID=1000 CMD=curl ARGS=[curl https://example.com] RetVal=0
Security Use Cases
1. Detect Suspicious Commands
// Alert on sensitive command execution
if execEvent.Command == "passwd" || execEvent.Command == "useradd" {
alert("User management command executed", execEvent)
}
2. Monitor Container Escapes
// Track processes spawned with UID 0 from non-root parents
if execEvent.UID == 0 && parentUID != 0 {
alert("Potential privilege escalation", execEvent)
}
3. Audit Command Arguments
// Log all wget/curl downloads
if execEvent.Command == "wget" || execEvent.Command == "curl" {
logDownload(execEvent.Args)
}
Integration Example
func main() {
// Create and start collector
collector, _ := collectors.NewExecSnoopCollector(logger, config, "")
eventChan, _ := collector.Start(ctx)
// Process events
for event := range eventChan {
if execEvent, ok := event.(*collectors.ExecEvent); ok {
// Send to SIEM
siem.Send(execEvent)
// Update metrics
processMetrics.Inc(execEvent.Command)
// Apply security policies
if policy.ShouldBlock(execEvent) {
// Take action (log, alert, etc.)
}
}
}
}
Performance Impact
eBPF Overhead
The Execsnoop collector has minimal performance impact due to eBPF's efficient design:
Aspect | Impact | Details |
---|---|---|
CPU Overhead | < 1% | eBPF runs in kernel space |
Memory Usage | ~2MB | 1MB ring buffer + BPF maps |
Latency | < 1μs | Per-execution overhead |
Event Rate | High | Can handle 100k+ events/sec |
Performance Characteristics
- Zero-copy: Ring buffer provides zero-copy data transfer
- Batching: Events are batched in ring buffer
- Selective: Can add filters to reduce data volume
- Non-blocking: Kernel continues execution without waiting
Optimization Tips
- Adjust ring buffer size based on event rate
- Implement kernel-side filtering to reduce data volume
- Use per-CPU buffers for high-throughput scenarios
- Monitor dropped events and adjust capacity
Related Collectors
System Monitoring
- Process Collector - Process statistics and metrics
- CPU Collector - CPU usage and performance
- Memory Collector - Memory statistics
Security Monitoring
- File Access Collector (Future) - Monitor file operations
- Network Connection Collector (Future) - Track network activity
- Syscall Collector (Future) - General syscall monitoring
eBPF-Based Collectors
- OOMKill Trace Collector (Planned) - Out-of-memory kill events
- TCP Connection Collector (Planned) - TCP connection tracking
- Block I/O Collector (Planned) - Disk I/O operations