Adding New Events¶
This guide walks you through the process of adding new event monitoring capabilities to Tracee. Adding new events involves modifications to several files across the codebase.
Overview¶
Adding a new event to Tracee requires changes in several main areas:
- eBPF Implementation - Implement the actual event handling logic
- Probe Configuration - Configure how the event attaches to kernel functions
- Event Definition - Define the event and its metadata in Go code
- Protobuf Schema - Add event to protobuf definitions for gRPC API
- gRPC Translation - Map event to protobuf enums for external APIs
- Event Documentation - Create documentation file for the event
Step-by-Step Process¶
1. Implement eBPF Program in pkg/ebpf/c/tracee.bpf.c¶
Choose a kernel function to monitor:
- System calls: sys_openat, sys_execve
- LSM hooks: security_file_open, security_bprm_check
- VFS operations: vfs_read, vfs_write
- Network: tcp_connect, inet_csk_accept
Find functions: cat /proc/kallsyms | grep function_name
Implement the eBPF program:
SEC("kprobe/your_kernel_function") // Must match probe configuration
int BPF_KPROBE(trace_your_event) // This name will be used in probe config
{
// Your event implementation follows this pattern:
// 1. Initialize program data
// 2. Apply scope filtering
// 3. Extract data fields
// 4. Apply data field-based filtering
// 5. Submit event
program_data_t p = {};
if (!init_program_data(&p, ctx, YOUR_EVENT_ID))
return 0;
if (!evaluate_scope_filters(&p))
return 0;
// Extract data fields from kernel function
void *arg1 = (void *)PT_REGS_PARM1(ctx);
int arg2 = PT_REGS_PARM2(ctx);
// Apply data field-based filtering if needed
// ... your filtering logic ...
// Save data fields to event buffer
save_str_to_buf(&p.event->args_buf, arg1, 0);
save_to_submit_buf(&p.event->args_buf, &arg2, sizeof(arg2), 1);
events_perf_submit(&p, 0);
return 0;
}
2. Configure Probes in pkg/ebpf/probes/probe_group.go¶
Add the probe configuration that matches your eBPF function names:
// In pkg/ebpf/probes/probe_group.go, add to allProbes map in NewDefaultProbeGroup():
YourNewEvent: NewTraceProbe(KProbe, "your_kernel_function", "trace_your_event"),
Attachment types:
- KProbe - Attaches to kernel function entry (most common)
- KretProbe - Attaches to kernel function exit (for return values)
- Tracepoint - Attaches to predefined kernel tracepoints (stable interface)
- SyscallEnter/SyscallExit - Specialized for system call entry/exit
3. Define the Event in pkg/events/core.go¶
Choose an event ID from the appropriate range and add it to both eBPF and Go code:
Event ID Ranges: - Common events: 1-699 (most events) - Network events: 700-1999 - User-space network: 2000-3999 - Capture meta-events: 4000-4999 - Signal meta-events: 5000+
In eBPF (pkg/ebpf/c/tracee.bpf.c):
#define YOUR_EVENT_ID 42
In Go (pkg/events/core.go):
// Add to appropriate const block (around line 100-200):
YourNewEvent = 42 // Must match eBPF ID
// Add to Core variable (around line 500+):
YourNewEvent: {
id: YourNewEvent,
id32Bit: Sys32Undefined,
name: "your_event_name",
version: NewVersion(1, 0, 0),
sets: []string{"fs"}, // Choose: syscalls, fs, net, security, proc, default
fields: []DataField{
{DecodeAs: data.STR_T, ArgMeta: trace.ArgMeta{Type: "const char*", Name: "pathname"}},
{DecodeAs: data.INT_T, ArgMeta: trace.ArgMeta{Type: "int", Name: "flags"}},
// Add all event data fields
},
dependencies: Dependencies{
probes: []Probe{{handle: probes.YourNewEvent, required: true}},
},
},
4. Add Event to Protobuf Schema¶
Add event ID to protobuf enum in api/v1beta1/event.proto:
enum EventId {
// ... existing events ...
your_new_event = 42; // Must match the ID from Go/eBPF
// ... more events ...
}
Important notes: - Event IDs in protobuf must match exactly with Go constants and eBPF defines - Follow the existing naming convention: lowercase with underscores - Add the event in the appropriate section (syscalls, common events, etc.)
5. Add Event to gRPC Translation Table¶
Update the translation table in pkg/server/grpc/tracee.go:
// Add to EventTranslationTable map in appropriate section:
events.YourNewEvent: pb.EventId_your_new_event,
This table maps internal Go event IDs to external protobuf event IDs for gRPC communication.
6. Generate Protobuf Files¶
After modifying any .proto files, regenerate the Go code:
# Generate protobuf Go files from proto definitions
make -f builder/Makefile.protoc
This command uses protoc to generate:
- Go structs from protobuf messages
- gRPC service definitions
- JSON marshaling/unmarshaling code
Verify the generated files:
- api/v1beta1/*.pb.go - Generated protobuf structs
- api/v1beta1/*_grpc.pb.go - Generated gRPC service code
7. Handle Complex Data Types (If Needed)¶
If your event uses complex data types, you may need to add marshalling logic in pkg/server/grpc/event_data.go:
// Add case in parseArgument function for custom types
case *YourCustomType:
return &pb.EventValue{
Name: arg.Name,
Value: &pb.EventValue_YourCustomField{
YourCustomField: convertYourCustomType(v),
},
}, nil
For new data types:
1. Add the type definition to api/v1beta1/event_data.proto
2. Add the field to the EventValue oneof
3. Implement conversion logic in event_data.go
4. Run make -f builder/Makefile.protoc to regenerate files
Testing Your New Event¶
8. Build and Test Compilation¶
# Build Tracee with your changes
make tracee
# Verify no compilation errors
echo $? # Should be 0
9. Test Event Functionality¶
# Test that your event can be selected
sudo ./dist/tracee --events your_event_name --output json
# Test with policies
sudo ./dist/tracee --config-file your_test_policy.yaml
10. Unit Tests¶
Add unit tests for your event definition and run them:
# Run unit tests
make test-unit
# Run integration tests
make test-integration
// In appropriate _test.go file
func TestYourNewEvent(t *testing.T) {
// Test event definition
// Test data field extraction
// Test filtering behavior
}
11. Integration Tests¶
Consider adding integration tests that actually trigger your event and verify it's captured correctly.
12. Create Event Documentation¶
After everything is working, create proper documentation for your event to help users understand its purpose, usage, and configuration.
For comprehensive documentation standards and templates, see the Event Documentation Guide.
The documentation guide covers all formatting requirements, accuracy standards, and provides a complete template to ensure your documentation matches Tracee's quality standards.
Common Patterns¶
- System calls: Hook
sys_*functions, useSyscallEnter/SyscallExitprobes - Security events: Hook
security_*functions, useKProbeattachments - File operations: Hook VFS functions (e.g.,
vfs_read,vfs_write) - Network events: Hook network functions, extract connection info
Best Practices¶
- Keep eBPF programs lightweight - apply filtering early, minimize processing
- Use descriptive names - follow existing naming conventions
- Document data fields clearly - explain purpose and format of each field
- Choose appropriate event sets - helps users discover and select your event
- Test thoroughly - verify event triggers correctly and data is accurate
Troubleshooting¶
Common Issues¶
Compilation Errors:
- Verify event IDs don't conflict
- Check eBPF program section names match probe configuration
- Ensure all required headers are included
- Run make -f builder/Makefile.protoc after modifying proto files
Protobuf/gRPC Issues: - Event ID mismatches between Go, eBPF, and protobuf - Missing entry in EventTranslationTable - Protobuf files not regenerated after schema changes - Complex data types not handled in event_data.go
Runtime Issues:
- Check kernel compatibility for attachment points
- Verify probe symbols exist on target kernel
- Test with bpftrace first for complex kernel function monitoring
Event Not Triggering:
- Verify the kernel function is actually called for your test case
- Check filtering logic in eBPF program
- Use bpf_printk() for debugging eBPF code
Debugging Tools¶
# Check eBPF program loading
bpftool prog list
# Monitor eBPF logs
cat /sys/kernel/debug/tracing/trace_pipe
# Test kernel symbol availability
cat /proc/kallsyms | grep your_symbol
Getting Help¶
- GitHub Issues: Ask questions about event implementation
- Discussions: Discuss design decisions for complex events
- Code Review: Submit WIP PRs for feedback on approach