forked from iovisor/bcc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a sigsnoop tool which can be used to trace signals system-wide. This is done by instrumenting signal/signal_generate tracepoint. Also add a killsnoop which instruments signal-related syscalls and behave the same as BCC's killsnoop. Output of killsnoop: ```shell sudo ./killsnoop TIME PID COMM SIG TPID RESULT 00:00:23 799 rsyslogd 22 799 0 ``` Output of sigsnoop: ```shell sudo ./sigsnoop TIME PID COMM SIG TPID RESULT 22:38:21 830 containerd 23 905 0 22:38:21 178088 gopls 23 178088 0 22:38:24 830 containerd 23 905 0 22:38:24 178088 gopls 23 178088 0 22:38:24 830 containerd 23 906 0 22:38:25 178088 gopls 23 178088 0 ``` Signed-off-by: Hengqi Chen <[email protected]>
- Loading branch information
1 parent
e9c5931
commit dca2d00
Showing
6 changed files
with
482 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) | ||
/* Copyright (c) 2021~2022 Hengqi Chen */ | ||
#include <vmlinux.h> | ||
#include <bpf/bpf_helpers.h> | ||
#include "sigsnoop.h" | ||
|
||
#define MAX_ENTRIES 10240 | ||
|
||
const volatile pid_t filtered_pid = 0; | ||
const volatile int target_signal = 0; | ||
const volatile bool failed_only = false; | ||
|
||
struct { | ||
__uint(type, BPF_MAP_TYPE_HASH); | ||
__uint(max_entries, MAX_ENTRIES); | ||
__type(key, __u32); | ||
__type(value, struct event); | ||
} values SEC(".maps"); | ||
|
||
struct { | ||
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); | ||
__uint(key_size, sizeof(__u32)); | ||
__uint(value_size, sizeof(__u32)); | ||
} events SEC(".maps"); | ||
|
||
static int probe_entry(pid_t tpid, int sig) | ||
{ | ||
struct event event = {}; | ||
__u64 pid_tgid; | ||
__u32 pid, tid; | ||
|
||
if (target_signal && sig != target_signal) | ||
return 0; | ||
|
||
pid_tgid = bpf_get_current_pid_tgid(); | ||
pid = pid_tgid >> 32; | ||
tid = (__u32)pid_tgid; | ||
if (filtered_pid && pid != filtered_pid) | ||
return 0; | ||
|
||
event.pid = pid; | ||
event.tpid = tpid; | ||
event.sig = sig; | ||
bpf_get_current_comm(event.comm, sizeof(event.comm)); | ||
bpf_map_update_elem(&values, &tid, &event, BPF_ANY); | ||
return 0; | ||
} | ||
|
||
static int probe_exit(void *ctx, int ret) | ||
{ | ||
__u64 pid_tgid = bpf_get_current_pid_tgid(); | ||
__u32 tid = (__u32)pid_tgid; | ||
struct event *eventp; | ||
|
||
eventp = bpf_map_lookup_elem(&values, &tid); | ||
if (!eventp) | ||
return 0; | ||
|
||
if (failed_only && ret >= 0) | ||
goto cleanup; | ||
|
||
eventp->ret = ret; | ||
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, eventp, sizeof(*eventp)); | ||
|
||
cleanup: | ||
bpf_map_delete_elem(&values, &tid); | ||
return 0; | ||
} | ||
|
||
SEC("tracepoint/syscalls/sys_enter_kill") | ||
int kill_entry(struct trace_event_raw_sys_enter *ctx) | ||
{ | ||
pid_t tpid = (pid_t)ctx->args[0]; | ||
int sig = (int)ctx->args[1]; | ||
|
||
return probe_entry(tpid, sig); | ||
} | ||
|
||
SEC("tracepoint/syscalls/sys_exit_kill") | ||
int kill_exit(struct trace_event_raw_sys_exit *ctx) | ||
{ | ||
return probe_exit(ctx, ctx->ret); | ||
} | ||
|
||
SEC("tracepoint/syscalls/sys_enter_tkill") | ||
int tkill_entry(struct trace_event_raw_sys_enter *ctx) | ||
{ | ||
pid_t tpid = (pid_t)ctx->args[0]; | ||
int sig = (int)ctx->args[1]; | ||
|
||
return probe_entry(tpid, sig); | ||
} | ||
|
||
SEC("tracepoint/syscalls/sys_exit_tkill") | ||
int tkill_exit(struct trace_event_raw_sys_exit *ctx) | ||
{ | ||
return probe_exit(ctx, ctx->ret); | ||
} | ||
|
||
SEC("tracepoint/syscalls/sys_enter_tgkill") | ||
int tgkill_entry(struct trace_event_raw_sys_enter *ctx) | ||
{ | ||
pid_t tpid = (pid_t)ctx->args[1]; | ||
int sig = (int)ctx->args[2]; | ||
|
||
return probe_entry(tpid, sig); | ||
} | ||
|
||
SEC("tracepoint/syscalls/sys_exit_tgkill") | ||
int tgkill_exit(struct trace_event_raw_sys_exit *ctx) | ||
{ | ||
return probe_exit(ctx, ctx->ret); | ||
} | ||
|
||
SEC("tracepoint/signal/signal_generate") | ||
int sig_trace(struct trace_event_raw_signal_generate *ctx) | ||
{ | ||
struct event event = {}; | ||
pid_t tpid = ctx->pid; | ||
int ret = ctx->errno; | ||
int sig = ctx->sig; | ||
__u64 pid_tgid; | ||
__u32 pid; | ||
|
||
if (failed_only && ret == 0) | ||
return 0; | ||
|
||
if (target_signal && sig != target_signal) | ||
return 0; | ||
|
||
pid_tgid = bpf_get_current_pid_tgid(); | ||
pid = pid_tgid >> 32; | ||
if (filtered_pid && pid != filtered_pid) | ||
return 0; | ||
|
||
event.pid = pid; | ||
event.tpid = tpid; | ||
event.sig = sig; | ||
event.ret = ret; | ||
bpf_get_current_comm(event.comm, sizeof(event.comm)); | ||
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event, sizeof(event)); | ||
return 0; | ||
} | ||
|
||
char LICENSE[] SEC("license") = "Dual BSD/GPL"; |
Oops, something went wrong.