Skip to content

Commit 920ded7

Browse files
committed
Stack traces: add stack trace pseudo event
This event allows the user to control which events stack traces should be produced for (via a parameter) and in which scopes. The list of events that stack traces should be produced for is populated in a BPF map to be used later.
1 parent 8965bc0 commit 920ded7

File tree

6 files changed

+91
-0
lines changed

6 files changed

+91
-0
lines changed

pkg/ebpf/c/stack_unwind/maps.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#ifndef __STACK_UNWIND_MAPS_H__
2+
#define __STACK_UNWIND_MAPS_H__
3+
4+
#include <maps.h>
5+
6+
struct stack_unwind_enabled_events {
7+
__uint(type, BPF_MAP_TYPE_HASH);
8+
__uint(max_entries, MAX_EVENT_ID);
9+
__type(key, u32);
10+
__type(value, u32);
11+
} su_enabled_evts SEC(".maps");
12+
13+
#endif /* __STACK_UNWIND_MAPS_H__ */

pkg/ebpf/c/stack_unwind/unwind.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#ifndef __STACK_UNWIND_H__
2+
#define __STACK_UNWIND_H__
3+
4+
#include "maps.h"
5+
6+
statfunc bool stack_trace_enabled_for_event(u32 event_id)
7+
{
8+
return bpf_map_lookup_elem(&su_enabled_evts, &event_id) != NULL;
9+
}
10+
11+
#endif /* __STACK_UNWIND_H__ */

pkg/ebpf/c/tracee.bpf.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
#include <common/probes.h>
4040
#include <common/signal.h>
4141

42+
#include <stack_unwind/unwind.h>
43+
4244
char LICENSE[] SEC("license") = "GPL";
4345

4446
// trace/events/syscalls.h: TP_PROTO(struct pt_regs *regs, long id)

pkg/ebpf/event_parameters.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type eventParameterHandler func(t *Tracee, eventParams []map[string]filters.Filt
1818
var eventParameterHandlers = map[events.ID]eventParameterHandler{
1919
events.SuspiciousSyscallSource: prepareSuspiciousSyscallSource,
2020
events.StackPivot: prepareStackPivot,
21+
events.StackTrace: populateMapsStackTrace,
2122
}
2223

2324
// handleEventParameters performs initialization actions according to event parameters,
@@ -157,3 +158,48 @@ func prepareSuspiciousSyscallSource(t *Tracee, eventParams []map[string]filters.
157158
func prepareStackPivot(t *Tracee, eventParams []map[string]filters.Filter[*filters.StringFilter]) error {
158159
return registerSyscallChecker(t, eventParams, "syscall", "stack_pivot_syscalls")
159160
}
161+
162+
func populateMapsStackTrace(t *Tracee, eventParams []map[string]filters.Filter[*filters.StringFilter]) error {
163+
// Get events to produce stack traces for
164+
selectedEvents := map[string]struct{}{}
165+
for _, policyParams := range eventParams {
166+
eventNamesParam, ok := policyParams["events"].(*filters.StringFilter)
167+
if !ok {
168+
return errfmt.Errorf("invalid argument name 'events'")
169+
}
170+
for _, eventName := range eventNamesParam.Equal() {
171+
selectedEvents[eventName] = struct{}{}
172+
}
173+
}
174+
175+
// If "all" was specified, add all events to selectedEvents
176+
if _, found := selectedEvents["all"]; found {
177+
selectedEvents = make(map[string]struct{}, events.MaxCommonID)
178+
for id := range events.MaxCommonID {
179+
d := events.Core.GetDefinitionByID(id)
180+
if d.Valid() {
181+
selectedEvents[d.GetName()] = struct{}{}
182+
}
183+
}
184+
}
185+
186+
logger.Debugw("stack traces are enabled", "selected events", selectedEvents)
187+
188+
// Update selected events map
189+
eventsMap, err := t.bpfModule.GetMap("su_enabled_evts")
190+
if err != nil {
191+
return errfmt.Errorf("could not get BPF map 'su_enabled_evts': %v", err)
192+
}
193+
for event := range selectedEvents {
194+
eventID, found := events.Core.GetDefinitionIDByName(event)
195+
if !found {
196+
return errfmt.Errorf("invalid event %s", event)
197+
}
198+
val := uint32(1)
199+
if err = eventsMap.Update(unsafe.Pointer(&eventID), unsafe.Pointer(&val)); err != nil {
200+
return errfmt.Errorf("failed updating stack unwind events map: %v", err)
201+
}
202+
}
203+
204+
return nil
205+
}

pkg/events/core.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ const (
116116
SecurityTaskSetrlimit
117117
SecuritySettime64
118118
ChmodCommon
119+
StackTrace // stack trace pseudo event
119120
MaxCommonID
120121
)
121122

@@ -13094,6 +13095,20 @@ var CoreEvents = map[ID]Definition{
1309413095
{Type: "unsigned long", Name: "vma_flags"},
1309513096
},
1309613097
},
13098+
// Stack trace pseudo event
13099+
// While this event is not internal (it needs to be selected by the user),
13100+
// it is never submitted to userspace.
13101+
// It's only used as a convenience method to select which events (and scopes)
13102+
// stack traces should be produced for and to manage its dependencies.
13103+
StackTrace: {
13104+
id: StackTrace,
13105+
id32Bit: Sys32Undefined,
13106+
name: "stack_trace",
13107+
version: NewVersion(1, 0, 0),
13108+
fields: []trace.ArgMeta{
13109+
{Type: "string", Name: "events"}, // pseudo field, only used as a parameter
13110+
},
13111+
},
1309713112
//
1309813113
// Begin of Signal Events (Control Plane)
1309913114
//

pkg/events/definition.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,7 @@ func (d Definition) GetProperties() map[string]interface{} {
118118
func (d Definition) NotValid() bool {
119119
return d.id == Undefined || d.id == Unsupported
120120
}
121+
122+
func (d Definition) Valid() bool {
123+
return !d.NotValid()
124+
}

0 commit comments

Comments
 (0)