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 <bpf/bpf_tracing.h>
7
8 #include "compat.bpf.h"
9 #include "mountsnoop.h"
10
11 #define MAX_ENTRIES 10240
12
13 const volatile pid_t target_pid = 0;
14
15 struct {
16 __uint(type, BPF_MAP_TYPE_HASH);
17 __uint(max_entries, MAX_ENTRIES);
18 __type(key, __u32);
19 __type(value, struct arg);
20 } args SEC(".maps");
21
probe_entry(const char * src,const char * dest,const char * fs,__u64 flags,const char * data,enum op op)22 static int probe_entry(const char *src, const char *dest, const char *fs,
23 __u64 flags, const char *data, enum op op)
24 {
25 __u64 pid_tgid = bpf_get_current_pid_tgid();
26 __u32 pid = pid_tgid >> 32;
27 __u32 tid = (__u32)pid_tgid;
28 struct arg arg = {};
29
30 if (target_pid && target_pid != pid)
31 return 0;
32
33 arg.ts = bpf_ktime_get_ns();
34 arg.flags = flags;
35 arg.src = src;
36 arg.dest = dest;
37 arg.fs = fs;
38 arg.data= data;
39 arg.op = op;
40 bpf_map_update_elem(&args, &tid, &arg, BPF_ANY);
41 return 0;
42 };
43
probe_exit(void * ctx,int ret)44 static int probe_exit(void *ctx, int ret)
45 {
46 __u64 pid_tgid = bpf_get_current_pid_tgid();
47 __u32 pid = pid_tgid >> 32;
48 __u32 tid = (__u32)pid_tgid;
49 struct task_struct *task;
50 struct event *eventp;
51 struct arg *argp;
52
53 argp = bpf_map_lookup_elem(&args, &tid);
54 if (!argp)
55 return 0;
56
57 eventp = reserve_buf(sizeof(*eventp));
58 if (!eventp)
59 goto cleanup;
60
61 task = (struct task_struct *)bpf_get_current_task();
62 eventp->delta = bpf_ktime_get_ns() - argp->ts;
63 eventp->flags = argp->flags;
64 eventp->pid = pid;
65 eventp->tid = tid;
66 eventp->mnt_ns = BPF_CORE_READ(task, nsproxy, mnt_ns, ns.inum);
67 eventp->ret = ret;
68 eventp->op = argp->op;
69 bpf_get_current_comm(&eventp->comm, sizeof(eventp->comm));
70 if (argp->src)
71 bpf_probe_read_user_str(eventp->src, sizeof(eventp->src), argp->src);
72 else
73 eventp->src[0] = '\0';
74 if (argp->dest)
75 bpf_probe_read_user_str(eventp->dest, sizeof(eventp->dest), argp->dest);
76 else
77 eventp->dest[0] = '\0';
78 if (argp->fs)
79 bpf_probe_read_user_str(eventp->fs, sizeof(eventp->fs), argp->fs);
80 else
81 eventp->fs[0] = '\0';
82 if (argp->data)
83 bpf_probe_read_user_str(eventp->data, sizeof(eventp->data), argp->data);
84 else
85 eventp->data[0] = '\0';
86
87 submit_buf(ctx, eventp, sizeof(*eventp));
88
89 cleanup:
90 bpf_map_delete_elem(&args, &tid);
91 return 0;
92 }
93
94 SEC("tracepoint/syscalls/sys_enter_mount")
mount_entry(struct trace_event_raw_sys_enter * ctx)95 int mount_entry(struct trace_event_raw_sys_enter *ctx)
96 {
97 const char *src = (const char *)ctx->args[0];
98 const char *dest = (const char *)ctx->args[1];
99 const char *fs = (const char *)ctx->args[2];
100 __u64 flags = (__u64)ctx->args[3];
101 const char *data = (const char *)ctx->args[4];
102
103 return probe_entry(src, dest, fs, flags, data, MOUNT);
104 }
105
106 SEC("tracepoint/syscalls/sys_exit_mount")
mount_exit(struct trace_event_raw_sys_exit * ctx)107 int mount_exit(struct trace_event_raw_sys_exit *ctx)
108 {
109 return probe_exit(ctx, (int)ctx->ret);
110 }
111
112 SEC("tracepoint/syscalls/sys_enter_umount")
umount_entry(struct trace_event_raw_sys_enter * ctx)113 int umount_entry(struct trace_event_raw_sys_enter *ctx)
114 {
115 const char *dest = (const char *)ctx->args[0];
116 __u64 flags = (__u64)ctx->args[1];
117
118 return probe_entry(NULL, dest, NULL, flags, NULL, UMOUNT);
119 }
120
121 SEC("tracepoint/syscalls/sys_exit_umount")
umount_exit(struct trace_event_raw_sys_exit * ctx)122 int umount_exit(struct trace_event_raw_sys_exit *ctx)
123 {
124 return probe_exit(ctx, (int)ctx->ret);
125 }
126
127 char LICENSE[] SEC("license") = "Dual BSD/GPL";
128