github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/gadgets/trace/signal/tracer/bpf/sigsnoop.bpf.c (about)

     1  // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
     2  /* Copyright (c) 2021~2022 Hengqi Chen */
     3  #include <vmlinux.h>
     4  #include <bpf/bpf_core_read.h>
     5  #include <bpf/bpf_helpers.h>
     6  #include "sigsnoop.h"
     7  #include <gadget/mntns_filter.h>
     8  
     9  #define MAX_ENTRIES 10240
    10  
    11  const volatile pid_t filtered_pid = 0;
    12  const volatile int target_signal = 0;
    13  const volatile bool failed_only = false;
    14  
    15  // we need this to make sure the compiler doesn't remove our struct
    16  const struct event *unusedevent __attribute__((unused));
    17  
    18  struct {
    19  	__uint(type, BPF_MAP_TYPE_HASH);
    20  	__uint(max_entries, MAX_ENTRIES);
    21  	__type(key, __u32);
    22  	__type(value, struct event);
    23  } values SEC(".maps");
    24  
    25  struct {
    26  	__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
    27  	__uint(key_size, sizeof(__u32));
    28  	__uint(value_size, sizeof(__u32));
    29  } events SEC(".maps");
    30  
    31  static int probe_entry(pid_t tpid, int sig)
    32  {
    33  	struct event event = {};
    34  	__u64 pid_tgid;
    35  	__u32 pid, tid;
    36  	u64 mntns_id;
    37  
    38  	mntns_id = gadget_get_mntns_id();
    39  
    40  	if (gadget_should_discard_mntns_id(mntns_id))
    41  		return 0;
    42  
    43  	if (target_signal && sig != target_signal)
    44  		return 0;
    45  
    46  	pid_tgid = bpf_get_current_pid_tgid();
    47  	pid = pid_tgid >> 32;
    48  	tid = (__u32)pid_tgid;
    49  	if (filtered_pid && pid != filtered_pid)
    50  		return 0;
    51  
    52  	event.pid = pid;
    53  	event.tpid = tpid;
    54  	event.sig = sig;
    55  	event.mntns_id = mntns_id;
    56  	bpf_get_current_comm(event.comm, sizeof(event.comm));
    57  	bpf_map_update_elem(&values, &tid, &event, BPF_ANY);
    58  	return 0;
    59  }
    60  
    61  static int probe_exit(void *ctx, int ret)
    62  {
    63  	__u64 pid_tgid = bpf_get_current_pid_tgid();
    64  	__u64 uid_gid = bpf_get_current_uid_gid();
    65  	__u32 tid = (__u32)pid_tgid;
    66  	struct event *eventp;
    67  
    68  	eventp = bpf_map_lookup_elem(&values, &tid);
    69  	if (!eventp)
    70  		return 0;
    71  
    72  	if (failed_only && ret >= 0)
    73  		goto cleanup;
    74  
    75  	eventp->ret = ret;
    76  	eventp->timestamp = bpf_ktime_get_boot_ns();
    77  	eventp->uid = (u32)uid_gid;
    78  	eventp->gid = (u32)(uid_gid >> 32);
    79  	bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, eventp,
    80  			      sizeof(*eventp));
    81  
    82  cleanup:
    83  	bpf_map_delete_elem(&values, &tid);
    84  	return 0;
    85  }
    86  
    87  SEC("tracepoint/syscalls/sys_enter_kill")
    88  int ig_sig_kill_e(struct syscall_trace_enter *ctx)
    89  {
    90  	pid_t tpid = (pid_t)ctx->args[0];
    91  	int sig = (int)ctx->args[1];
    92  
    93  	return probe_entry(tpid, sig);
    94  }
    95  
    96  SEC("tracepoint/syscalls/sys_exit_kill")
    97  int ig_sig_kill_x(struct syscall_trace_exit *ctx)
    98  {
    99  	return probe_exit(ctx, ctx->ret);
   100  }
   101  
   102  SEC("tracepoint/syscalls/sys_enter_tkill")
   103  int ig_sig_tkill_e(struct syscall_trace_enter *ctx)
   104  {
   105  	pid_t tpid = (pid_t)ctx->args[0];
   106  	int sig = (int)ctx->args[1];
   107  
   108  	return probe_entry(tpid, sig);
   109  }
   110  
   111  SEC("tracepoint/syscalls/sys_exit_tkill")
   112  int ig_sig_tkill_x(struct syscall_trace_exit *ctx)
   113  {
   114  	return probe_exit(ctx, ctx->ret);
   115  }
   116  
   117  SEC("tracepoint/syscalls/sys_enter_tgkill")
   118  int ig_sig_tgkill_e(struct syscall_trace_enter *ctx)
   119  {
   120  	pid_t tpid = (pid_t)ctx->args[1];
   121  	int sig = (int)ctx->args[2];
   122  
   123  	return probe_entry(tpid, sig);
   124  }
   125  
   126  SEC("tracepoint/syscalls/sys_exit_tgkill")
   127  int ig_sig_tgkill_x(struct syscall_trace_exit *ctx)
   128  {
   129  	return probe_exit(ctx, ctx->ret);
   130  }
   131  
   132  SEC("tracepoint/signal/signal_generate")
   133  int ig_sig_generate(struct trace_event_raw_signal_generate *ctx)
   134  {
   135  	struct event event = {};
   136  	pid_t tpid = ctx->pid;
   137  	int ret = ctx->errno;
   138  	int sig = ctx->sig;
   139  	__u64 pid_tgid;
   140  	__u32 pid;
   141  	u64 mntns_id;
   142  	__u64 uid_gid = bpf_get_current_uid_gid();
   143  
   144  	mntns_id = gadget_get_mntns_id();
   145  
   146  	if (gadget_should_discard_mntns_id(mntns_id))
   147  		return 0;
   148  
   149  	if (failed_only && ret == 0)
   150  		return 0;
   151  
   152  	if (target_signal && sig != target_signal)
   153  		return 0;
   154  
   155  	pid_tgid = bpf_get_current_pid_tgid();
   156  	pid = pid_tgid >> 32;
   157  	if (filtered_pid && pid != filtered_pid)
   158  		return 0;
   159  
   160  	event.pid = pid;
   161  	event.tpid = tpid;
   162  	event.mntns_id = mntns_id;
   163  	event.sig = sig;
   164  	event.ret = ret;
   165  	event.uid = (u32)uid_gid;
   166  	event.gid = (u32)(uid_gid >> 32);
   167  	bpf_get_current_comm(event.comm, sizeof(event.comm));
   168  	event.timestamp = bpf_ktime_get_boot_ns();
   169  	bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event,
   170  			      sizeof(event));
   171  	return 0;
   172  }
   173  
   174  char LICENSE[] SEC("license") = "Dual BSD/GPL";