Skip to content

Commit

Permalink
fix: get exit code and signal values
Browse files Browse the repository at this point in the history
When a process exits normally via exit(n), the exit code is
stored in the upper byte (exit_code << 8). The lower byte is
used for signal information if the process was terminated by
a signal.

Also, align the type of exit_code used at struct task_struct.
  • Loading branch information
rscampos committed Jan 30, 2025
1 parent 7bd8324 commit a13d497
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 17 deletions.
4 changes: 2 additions & 2 deletions pkg/ebpf/c/common/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ statfunc u64 get_task_start_time(struct task_struct *task);
statfunc u32 get_task_host_pid(struct task_struct *task);
statfunc u32 get_task_host_tgid(struct task_struct *task);
statfunc struct task_struct *get_parent_task(struct task_struct *task);
statfunc u32 get_task_exit_code(struct task_struct *task);
statfunc int get_task_exit_code(struct task_struct *task);
statfunc int get_task_parent_flags(struct task_struct *task);
statfunc const struct cred *get_task_real_cred(struct task_struct *task);

Expand Down Expand Up @@ -195,7 +195,7 @@ statfunc struct task_struct *get_leader_task(struct task_struct *task)
return BPF_CORE_READ(task, group_leader);
}

statfunc u32 get_task_exit_code(struct task_struct *task)
statfunc int get_task_exit_code(struct task_struct *task)
{
return BPF_CORE_READ(task, exit_code);
}
Expand Down
26 changes: 20 additions & 6 deletions pkg/ebpf/c/tracee.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1547,7 +1547,6 @@ int tracepoint__sched__sched_process_exit(struct bpf_raw_tracepoint_args *ctx)
if (!policies_matched(p.event))
return 0;

long exit_code = get_task_exit_code(p.event->task);
bool group_dead = false;
struct task_struct *task = p.event->task;
struct signal_struct *signal = BPF_CORE_READ(task, signal);
Expand All @@ -1559,8 +1558,16 @@ int tracepoint__sched__sched_process_exit(struct bpf_raw_tracepoint_args *ctx)
group_dead = true;
}

save_to_submit_buf(&p.event->args_buf, (void *) &exit_code, sizeof(long), 0);
save_to_submit_buf(&p.event->args_buf, (void *) &group_dead, sizeof(bool), 1);
// extract exit code and signal values
int exit_code = get_task_exit_code(p.event->task);
int exit_code_real = exit_code >> 8;

save_to_submit_buf(&p.event->args_buf, (void *) &exit_code_real, sizeof(int), 0);
if (task_flags & PF_SIGNALED) {
int signal_code = exit_code & 0xFF;
save_to_submit_buf(&p.event->args_buf, (void *) &signal_code, sizeof(int), 1);
}
save_to_submit_buf(&p.event->args_buf, (void *) &group_dead, sizeof(bool), 2);

events_perf_submit(&p, 0);

Expand Down Expand Up @@ -7155,10 +7162,17 @@ int sched_process_exit_signal(struct bpf_raw_tracepoint_args *ctx)
if (live.counter == 0)
group_dead = true;

long exit_code = get_task_exit_code(task);
// extract exit code and signal values
int task_flags = get_task_flags(task);
int exit_code = get_task_exit_code(task);
int exit_code_real = exit_code >> 8;

save_to_submit_buf(&signal->args_buf, (void *) &exit_code, sizeof(long), 4);
save_to_submit_buf(&signal->args_buf, (void *) &group_dead, sizeof(bool), 5);
save_to_submit_buf(&signal->args_buf, (void *) &exit_code_real, sizeof(int), 4);
if (task_flags & PF_SIGNALED) {
int signal_code = exit_code & 0xFF;
save_to_submit_buf(&signal->args_buf, (void *) &signal_code, sizeof(int), 5);
}
save_to_submit_buf(&signal->args_buf, (void *) &group_dead, sizeof(bool), 6);

signal_perf_submit(ctx, signal);

Expand Down
6 changes: 5 additions & 1 deletion pkg/ebpf/controlplane/processes.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,11 @@ func (ctrl *Controller) procTreeExitProcessor(args []trace.Argument) error {
// }

// // Exit logic arguments
// exitFeed.ExitCode, err = parse.ArgVal[int64](args, "exit_code")
// exitFeed.ExitCode, err = parse.ArgVal[int32](args, "exit_code")
// if err != nil {
// return err
// }
// exitFeed.SignalCode, err = parse.ArgVal[int32](args, "signal_code")
// if err != nil {
// return err
// }
Expand Down
3 changes: 2 additions & 1 deletion pkg/ebpf/controlplane/processes_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ func Benchmark_procTreeExitProcessor(b *testing.B) {
{ArgMeta: trace.ArgMeta{Name: "task_hash"}, Value: uint32(1)},
{ArgMeta: trace.ArgMeta{Name: "parent_hash"}, Value: uint32(1)},
{ArgMeta: trace.ArgMeta{Name: "leader_hash"}, Value: uint32(1)},
{ArgMeta: trace.ArgMeta{Name: "exit_code"}, Value: int64(1)},
{ArgMeta: trace.ArgMeta{Name: "exit_code"}, Value: int32(1)},
{ArgMeta: trace.ArgMeta{Name: "signal_code"}, Value: int32(1)},
{ArgMeta: trace.ArgMeta{Name: "process_group_exit"}, Value: true},
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/ebpf/processor_proctree.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ func (t *Tracee) procTreeExitProcessor(event *trace.Event) error {
defer t.processTree.PutExitFeedInPool(exitFeed)

// // Exit logic arguments
// exitFeed.ExitCode, err = parse.ArgVal[int64](event.Args, "exit_code")
// exitFeed.ExitCode, err = parse.ArgVal[int32](event.Args, "exit_code")
// if err != nil {
// return err
// }
Expand Down
3 changes: 2 additions & 1 deletion pkg/ebpf/processor_proctree_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ func Benchmark_procTreeExitProcessor(b *testing.B) {

event := &trace.Event{
Args: []trace.Argument{
{ArgMeta: trace.ArgMeta{Name: "exit_code"}, Value: int64(1)},
{ArgMeta: trace.ArgMeta{Name: "exit_code"}, Value: int32(1)},
{ArgMeta: trace.ArgMeta{Name: "signal_code"}, Value: int32(1)},
{ArgMeta: trace.ArgMeta{Name: "process_group_exit"}, Value: true},
},
}
Expand Down
6 changes: 4 additions & 2 deletions pkg/events/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -11213,7 +11213,8 @@ var CoreEvents = map[ID]Definition{
},
sets: []string{"proc", "proc_life"},
fields: []trace.ArgMeta{
{Type: "long", Name: "exit_code"},
{Type: "int", Name: "exit_code"},
{Type: "int", Name: "signal_code"},
// The field value represents that all threads exited at the event time.
// Multiple exits of threads of the same process group at the same time could result that all threads exit
// events would have 'true' value in this field altogether.
Expand Down Expand Up @@ -13234,7 +13235,8 @@ var CoreEvents = map[ID]Definition{
{Type: "u32", Name: "task_hash"},
{Type: "u32", Name: "parent_hash"},
{Type: "u32", Name: "leader_hash"},
{Type: "long", Name: "exit_code"},
{Type: "int", Name: "exit_code"},
{Type: "int", Name: "signal_code"},
{Type: "bool", Name: "process_group_exit"},
},
},
Expand Down
3 changes: 2 additions & 1 deletion pkg/proctree/proctree_feed.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,8 @@ type ExitFeed struct {
TaskHash uint32
ParentHash uint32
LeaderHash uint32
ExitCode int64
ExitCode int32
SignalCode int32
Group bool
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/server/grpc/event_data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,15 @@ func Test_getEventData(t *testing.T) {
args: []trace.Argument{
{
ArgMeta: trace.ArgMeta{
Name: "exit_code",
Name: "newmask",
Type: "long",
},
Value: int64(1000),
},
},
expected: []*pb.EventValue{
{
Name: "exit_code",
Name: "newmask",
Value: &pb.EventValue_Int64{
Int64: 1000,
},
Expand Down

0 comments on commit a13d497

Please sign in to comment.