Skip to content

Commit

Permalink
libbpf-tools: Fix bindsnoop for kernel v6.6+
Browse files Browse the repository at this point in the history
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 iovisor#4838.

  [0]: https://lore.kernel.org/all/[email protected]/

Signed-off-by: Hengqi Chen <[email protected]>
  • Loading branch information
chenhengqi committed Jan 1, 2024
1 parent 7266156 commit 970f3be
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 3 deletions.
8 changes: 5 additions & 3 deletions libbpf-tools/bindsnoop.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_endian.h>

#include "bindsnoop.h"
#include "core_fixes.bpf.h"

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

opts.fields.freebind = BPF_CORE_READ_BITFIELD_PROBED(inet_sock, freebind);
opts.fields.transparent = BPF_CORE_READ_BITFIELD_PROBED(inet_sock, transparent);
opts.fields.bind_address_no_port = BPF_CORE_READ_BITFIELD_PROBED(inet_sock, bind_address_no_port);
opts.fields.freebind = get_inet_sock_freebind(inet_sock);
opts.fields.transparent = get_inet_sock_transparent(inet_sock);
opts.fields.bind_address_no_port = get_inet_sock_bind_address_no_port(inet_sock);
opts.fields.reuseaddress = BPF_CORE_READ_BITFIELD_PROBED(sock, __sk_common.skc_reuse);
opts.fields.reuseport = BPF_CORE_READ_BITFIELD_PROBED(sock, __sk_common.skc_reuseport);
event.opts = opts.data;
Expand Down
56 changes: 56 additions & 0 deletions libbpf-tools/core_fixes.bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,4 +249,60 @@ static __always_inline __u64 get_sock_ident(struct sock *sk)
return (__u64)sk;
}

/**
* During kernel 6.6 development cycle, several bitfields in struct inet_sock gone,
* they are placed in inet_sock::inet_flags instead ([0]).
*
* References:
* [0]: https://lore.kernel.org/all/[email protected]/
*/
struct inet_sock___o {
__u8 freebind: 1;
__u8 transparent: 1;
__u8 bind_address_no_port: 1;
};

enum {
INET_FLAGS_FREEBIND___x = 11,
INET_FLAGS_TRANSPARENT___x = 15,
INET_FLAGS_BIND_ADDRESS_NO_PORT___x = 18,
};

struct inet_sock___x {
unsigned long inet_flags;
};

static __always_inline __u8 get_inet_sock_freebind(void *inet_sock)
{
unsigned long inet_flags;

if (bpf_core_field_exists(struct inet_sock___o, freebind))
return BPF_CORE_READ_BITFIELD_PROBED((struct inet_sock___o *)inet_sock, freebind);

inet_flags = BPF_CORE_READ((struct inet_sock___x *)inet_sock, inet_flags);
return (1 << INET_FLAGS_FREEBIND___x) & inet_flags ? 1 : 0;
}

static __always_inline __u8 get_inet_sock_transparent(void *inet_sock)
{
unsigned long inet_flags;

if (bpf_core_field_exists(struct inet_sock___o, transparent))
return BPF_CORE_READ_BITFIELD_PROBED((struct inet_sock___o *)inet_sock, transparent);

inet_flags = BPF_CORE_READ((struct inet_sock___x *)inet_sock, inet_flags);
return (1 << INET_FLAGS_TRANSPARENT___x) & inet_flags ? 1 : 0;
}

static __always_inline __u8 get_inet_sock_bind_address_no_port(void *inet_sock)
{
unsigned long inet_flags;

if (bpf_core_field_exists(struct inet_sock___o, bind_address_no_port))
return BPF_CORE_READ_BITFIELD_PROBED((struct inet_sock___o *)inet_sock, bind_address_no_port);

inet_flags = BPF_CORE_READ((struct inet_sock___x *)inet_sock, inet_flags);
return (1 << INET_FLAGS_BIND_ADDRESS_NO_PORT___x) & inet_flags ? 1 : 0;
}

#endif /* __CORE_FIXES_BPF_H */

0 comments on commit 970f3be

Please sign in to comment.