1*387f9dfdSAndroid Build Coastguard Worker /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2*387f9dfdSAndroid Build Coastguard Worker /* Copyright (c) 2021 Hengqi Chen */
3*387f9dfdSAndroid Build Coastguard Worker #include <vmlinux.h>
4*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_helpers.h>
5*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_core_read.h>
6*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_tracing.h>
7*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_endian.h>
8*387f9dfdSAndroid Build Coastguard Worker #include "bindsnoop.h"
9*387f9dfdSAndroid Build Coastguard Worker
10*387f9dfdSAndroid Build Coastguard Worker #define MAX_ENTRIES 10240
11*387f9dfdSAndroid Build Coastguard Worker #define MAX_PORTS 1024
12*387f9dfdSAndroid Build Coastguard Worker
13*387f9dfdSAndroid Build Coastguard Worker const volatile bool filter_cg = false;
14*387f9dfdSAndroid Build Coastguard Worker const volatile pid_t target_pid = 0;
15*387f9dfdSAndroid Build Coastguard Worker const volatile bool ignore_errors = true;
16*387f9dfdSAndroid Build Coastguard Worker const volatile bool filter_by_port = false;
17*387f9dfdSAndroid Build Coastguard Worker
18*387f9dfdSAndroid Build Coastguard Worker struct {
19*387f9dfdSAndroid Build Coastguard Worker __uint(type, BPF_MAP_TYPE_CGROUP_ARRAY);
20*387f9dfdSAndroid Build Coastguard Worker __type(key, u32);
21*387f9dfdSAndroid Build Coastguard Worker __type(value, u32);
22*387f9dfdSAndroid Build Coastguard Worker __uint(max_entries, 1);
23*387f9dfdSAndroid Build Coastguard Worker } cgroup_map SEC(".maps");
24*387f9dfdSAndroid Build Coastguard Worker
25*387f9dfdSAndroid Build Coastguard Worker struct {
26*387f9dfdSAndroid Build Coastguard Worker __uint(type, BPF_MAP_TYPE_HASH);
27*387f9dfdSAndroid Build Coastguard Worker __uint(max_entries, MAX_ENTRIES);
28*387f9dfdSAndroid Build Coastguard Worker __type(key, __u32);
29*387f9dfdSAndroid Build Coastguard Worker __type(value, struct socket *);
30*387f9dfdSAndroid Build Coastguard Worker } sockets SEC(".maps");
31*387f9dfdSAndroid Build Coastguard Worker
32*387f9dfdSAndroid Build Coastguard Worker struct {
33*387f9dfdSAndroid Build Coastguard Worker __uint(type, BPF_MAP_TYPE_HASH);
34*387f9dfdSAndroid Build Coastguard Worker __uint(max_entries, MAX_PORTS);
35*387f9dfdSAndroid Build Coastguard Worker __type(key, __u16);
36*387f9dfdSAndroid Build Coastguard Worker __type(value, __u16);
37*387f9dfdSAndroid Build Coastguard Worker } ports SEC(".maps");
38*387f9dfdSAndroid Build Coastguard Worker
39*387f9dfdSAndroid Build Coastguard Worker struct {
40*387f9dfdSAndroid Build Coastguard Worker __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
41*387f9dfdSAndroid Build Coastguard Worker __uint(key_size, sizeof(__u32));
42*387f9dfdSAndroid Build Coastguard Worker __uint(value_size, sizeof(__u32));
43*387f9dfdSAndroid Build Coastguard Worker } events SEC(".maps");
44*387f9dfdSAndroid Build Coastguard Worker
probe_entry(struct pt_regs * ctx,struct socket * socket)45*387f9dfdSAndroid Build Coastguard Worker static int probe_entry(struct pt_regs *ctx, struct socket *socket)
46*387f9dfdSAndroid Build Coastguard Worker {
47*387f9dfdSAndroid Build Coastguard Worker __u64 pid_tgid = bpf_get_current_pid_tgid();
48*387f9dfdSAndroid Build Coastguard Worker __u32 pid = pid_tgid >> 32;
49*387f9dfdSAndroid Build Coastguard Worker __u32 tid = (__u32)pid_tgid;
50*387f9dfdSAndroid Build Coastguard Worker
51*387f9dfdSAndroid Build Coastguard Worker if (target_pid && target_pid != pid)
52*387f9dfdSAndroid Build Coastguard Worker return 0;
53*387f9dfdSAndroid Build Coastguard Worker
54*387f9dfdSAndroid Build Coastguard Worker bpf_map_update_elem(&sockets, &tid, &socket, BPF_ANY);
55*387f9dfdSAndroid Build Coastguard Worker return 0;
56*387f9dfdSAndroid Build Coastguard Worker };
57*387f9dfdSAndroid Build Coastguard Worker
probe_exit(struct pt_regs * ctx,short ver)58*387f9dfdSAndroid Build Coastguard Worker static int probe_exit(struct pt_regs *ctx, short ver)
59*387f9dfdSAndroid Build Coastguard Worker {
60*387f9dfdSAndroid Build Coastguard Worker __u64 pid_tgid = bpf_get_current_pid_tgid();
61*387f9dfdSAndroid Build Coastguard Worker __u32 pid = pid_tgid >> 32;
62*387f9dfdSAndroid Build Coastguard Worker __u32 tid = (__u32)pid_tgid;
63*387f9dfdSAndroid Build Coastguard Worker struct socket **socketp, *socket;
64*387f9dfdSAndroid Build Coastguard Worker struct inet_sock *inet_sock;
65*387f9dfdSAndroid Build Coastguard Worker struct sock *sock;
66*387f9dfdSAndroid Build Coastguard Worker union bind_options opts;
67*387f9dfdSAndroid Build Coastguard Worker struct bind_event event = {};
68*387f9dfdSAndroid Build Coastguard Worker __u16 sport = 0, *port;
69*387f9dfdSAndroid Build Coastguard Worker int ret;
70*387f9dfdSAndroid Build Coastguard Worker
71*387f9dfdSAndroid Build Coastguard Worker socketp = bpf_map_lookup_elem(&sockets, &tid);
72*387f9dfdSAndroid Build Coastguard Worker if (!socketp)
73*387f9dfdSAndroid Build Coastguard Worker return 0;
74*387f9dfdSAndroid Build Coastguard Worker
75*387f9dfdSAndroid Build Coastguard Worker ret = PT_REGS_RC(ctx);
76*387f9dfdSAndroid Build Coastguard Worker if (ignore_errors && ret != 0)
77*387f9dfdSAndroid Build Coastguard Worker goto cleanup;
78*387f9dfdSAndroid Build Coastguard Worker
79*387f9dfdSAndroid Build Coastguard Worker socket = *socketp;
80*387f9dfdSAndroid Build Coastguard Worker sock = BPF_CORE_READ(socket, sk);
81*387f9dfdSAndroid Build Coastguard Worker inet_sock = (struct inet_sock *)sock;
82*387f9dfdSAndroid Build Coastguard Worker
83*387f9dfdSAndroid Build Coastguard Worker sport = bpf_ntohs(BPF_CORE_READ(inet_sock, inet_sport));
84*387f9dfdSAndroid Build Coastguard Worker port = bpf_map_lookup_elem(&ports, &sport);
85*387f9dfdSAndroid Build Coastguard Worker if (filter_by_port && !port)
86*387f9dfdSAndroid Build Coastguard Worker goto cleanup;
87*387f9dfdSAndroid Build Coastguard Worker
88*387f9dfdSAndroid Build Coastguard Worker opts.fields.freebind = BPF_CORE_READ_BITFIELD_PROBED(inet_sock, freebind);
89*387f9dfdSAndroid Build Coastguard Worker opts.fields.transparent = BPF_CORE_READ_BITFIELD_PROBED(inet_sock, transparent);
90*387f9dfdSAndroid Build Coastguard Worker opts.fields.bind_address_no_port = BPF_CORE_READ_BITFIELD_PROBED(inet_sock, bind_address_no_port);
91*387f9dfdSAndroid Build Coastguard Worker opts.fields.reuseaddress = BPF_CORE_READ_BITFIELD_PROBED(sock, __sk_common.skc_reuse);
92*387f9dfdSAndroid Build Coastguard Worker opts.fields.reuseport = BPF_CORE_READ_BITFIELD_PROBED(sock, __sk_common.skc_reuseport);
93*387f9dfdSAndroid Build Coastguard Worker event.opts = opts.data;
94*387f9dfdSAndroid Build Coastguard Worker event.ts_us = bpf_ktime_get_ns() / 1000;
95*387f9dfdSAndroid Build Coastguard Worker event.pid = pid;
96*387f9dfdSAndroid Build Coastguard Worker event.port = sport;
97*387f9dfdSAndroid Build Coastguard Worker event.bound_dev_if = BPF_CORE_READ(sock, __sk_common.skc_bound_dev_if);
98*387f9dfdSAndroid Build Coastguard Worker event.ret = ret;
99*387f9dfdSAndroid Build Coastguard Worker event.proto = BPF_CORE_READ_BITFIELD_PROBED(sock, sk_protocol);
100*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&event.task, sizeof(event.task));
101*387f9dfdSAndroid Build Coastguard Worker if (ver == 4) {
102*387f9dfdSAndroid Build Coastguard Worker event.ver = ver;
103*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&event.addr, sizeof(event.addr), &inet_sock->inet_saddr);
104*387f9dfdSAndroid Build Coastguard Worker } else { /* ver == 6 */
105*387f9dfdSAndroid Build Coastguard Worker event.ver = ver;
106*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&event.addr, sizeof(event.addr), sock->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
107*387f9dfdSAndroid Build Coastguard Worker }
108*387f9dfdSAndroid Build Coastguard Worker bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event, sizeof(event));
109*387f9dfdSAndroid Build Coastguard Worker
110*387f9dfdSAndroid Build Coastguard Worker cleanup:
111*387f9dfdSAndroid Build Coastguard Worker bpf_map_delete_elem(&sockets, &tid);
112*387f9dfdSAndroid Build Coastguard Worker return 0;
113*387f9dfdSAndroid Build Coastguard Worker }
114*387f9dfdSAndroid Build Coastguard Worker
115*387f9dfdSAndroid Build Coastguard Worker SEC("kprobe/inet_bind")
BPF_KPROBE(ipv4_bind_entry,struct socket * socket)116*387f9dfdSAndroid Build Coastguard Worker int BPF_KPROBE(ipv4_bind_entry, struct socket *socket)
117*387f9dfdSAndroid Build Coastguard Worker {
118*387f9dfdSAndroid Build Coastguard Worker if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
119*387f9dfdSAndroid Build Coastguard Worker return 0;
120*387f9dfdSAndroid Build Coastguard Worker
121*387f9dfdSAndroid Build Coastguard Worker return probe_entry(ctx, socket);
122*387f9dfdSAndroid Build Coastguard Worker }
123*387f9dfdSAndroid Build Coastguard Worker
124*387f9dfdSAndroid Build Coastguard Worker SEC("kretprobe/inet_bind")
BPF_KRETPROBE(ipv4_bind_exit)125*387f9dfdSAndroid Build Coastguard Worker int BPF_KRETPROBE(ipv4_bind_exit)
126*387f9dfdSAndroid Build Coastguard Worker {
127*387f9dfdSAndroid Build Coastguard Worker if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
128*387f9dfdSAndroid Build Coastguard Worker return 0;
129*387f9dfdSAndroid Build Coastguard Worker
130*387f9dfdSAndroid Build Coastguard Worker return probe_exit(ctx, 4);
131*387f9dfdSAndroid Build Coastguard Worker }
132*387f9dfdSAndroid Build Coastguard Worker
133*387f9dfdSAndroid Build Coastguard Worker SEC("kprobe/inet6_bind")
BPF_KPROBE(ipv6_bind_entry,struct socket * socket)134*387f9dfdSAndroid Build Coastguard Worker int BPF_KPROBE(ipv6_bind_entry, struct socket *socket)
135*387f9dfdSAndroid Build Coastguard Worker {
136*387f9dfdSAndroid Build Coastguard Worker if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
137*387f9dfdSAndroid Build Coastguard Worker return 0;
138*387f9dfdSAndroid Build Coastguard Worker
139*387f9dfdSAndroid Build Coastguard Worker return probe_entry(ctx, socket);
140*387f9dfdSAndroid Build Coastguard Worker }
141*387f9dfdSAndroid Build Coastguard Worker
142*387f9dfdSAndroid Build Coastguard Worker SEC("kretprobe/inet6_bind")
BPF_KRETPROBE(ipv6_bind_exit)143*387f9dfdSAndroid Build Coastguard Worker int BPF_KRETPROBE(ipv6_bind_exit)
144*387f9dfdSAndroid Build Coastguard Worker {
145*387f9dfdSAndroid Build Coastguard Worker if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
146*387f9dfdSAndroid Build Coastguard Worker return 0;
147*387f9dfdSAndroid Build Coastguard Worker
148*387f9dfdSAndroid Build Coastguard Worker return probe_exit(ctx, 6);
149*387f9dfdSAndroid Build Coastguard Worker }
150*387f9dfdSAndroid Build Coastguard Worker
151*387f9dfdSAndroid Build Coastguard Worker char LICENSE[] SEC("license") = "Dual BSD/GPL";
152