inspektor-gadget

Форк
0
144 строки · 4.1 Кб
1
// SPDX-License-Identifier: GPL-2.0
2
//
3
// Based on tcpretrans(8) from BCC
4
//
5
// Copyright 2016 Netflix, Inc.
6
//
7
// 14-Feb-2016   Brendan Gregg   Created this.
8
// 03-Nov-2017   Matthias Tafelmeier Extended this.
9
// Copyright 2023 Microsoft Corporation
10

11
#include <vmlinux.h>
12

13
#include <bpf/bpf_helpers.h>
14
#include <bpf/bpf_core_read.h>
15
#include <bpf/bpf_tracing.h>
16
#include <bpf/bpf_endian.h>
17

18
#define GADGET_TYPE_TRACING
19
#include <gadget/sockets-map.h>
20

21
#include "tcpretrans.h"
22

23
/* Define here, because there are conflicts with include files */
24
#define AF_INET 2
25
#define AF_INET6 10
26

27
// we need this to make sure the compiler doesn't remove our struct
28
const struct event *unusedevent __attribute__((unused));
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
static __always_inline int __trace_tcp_retrans(void *ctx, const struct sock *sk,
37
					       const struct sk_buff *skb)
38
{
39
	struct inet_sock *sockp;
40
	struct task_struct *task;
41
	__u64 pid_tgid, uid_gid;
42
	struct event event = {};
43
	struct tcp_skb_cb *tcb;
44

45
	if (sk == NULL)
46
		return 0;
47

48
	if (BPF_CORE_READ_BITFIELD_PROBED(sk, sk_protocol) != IPPROTO_TCP)
49
		return 0;
50

51
	sockp = (struct inet_sock *)sk;
52
	task = (struct task_struct *)bpf_get_current_task();
53
	pid_tgid = bpf_get_current_pid_tgid();
54
	uid_gid = bpf_get_current_uid_gid();
55

56
	event.timestamp = bpf_ktime_get_boot_ns();
57
	event.af = BPF_CORE_READ(sk, __sk_common.skc_family);
58
	event.state = BPF_CORE_READ(sk, __sk_common.skc_state);
59

60
	bpf_get_current_comm(&event.proc_current.task,
61
			     sizeof(event.proc_current.task));
62
	event.proc_current.pid = pid_tgid >> 32;
63
	event.proc_current.tid = (__u32)pid_tgid;
64
	event.proc_current.mount_ns_id =
65
		(u64)BPF_CORE_READ(task, nsproxy, mnt_ns, ns.inum);
66
	event.proc_current.uid = (u32)uid_gid;
67
	event.proc_current.gid = (u32)(uid_gid >> 32);
68

69
	// The tcp_retransmit_skb tracepoint is fired with a skb that does not
70
	// contain the TCP header because the TCP header is built on a cloned skb
71
	// we don't have access to.
72
	// skb->transport_header is not set: skb_transport_header_was_set() == false.
73
	// Instead, we have to read the TCP flags from the TCP control buffer.
74
	tcb = (struct tcp_skb_cb *)&(skb->cb[0]);
75
	bpf_probe_read_kernel(&event.tcpflags, sizeof(event.tcpflags),
76
			      &tcb->tcp_flags);
77

78
	BPF_CORE_READ_INTO(&event.dport, sk, __sk_common.skc_dport);
79
	if (event.dport == 0)
80
		return 0;
81

82
	BPF_CORE_READ_INTO(&event.sport, sockp, inet_sport);
83
	if (event.sport == 0)
84
		return 0;
85

86
	switch (event.af) {
87
	case AF_INET:
88
		BPF_CORE_READ_INTO(&event.daddr_v4, sk, __sk_common.skc_daddr);
89
		if (event.daddr_v4 == 0)
90
			return 0;
91
		BPF_CORE_READ_INTO(&event.saddr_v4, sk,
92
				   __sk_common.skc_rcv_saddr);
93
		if (event.saddr_v4 == 0)
94
			return 0;
95
		break;
96

97
	case AF_INET6:
98
		BPF_CORE_READ_INTO(
99
			&event.saddr_v6, sk,
100
			__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
101
		if (event.saddr_v6 == 0)
102
			return 0;
103
		BPF_CORE_READ_INTO(&event.daddr_v6, sk,
104
				   __sk_common.skc_v6_daddr.in6_u.u6_addr32);
105
		if (event.daddr_v6 == 0)
106
			return 0;
107
		break;
108

109
	default:
110
		// drop
111
		return 0;
112
	}
113

114
	BPF_CORE_READ_INTO(&event.netns, sk, __sk_common.skc_net.net, ns.inum);
115

116
	struct sockets_value *skb_val = gadget_socket_lookup(sk, event.netns);
117

118
	if (skb_val != NULL) {
119
		event.proc_socket.mount_ns_id = skb_val->mntns;
120
		event.proc_socket.pid = skb_val->pid_tgid >> 32;
121
		event.proc_socket.tid = (__u32)skb_val->pid_tgid;
122
		__builtin_memcpy(&event.proc_socket.task, skb_val->task,
123
				 sizeof(event.proc_socket.task));
124
		event.proc_socket.uid = (__u32)skb_val->uid_gid;
125
		event.proc_socket.gid = (__u32)(skb_val->uid_gid >> 32);
126
	}
127

128
	bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event,
129
			      sizeof(event));
130
	return 0;
131
}
132

133
SEC("tracepoint/tcp/tcp_retransmit_skb")
134
int ig_tcpretrans(struct trace_event_raw_tcp_event_sk_skb *ctx)
135
{
136
	// struct trace_event_raw_tcp_event_sk_skb is described in:
137
	// /sys/kernel/tracing/events/tcp/tcp_retransmit_skb/format
138
	const struct sk_buff *skb = ctx->skbaddr;
139
	const struct sock *sk = ctx->skaddr;
140

141
	return __trace_tcp_retrans(ctx, sk, skb);
142
}
143

144
char LICENSE[] SEC("license") = "GPL";
145

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.