github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/gadgets/trace/mount/tracer/bpf/mountsnoop.bpf.c (about) 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* Copyright (c) 2021 Hengqi Chen */ 3 #include <vmlinux.h> 4 #include <bpf/bpf_helpers.h> 5 #include <bpf/bpf_core_read.h> 6 #include "mountsnoop.h" 7 #include <gadget/mntns_filter.h> 8 9 #define MAX_ENTRIES 10240 10 11 const volatile pid_t target_pid = 0; 12 13 // we need this to make sure the compiler doesn't remove our struct 14 const struct event *unusedevent __attribute__((unused)); 15 16 struct { 17 __uint(type, BPF_MAP_TYPE_HASH); 18 __uint(max_entries, MAX_ENTRIES); 19 __type(key, __u32); 20 __type(value, struct arg); 21 } args SEC(".maps"); 22 23 struct { 24 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 25 __uint(max_entries, 1); 26 __type(key, int); 27 __type(value, struct event); 28 } heap SEC(".maps"); 29 30 struct { 31 __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); 32 __uint(key_size, sizeof(__u32)); 33 __uint(value_size, sizeof(__u32)); 34 } events SEC(".maps"); 35 36 // TODO: have to use "inline" to avoid this error: 37 // bpf/mountsnoop.bpf.c:41:12: error: defined with too many args 38 // static int probe_entry(const char *src, const char *dest, const char *fs, 39 static __always_inline int probe_entry(const char *src, const char *dest, 40 const char *fs, __u64 flags, 41 const char *data, enum op op) 42 { 43 __u64 pid_tgid = bpf_get_current_pid_tgid(); 44 __u32 pid = pid_tgid >> 32; 45 __u32 tid = (__u32)pid_tgid; 46 struct arg arg = {}; 47 u64 mntns_id; 48 49 mntns_id = gadget_get_mntns_id(); 50 51 if (gadget_should_discard_mntns_id(mntns_id)) 52 return 0; 53 54 if (target_pid && target_pid != pid) 55 return 0; 56 57 arg.ts = bpf_ktime_get_ns(); 58 arg.flags = flags; 59 arg.src = src; 60 arg.dest = dest; 61 arg.fs = fs; 62 arg.data = data; 63 arg.op = op; 64 bpf_map_update_elem(&args, &tid, &arg, BPF_ANY); 65 66 return 0; 67 }; 68 69 static int probe_exit(void *ctx, int ret) 70 { 71 __u64 pid_tgid = bpf_get_current_pid_tgid(); 72 __u32 pid = pid_tgid >> 32; 73 __u32 tid = (__u32)pid_tgid; 74 struct arg *argp; 75 struct event *eventp; 76 int zero = 0; 77 u64 mntns_id; 78 79 argp = bpf_map_lookup_elem(&args, &tid); 80 if (!argp) 81 return 0; 82 83 eventp = bpf_map_lookup_elem(&heap, &zero); 84 if (!eventp) 85 goto cleanup; 86 87 eventp->mount_ns_id = gadget_get_mntns_id(); 88 eventp->timestamp = bpf_ktime_get_boot_ns(); 89 eventp->delta = bpf_ktime_get_ns() - argp->ts; 90 eventp->flags = argp->flags; 91 eventp->pid = pid; 92 eventp->tid = tid; 93 eventp->ret = ret; 94 eventp->op = argp->op; 95 bpf_get_current_comm(&eventp->comm, sizeof(eventp->comm)); 96 if (argp->src) 97 bpf_probe_read_user_str(eventp->src, sizeof(eventp->src), 98 argp->src); 99 else 100 eventp->src[0] = '\0'; 101 if (argp->dest) 102 bpf_probe_read_user_str(eventp->dest, sizeof(eventp->dest), 103 argp->dest); 104 else 105 eventp->dest[0] = '\0'; 106 if (argp->fs) 107 bpf_probe_read_user_str(eventp->fs, sizeof(eventp->fs), 108 argp->fs); 109 else 110 eventp->fs[0] = '\0'; 111 if (argp->data) 112 bpf_probe_read_user_str(eventp->data, sizeof(eventp->data), 113 argp->data); 114 else 115 eventp->data[0] = '\0'; 116 117 bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, eventp, 118 sizeof(*eventp)); 119 120 cleanup: 121 bpf_map_delete_elem(&args, &tid); 122 return 0; 123 } 124 125 SEC("tracepoint/syscalls/sys_enter_mount") 126 int ig_mount_e(struct syscall_trace_enter *ctx) 127 { 128 const char *src = (const char *)ctx->args[0]; 129 const char *dest = (const char *)ctx->args[1]; 130 const char *fs = (const char *)ctx->args[2]; 131 __u64 flags = (__u64)ctx->args[3]; 132 const char *data = (const char *)ctx->args[4]; 133 134 return probe_entry(src, dest, fs, flags, data, MOUNT); 135 } 136 137 SEC("tracepoint/syscalls/sys_exit_mount") 138 int ig_mount_x(struct syscall_trace_exit *ctx) 139 { 140 return probe_exit(ctx, (int)ctx->ret); 141 } 142 143 SEC("tracepoint/syscalls/sys_enter_umount") 144 int ig_umount_e(struct syscall_trace_enter *ctx) 145 { 146 const char *dest = (const char *)ctx->args[0]; 147 __u64 flags = (__u64)ctx->args[1]; 148 149 return probe_entry(NULL, dest, NULL, flags, NULL, UMOUNT); 150 } 151 152 SEC("tracepoint/syscalls/sys_exit_umount") 153 int ig_umount_x(struct syscall_trace_exit *ctx) 154 { 155 return probe_exit(ctx, (int)ctx->ret); 156 } 157 158 char LICENSE[] SEC("license") = "Dual BSD/GPL";