Skip to content

Commit 970f3be

Browse files
committed
libbpf-tools: Fix bindsnoop for kernel v6.6+
The freebind field in struct inet_sock gone in recent kernel versions due to some kernel refactor works ([0]). The change breaks the bindsnoop tool. Fix it in a CO-RE way. This should close #4838. [0]: https://lore.kernel.org/all/[email protected]/ Signed-off-by: Hengqi Chen <[email protected]>
1 parent 7266156 commit 970f3be

File tree

2 files changed

+61
-3
lines changed

2 files changed

+61
-3
lines changed

libbpf-tools/bindsnoop.bpf.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
#include <bpf/bpf_core_read.h>
66
#include <bpf/bpf_tracing.h>
77
#include <bpf/bpf_endian.h>
8+
89
#include "bindsnoop.h"
10+
#include "core_fixes.bpf.h"
911

1012
#define MAX_ENTRIES 10240
1113
#define MAX_PORTS 1024
@@ -85,9 +87,9 @@ static int probe_exit(struct pt_regs *ctx, short ver)
8587
if (filter_by_port && !port)
8688
goto cleanup;
8789

88-
opts.fields.freebind = BPF_CORE_READ_BITFIELD_PROBED(inet_sock, freebind);
89-
opts.fields.transparent = BPF_CORE_READ_BITFIELD_PROBED(inet_sock, transparent);
90-
opts.fields.bind_address_no_port = BPF_CORE_READ_BITFIELD_PROBED(inet_sock, bind_address_no_port);
90+
opts.fields.freebind = get_inet_sock_freebind(inet_sock);
91+
opts.fields.transparent = get_inet_sock_transparent(inet_sock);
92+
opts.fields.bind_address_no_port = get_inet_sock_bind_address_no_port(inet_sock);
9193
opts.fields.reuseaddress = BPF_CORE_READ_BITFIELD_PROBED(sock, __sk_common.skc_reuse);
9294
opts.fields.reuseport = BPF_CORE_READ_BITFIELD_PROBED(sock, __sk_common.skc_reuseport);
9395
event.opts = opts.data;

libbpf-tools/core_fixes.bpf.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,4 +249,60 @@ static __always_inline __u64 get_sock_ident(struct sock *sk)
249249
return (__u64)sk;
250250
}
251251

252+
/**
253+
* During kernel 6.6 development cycle, several bitfields in struct inet_sock gone,
254+
* they are placed in inet_sock::inet_flags instead ([0]).
255+
*
256+
* References:
257+
* [0]: https://lore.kernel.org/all/[email protected]/
258+
*/
259+
struct inet_sock___o {
260+
__u8 freebind: 1;
261+
__u8 transparent: 1;
262+
__u8 bind_address_no_port: 1;
263+
};
264+
265+
enum {
266+
INET_FLAGS_FREEBIND___x = 11,
267+
INET_FLAGS_TRANSPARENT___x = 15,
268+
INET_FLAGS_BIND_ADDRESS_NO_PORT___x = 18,
269+
};
270+
271+
struct inet_sock___x {
272+
unsigned long inet_flags;
273+
};
274+
275+
static __always_inline __u8 get_inet_sock_freebind(void *inet_sock)
276+
{
277+
unsigned long inet_flags;
278+
279+
if (bpf_core_field_exists(struct inet_sock___o, freebind))
280+
return BPF_CORE_READ_BITFIELD_PROBED((struct inet_sock___o *)inet_sock, freebind);
281+
282+
inet_flags = BPF_CORE_READ((struct inet_sock___x *)inet_sock, inet_flags);
283+
return (1 << INET_FLAGS_FREEBIND___x) & inet_flags ? 1 : 0;
284+
}
285+
286+
static __always_inline __u8 get_inet_sock_transparent(void *inet_sock)
287+
{
288+
unsigned long inet_flags;
289+
290+
if (bpf_core_field_exists(struct inet_sock___o, transparent))
291+
return BPF_CORE_READ_BITFIELD_PROBED((struct inet_sock___o *)inet_sock, transparent);
292+
293+
inet_flags = BPF_CORE_READ((struct inet_sock___x *)inet_sock, inet_flags);
294+
return (1 << INET_FLAGS_TRANSPARENT___x) & inet_flags ? 1 : 0;
295+
}
296+
297+
static __always_inline __u8 get_inet_sock_bind_address_no_port(void *inet_sock)
298+
{
299+
unsigned long inet_flags;
300+
301+
if (bpf_core_field_exists(struct inet_sock___o, bind_address_no_port))
302+
return BPF_CORE_READ_BITFIELD_PROBED((struct inet_sock___o *)inet_sock, bind_address_no_port);
303+
304+
inet_flags = BPF_CORE_READ((struct inet_sock___x *)inet_sock, inet_flags);
305+
return (1 << INET_FLAGS_BIND_ADDRESS_NO_PORT___x) & inet_flags ? 1 : 0;
306+
}
307+
252308
#endif /* __CORE_FIXES_BPF_H */

0 commit comments

Comments
 (0)