Skip to content

Commit

Permalink
libbpf-tools: add sigsnoop
Browse files Browse the repository at this point in the history
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
chenhengqi authored and yonghong-song committed Jul 22, 2022
1 parent e9c5931 commit dca2d00
Show file tree
Hide file tree
Showing 6 changed files with 482 additions and 3 deletions.
6 changes: 4 additions & 2 deletions libbpf-tools/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@
/funclatency
/gethostlatency
/hardirqs
/killsnoop
/klockstat
/ksnoop
/llcstat
/nfsdist
/nfsslower
/mdflush
/mountsnoop
/nfsdist
/nfsslower
/numamove
/offcputime
/oomkill
Expand All @@ -39,6 +40,7 @@
/runqlat
/runqlen
/runqslower
/sigsnoop
/slabratetop
/softirqs
/solisten
Expand Down
8 changes: 7 additions & 1 deletion libbpf-tools/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ APPS = \
runqlat \
runqlen \
runqslower \
sigsnoop \
slabratetop \
softirqs \
solisten \
Expand All @@ -71,7 +72,8 @@ export OUTPUT BPFTOOL ARCH BTFHUB_ARCHIVE APPS

FSDIST_ALIASES = btrfsdist ext4dist nfsdist xfsdist
FSSLOWER_ALIASES = btrfsslower ext4slower nfsslower xfsslower
APP_ALIASES = $(FSDIST_ALIASES) $(FSSLOWER_ALIASES)
SIGSNOOP_ALIAS = killsnoop
APP_ALIASES = $(FSDIST_ALIASES) $(FSSLOWER_ALIASES) ${SIGSNOOP_ALIAS}

COMMON_OBJ = \
$(OUTPUT)/trace_helpers.o \
Expand Down Expand Up @@ -171,6 +173,10 @@ $(FSDIST_ALIASES): fsdist
$(call msg,SYMLINK,$@)
$(Q)ln -f -s $^ $@

$(SIGSNOOP_ALIAS): sigsnoop
$(call msg,SYMLINK,$@)
$(Q)ln -f -s $^ $@

install: $(APPS) $(APP_ALIASES)
$(call msg, INSTALL libbpf-tools)
$(Q)$(INSTALL) -m 0755 -d $(DESTDIR)$(prefix)/bin
Expand Down
145 changes: 145 additions & 0 deletions libbpf-tools/sigsnoop.bpf.c
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";
Loading

0 comments on commit dca2d00

Please sign in to comment.