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