Skip to content
API Documentation
BastionGuard™
bsc_ebpf.c File Reference

Go to the source code of this file.

Classes

struct  bsc_conn_event
struct  dedup_key

Macros

#define AF_INET   2
#define AF_INET6   10
#define TCP_ESTABLISHED   1
#define IPPROTO_TCP   6
#define IPPROTO_UDP   17
#define RINGBUF_SIZE   (8 * 1024 * 1024)
#define UDP_DEDUP_WINDOW_NS   (5ULL * 1000ULL * 1000ULL * 1000ULL)
#define TCP_DEDUP_WINDOW_NS   (2ULL * 1000ULL * 1000ULL * 1000ULL)

Functions

struct { ... }  SEC (".maps")
 __uint (type, BPF_MAP_TYPE_RINGBUF)
 __uint (max_entries, RINGBUF_SIZE)
 __uint (type, BPF_MAP_TYPE_LRU_HASH)
 __uint (max_entries, 8192)
 __type (key, struct dedup_key)
 __type (value, __u64)
static __always_inline void fill_proc (struct bsc_conn_event *ev)
static __always_inline bool should_emit (const struct dedup_key *k, __u64 now_ns, __u64 window_ns)
int bsc_inet_sock_set_state (struct trace_event_raw_inet_sock_set_state *ctx)
int BPF_KPROBE (bsc_tcp_v4_connect, struct sock *sk)
int BPF_KPROBE (bsc_tcp_v6_connect, struct sock *sk)
static __always_inline bool extract_msg_v4 (struct msghdr *msg, __u32 *out_daddr, __u16 *out_dport)
static __always_inline bool extract_msg_v6 (struct msghdr *msg, __u8 out_daddr[16], __u16 *out_dport)
int BPF_KPROBE (bsc_udp_sendmsg, struct sock *sk, struct msghdr *msg)
int BPF_KPROBE (bsc_udpv6_sendmsg, struct sock *sk, struct msghdr *msg)
char LICENSE[] SEC ("license")

Macro Definition Documentation

◆ AF_INET

◆ AF_INET6

◆ IPPROTO_TCP

#define IPPROTO_TCP   6

◆ IPPROTO_UDP

#define IPPROTO_UDP   17

◆ RINGBUF_SIZE

#define RINGBUF_SIZE   (8 * 1024 * 1024)

Definition at line 65 of file bsc_ebpf.c.

◆ TCP_DEDUP_WINDOW_NS

#define TCP_DEDUP_WINDOW_NS   (2ULL * 1000ULL * 1000ULL * 1000ULL)

Definition at line 69 of file bsc_ebpf.c.

Referenced by BPF_KPROBE(), and BPF_KPROBE().

◆ TCP_ESTABLISHED

#define TCP_ESTABLISHED   1

Definition at line 58 of file bsc_ebpf.c.

Referenced by bsc_inet_sock_set_state().

◆ UDP_DEDUP_WINDOW_NS

#define UDP_DEDUP_WINDOW_NS   (5ULL * 1000ULL * 1000ULL * 1000ULL)

Definition at line 68 of file bsc_ebpf.c.

Referenced by BPF_KPROBE(), and BPF_KPROBE().

Function Documentation

◆ __type() [1/2]

@072270030377323145125163337314057176140314073041::__type ( key ,
struct dedup_key  )

◆ __type() [2/2]

@072270030377323145125163337314057176140314073041::__type ( value ,
__u64  )

◆ __uint() [1/4]

SEC::__uint ( max_entries ,
8192  )

◆ __uint() [2/4]

@314017302272111134376103221067163065253031234061::__uint ( max_entries ,
RINGBUF_SIZE  )

◆ __uint() [3/4]

SEC::__uint ( type ,
BPF_MAP_TYPE_LRU_HASH  )

◆ __uint() [4/4]

SEC::__uint ( type ,
BPF_MAP_TYPE_RINGBUF  )

◆ BPF_KPROBE() [1/4]

int BPF_KPROBE ( bsc_tcp_v4_connect ,
struct sock * sk )

Definition at line 209 of file bsc_ebpf.c.

210{
211 if (!sk) return 0;
212
213 const __u64 now = bpf_ktime_get_ns();
214
215 /* Leggi destinazione dalla struct sock (inet_sock → skc_daddr/dport).
216 * NOTA: in tcp_v4_connect la destinazione viene scritta prima
217 * della chiamata effettiva al connect — quindi e' gia' nel sk. */
218 __u32 daddr = BPF_CORE_READ(sk, __sk_common.skc_daddr);
219 __u32 saddr = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr);
220 __u16 dport = BPF_CORE_READ(sk, __sk_common.skc_dport); /* net byte order */
221 __u16 sport = BPF_CORE_READ(sk, __sk_common.skc_num); /* host byte order */
222 dport = bpf_ntohs(dport);
223
224 /* saddr puo' essere 0 (kernel non ha ancora scelto src): non e' errore */
225
226 struct dedup_key k = {};
227 const __u64 pid_tgid = bpf_get_current_pid_tgid();
228 k.pid = (__u32)(pid_tgid >> 32);
229 k.dst_port = dport;
230 k.family = AF_INET;
231 k.proto = IPPROTO_TCP;
232 __builtin_memcpy(k.dst_addr, &daddr, 4);
233 if (!should_emit(&k, now, TCP_DEDUP_WINDOW_NS)) return 0;
234
235 struct bsc_conn_event *ev = bpf_ringbuf_reserve(&bsc_events,
236 sizeof(*ev), 0);
237 if (!ev) return 0;
238
239 fill_proc(ev);
240 ev->family = AF_INET;
241 ev->proto = IPPROTO_TCP;
242 ev->event_kind = 1;
243 ev->_pad[0] = 0;
244 ev->src_port = sport;
245 ev->dst_port = dport;
246
247 __builtin_memset(ev->src_addr, 0, sizeof(ev->src_addr));
248 __builtin_memset(ev->dst_addr, 0, sizeof(ev->dst_addr));
249 __builtin_memcpy(ev->src_addr, &saddr, 4);
250 __builtin_memcpy(ev->dst_addr, &daddr, 4);
251
252 ev->ts_ns = now;
253 bpf_ringbuf_submit(ev, 0);
254 return 0;
255}
static __always_inline void fill_proc(struct bsc_conn_event *ev)
Definition bsc_ebpf.c:127
#define TCP_DEDUP_WINDOW_NS
Definition bsc_ebpf.c:69
static __always_inline bool should_emit(const struct dedup_key *k, __u64 now_ns, __u64 window_ns)
Definition bsc_ebpf.c:139
#define IPPROTO_TCP
Definition bsc_ebpf.c:60
#define AF_INET
Definition bsc_ebpf.c:56
__u8 _pad[1]
Definition bsc_ebpf.c:90
__u16 dst_port
Definition bsc_ebpf.c:92
__u8 src_addr[16]
Definition bsc_ebpf.c:95
__u8 dst_addr[16]
Definition bsc_ebpf.c:96
__u8 event_kind
Definition bsc_ebpf.c:89
__u16 src_port
Definition bsc_ebpf.c:91
__u16 dst_port
Definition bsc_ebpf.c:107
__u8 dst_addr[16]
Definition bsc_ebpf.c:110
__u32 pid
Definition bsc_ebpf.c:106
__u8 proto
Definition bsc_ebpf.c:109
__u8 family
Definition bsc_ebpf.c:108

References bsc_conn_event::_pad, AF_INET, BPF_KPROBE(), bsc_conn_event::dst_addr, dedup_key::dst_addr, bsc_conn_event::dst_port, dedup_key::dst_port, bsc_conn_event::event_kind, bsc_conn_event::family, dedup_key::family, fill_proc(), IPPROTO_TCP, dedup_key::pid, bsc_conn_event::proto, dedup_key::proto, should_emit(), bsc_conn_event::src_addr, bsc_conn_event::src_port, TCP_DEDUP_WINDOW_NS, and bsc_conn_event::ts_ns.

Referenced by BPF_KPROBE(), BPF_KPROBE(), BPF_KPROBE(), and BPF_KPROBE().

◆ BPF_KPROBE() [2/4]

int BPF_KPROBE ( bsc_tcp_v6_connect ,
struct sock * sk )

Definition at line 258 of file bsc_ebpf.c.

259{
260 if (!sk) return 0;
261
262 const __u64 now = bpf_ktime_get_ns();
263
264 __u16 dport = BPF_CORE_READ(sk, __sk_common.skc_dport);
265 __u16 sport = BPF_CORE_READ(sk, __sk_common.skc_num);
266 dport = bpf_ntohs(dport);
267
268 struct dedup_key k = {};
269 const __u64 pid_tgid = bpf_get_current_pid_tgid();
270 k.pid = (__u32)(pid_tgid >> 32);
271 k.dst_port = dport;
272 k.family = AF_INET6;
273 k.proto = IPPROTO_TCP;
274 BPF_CORE_READ_INTO(k.dst_addr, sk, __sk_common.skc_v6_daddr);
275 if (!should_emit(&k, now, TCP_DEDUP_WINDOW_NS)) return 0;
276
277 struct bsc_conn_event *ev = bpf_ringbuf_reserve(&bsc_events,
278 sizeof(*ev), 0);
279 if (!ev) return 0;
280
281 fill_proc(ev);
282 ev->family = AF_INET6;
283 ev->proto = IPPROTO_TCP;
284 ev->event_kind = 1;
285 ev->_pad[0] = 0;
286 ev->src_port = sport;
287 ev->dst_port = dport;
288
289 BPF_CORE_READ_INTO(ev->src_addr, sk, __sk_common.skc_v6_rcv_saddr);
290 BPF_CORE_READ_INTO(ev->dst_addr, sk, __sk_common.skc_v6_daddr);
291
292 ev->ts_ns = now;
293 bpf_ringbuf_submit(ev, 0);
294 return 0;
295}
#define AF_INET6
Definition bsc_ebpf.c:57

References bsc_conn_event::_pad, AF_INET6, BPF_KPROBE(), bsc_conn_event::dst_addr, dedup_key::dst_addr, bsc_conn_event::dst_port, dedup_key::dst_port, bsc_conn_event::event_kind, bsc_conn_event::family, dedup_key::family, fill_proc(), IPPROTO_TCP, dedup_key::pid, bsc_conn_event::proto, dedup_key::proto, should_emit(), bsc_conn_event::src_addr, bsc_conn_event::src_port, TCP_DEDUP_WINDOW_NS, and bsc_conn_event::ts_ns.

◆ BPF_KPROBE() [3/4]

int BPF_KPROBE ( bsc_udp_sendmsg ,
struct sock * sk,
struct msghdr * msg )

Definition at line 348 of file bsc_ebpf.c.

349{
350 if (!sk) return 0;
351
352 __u32 daddr = 0;
353 __u16 dport = 0;
354
355 /* 1) prova dalla msghdr (UDP unconnected) */
356 if (!extract_msg_v4(msg, &daddr, &dport)) {
357 /* 2) fallback: dalla struct sock (UDP connected) */
358 daddr = BPF_CORE_READ(sk, __sk_common.skc_daddr);
359 __u16 d = BPF_CORE_READ(sk, __sk_common.skc_dport);
360 dport = bpf_ntohs(d);
361 }
362 if (dport == 0) return 0; /* socket senza destinazione risolta */
363
364 const __u64 now = bpf_ktime_get_ns();
365 __u32 saddr = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr);
366 __u16 sport = BPF_CORE_READ(sk, __sk_common.skc_num);
367
368 struct dedup_key k = {};
369 const __u64 pid_tgid = bpf_get_current_pid_tgid();
370 k.pid = (__u32)(pid_tgid >> 32);
371 k.dst_port = dport;
372 k.family = AF_INET;
373 k.proto = IPPROTO_UDP;
374 __builtin_memcpy(k.dst_addr, &daddr, 4);
375 if (!should_emit(&k, now, UDP_DEDUP_WINDOW_NS)) return 0;
376
377 struct bsc_conn_event *ev = bpf_ringbuf_reserve(&bsc_events,
378 sizeof(*ev), 0);
379 if (!ev) return 0;
380
381 fill_proc(ev);
382 ev->family = AF_INET;
383 ev->proto = IPPROTO_UDP;
384 ev->event_kind = 2;
385 ev->_pad[0] = 0;
386 ev->src_port = sport;
387 ev->dst_port = dport;
388
389 __builtin_memset(ev->src_addr, 0, sizeof(ev->src_addr));
390 __builtin_memset(ev->dst_addr, 0, sizeof(ev->dst_addr));
391 __builtin_memcpy(ev->src_addr, &saddr, 4);
392 __builtin_memcpy(ev->dst_addr, &daddr, 4);
393
394 ev->ts_ns = now;
395 bpf_ringbuf_submit(ev, 0);
396 return 0;
397}
#define UDP_DEDUP_WINDOW_NS
Definition bsc_ebpf.c:68
static __always_inline bool extract_msg_v4(struct msghdr *msg, __u32 *out_daddr, __u16 *out_dport)
Definition bsc_ebpf.c:311
#define IPPROTO_UDP
Definition bsc_ebpf.c:61

References bsc_conn_event::_pad, AF_INET, BPF_KPROBE(), bsc_conn_event::dst_addr, dedup_key::dst_addr, bsc_conn_event::dst_port, dedup_key::dst_port, bsc_conn_event::event_kind, extract_msg_v4(), bsc_conn_event::family, dedup_key::family, fill_proc(), IPPROTO_UDP, dedup_key::pid, bsc_conn_event::proto, dedup_key::proto, should_emit(), bsc_conn_event::src_addr, bsc_conn_event::src_port, bsc_conn_event::ts_ns, and UDP_DEDUP_WINDOW_NS.

◆ BPF_KPROBE() [4/4]

int BPF_KPROBE ( bsc_udpv6_sendmsg ,
struct sock * sk,
struct msghdr * msg )

Definition at line 400 of file bsc_ebpf.c.

401{
402 if (!sk) return 0;
403
404 __u8 daddr[16] = {};
405 __u16 dport = 0;
406
407 if (!extract_msg_v6(msg, daddr, &dport)) {
408 /* fallback: socket connected */
409 BPF_CORE_READ_INTO(daddr, sk, __sk_common.skc_v6_daddr);
410 __u16 d = BPF_CORE_READ(sk, __sk_common.skc_dport);
411 dport = bpf_ntohs(d);
412 }
413 if (dport == 0) return 0;
414
415 const __u64 now = bpf_ktime_get_ns();
416 __u16 sport = BPF_CORE_READ(sk, __sk_common.skc_num);
417
418 struct dedup_key k = {};
419 const __u64 pid_tgid = bpf_get_current_pid_tgid();
420 k.pid = (__u32)(pid_tgid >> 32);
421 k.dst_port = dport;
422 k.family = AF_INET6;
423 k.proto = IPPROTO_UDP;
424 __builtin_memcpy(k.dst_addr, daddr, 16);
425 if (!should_emit(&k, now, UDP_DEDUP_WINDOW_NS)) return 0;
426
427 struct bsc_conn_event *ev = bpf_ringbuf_reserve(&bsc_events,
428 sizeof(*ev), 0);
429 if (!ev) return 0;
430
431 fill_proc(ev);
432 ev->family = AF_INET6;
433 ev->proto = IPPROTO_UDP;
434 ev->event_kind = 2;
435 ev->_pad[0] = 0;
436 ev->src_port = sport;
437 ev->dst_port = dport;
438
439 BPF_CORE_READ_INTO(ev->src_addr, sk, __sk_common.skc_v6_rcv_saddr);
440 __builtin_memcpy(ev->dst_addr, daddr, 16);
441
442 ev->ts_ns = now;
443 bpf_ringbuf_submit(ev, 0);
444 return 0;
445}
static __always_inline bool extract_msg_v6(struct msghdr *msg, __u8 out_daddr[16], __u16 *out_dport)
Definition bsc_ebpf.c:329

References bsc_conn_event::_pad, AF_INET6, BPF_KPROBE(), bsc_conn_event::dst_addr, dedup_key::dst_addr, bsc_conn_event::dst_port, dedup_key::dst_port, bsc_conn_event::event_kind, extract_msg_v6(), bsc_conn_event::family, dedup_key::family, fill_proc(), IPPROTO_UDP, dedup_key::pid, bsc_conn_event::proto, dedup_key::proto, should_emit(), bsc_conn_event::src_addr, bsc_conn_event::src_port, bsc_conn_event::ts_ns, and UDP_DEDUP_WINDOW_NS.

◆ bsc_inet_sock_set_state()

int bsc_inet_sock_set_state ( struct trace_event_raw_inet_sock_set_state * ctx)

Definition at line 157 of file bsc_ebpf.c.

158{
159 if (ctx->newstate != TCP_ESTABLISHED)
160 return 0;
161
162 const __u16 family = ctx->family;
163 if (family != AF_INET && family != AF_INET6)
164 return 0;
165
166 const __u8 proto = (__u8)ctx->protocol;
167 if (proto != IPPROTO_TCP && proto != IPPROTO_UDP)
168 return 0;
169
170 struct bsc_conn_event *ev = bpf_ringbuf_reserve(&bsc_events,
171 sizeof(*ev), 0);
172 if (!ev) return 0;
173
174 fill_proc(ev);
175 ev->family = (__u8)family;
176 ev->proto = proto;
177 ev->event_kind = 0;
178 ev->_pad[0] = 0;
179 ev->src_port = bpf_ntohs(ctx->sport);
180 ev->dst_port = bpf_ntohs(ctx->dport);
181
182 if (family == AF_INET) {
183 __builtin_memset(ev->src_addr, 0, sizeof(ev->src_addr));
184 __builtin_memset(ev->dst_addr, 0, sizeof(ev->dst_addr));
185 bpf_probe_read_kernel(ev->src_addr, 4, &ctx->saddr);
186 bpf_probe_read_kernel(ev->dst_addr, 4, &ctx->daddr);
187 } else {
188 BPF_CORE_READ_INTO(ev->src_addr, ctx, saddr_v6);
189 BPF_CORE_READ_INTO(ev->dst_addr, ctx, daddr_v6);
190 }
191
192 ev->ts_ns = bpf_ktime_get_ns();
193 bpf_ringbuf_submit(ev, 0);
194 return 0;
195}
#define TCP_ESTABLISHED
Definition bsc_ebpf.c:58

References bsc_conn_event::_pad, AF_INET, AF_INET6, bsc_inet_sock_set_state(), bsc_conn_event::dst_addr, bsc_conn_event::dst_port, bsc_conn_event::event_kind, bsc_conn_event::family, fill_proc(), IPPROTO_TCP, IPPROTO_UDP, bsc_conn_event::proto, bsc_conn_event::src_addr, bsc_conn_event::src_port, TCP_ESTABLISHED, and bsc_conn_event::ts_ns.

Referenced by bsc_inet_sock_set_state().

◆ extract_msg_v4()

__always_inline bool extract_msg_v4 ( struct msghdr * msg,
__u32 * out_daddr,
__u16 * out_dport )
static

Definition at line 311 of file bsc_ebpf.c.

314{
315 if (!msg) return false;
316 void* name = BPF_CORE_READ(msg, msg_name);
317 int nlen = BPF_CORE_READ(msg, msg_namelen);
318 if (!name || nlen < (int)sizeof(struct sockaddr_in)) return false;
319
320 struct sockaddr_in sa = {};
321 if (bpf_probe_read_kernel(&sa, sizeof(sa), name) != 0) return false;
322 if (sa.sin_family != AF_INET) return false;
323
324 *out_daddr = sa.sin_addr.s_addr; /* network byte order */
325 *out_dport = bpf_ntohs(sa.sin_port);
326 return true;
327}

References AF_INET, and extract_msg_v4().

Referenced by BPF_KPROBE(), and extract_msg_v4().

◆ extract_msg_v6()

__always_inline bool extract_msg_v6 ( struct msghdr * msg,
__u8 out_daddr[16],
__u16 * out_dport )
static

Definition at line 329 of file bsc_ebpf.c.

332{
333 if (!msg) return false;
334 void* name = BPF_CORE_READ(msg, msg_name);
335 int nlen = BPF_CORE_READ(msg, msg_namelen);
336 if (!name || nlen < (int)sizeof(struct sockaddr_in6)) return false;
337
338 struct sockaddr_in6 sa = {};
339 if (bpf_probe_read_kernel(&sa, sizeof(sa), name) != 0) return false;
340 if (sa.sin6_family != AF_INET6) return false;
341
342 __builtin_memcpy(out_daddr, &sa.sin6_addr, 16);
343 *out_dport = bpf_ntohs(sa.sin6_port);
344 return true;
345}

References AF_INET6, and extract_msg_v6().

Referenced by BPF_KPROBE(), and extract_msg_v6().

◆ fill_proc()

__always_inline void fill_proc ( struct bsc_conn_event * ev)
static

Definition at line 127 of file bsc_ebpf.c.

128{
129 const __u64 pid_tgid = bpf_get_current_pid_tgid();
130 ev->pid = (__u32)(pid_tgid >> 32);
131 ev->tid = (__u32)(pid_tgid & 0xffffffffull);
132 const __u64 uid_gid = bpf_get_current_uid_gid();
133 ev->uid = (__u32)(uid_gid & 0xffffffffull);
134 ev->gid = (__u32)(uid_gid >> 32);
135 bpf_get_current_comm(ev->comm, sizeof(ev->comm));
136}
char comm[16]
Definition bsc_ebpf.c:84

References bsc_conn_event::comm, fill_proc(), bsc_conn_event::gid, bsc_conn_event::pid, bsc_conn_event::tid, and bsc_conn_event::uid.

Referenced by BPF_KPROBE(), BPF_KPROBE(), BPF_KPROBE(), BPF_KPROBE(), bsc_inet_sock_set_state(), and fill_proc().

◆ SEC() [1/2]

struct @314017302272111134376103221067163065253031234061 SEC ( ".maps" )

◆ SEC() [2/2]

char LICENSE[] SEC ( "license" )

References SEC.

◆ should_emit()

__always_inline bool should_emit ( const struct dedup_key * k,
__u64 now_ns,
__u64 window_ns )
static

Definition at line 139 of file bsc_ebpf.c.

142{
143 __u64* last = bpf_map_lookup_elem(&bsc_dedup, k);
144 if (last) {
145 if (now_ns - *last < window_ns) return false; /* scarto: duplicato */
146 *last = now_ns; /* update in-place */
147 return true;
148 }
149 bpf_map_update_elem(&bsc_dedup, k, &now_ns, BPF_ANY);
150 return true;
151}

References should_emit().

Referenced by BPF_KPROBE(), BPF_KPROBE(), BPF_KPROBE(), BPF_KPROBE(), and should_emit().