From 591fcbc930e4361d9c3cd4f94bb9a9956e747c95 Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Mon, 17 Jan 2022 16:58:02 +0000 Subject: [PATCH] tools: Update BPF script for trampolines on newer kernels (5.10+) Since Linux 5.10 and commit 3aac1ead5eb6 ("bpf: Move prog->aux->linked_prog and trampoline into bpf_link on attach"), the kernel "struct bpf_prog_aux" no longer has a "trampoline" attribute. Instead, it got a "dst_trampoline" attribute, but the latter cannot be used as a drop-in remplacement, because the reference from the tracing program to the target is removed after attaching (and this pointer is NULL). To retrieve the target program, we must instead loop on the existing links, find their parent "struct bpf_tracing_link" object, and get the target program from there. Let's adjust the script accordingly, but keep compatibility for older kernels too. Signed-off-by: Quentin Monnet --- tools/bpf_inspect.py | 63 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/tools/bpf_inspect.py b/tools/bpf_inspect.py index 0ce7959f8..f6d8b183b 100755 --- a/tools/bpf_inspect.py +++ b/tools/bpf_inspect.py @@ -4,8 +4,14 @@ import argparse +from drgn import container_of from drgn.helpers import enum_type_to_class -from drgn.helpers.linux import bpf_map_for_each, bpf_prog_for_each, hlist_for_each_entry +from drgn.helpers.linux import ( + bpf_link_for_each, + bpf_map_for_each, + bpf_prog_for_each, + hlist_for_each_entry, +) BpfMapType = enum_type_to_class(prog.type("enum bpf_map_type"), "BpfMapType") BpfProgType = enum_type_to_class(prog.type("enum bpf_prog_type"), "BpfProgType") @@ -50,10 +56,9 @@ def attach_type_to_tramp(attach_type): return BpfProgTrampType.BPF_TRAMP_REPLACE -def get_linked_func(bpf_prog): +def get_linked_func(bpf_prog, linked_prog): kind = attach_type_to_tramp(bpf_prog.expected_attach_type) - linked_prog = bpf_prog.aux.linked_prog linked_prog_id = linked_prog.aux.id.value_() linked_btf_id = bpf_prog.aux.attach_btf_id.value_() linked_name = ( @@ -64,15 +69,7 @@ def get_linked_func(bpf_prog): return f"{linked_prog_id}->{linked_btf_id}: {kind.name} {linked_name}" -def get_tramp_progs(bpf_prog): - try: - tr = bpf_prog.aux.member_("trampoline") - except LookupError: - # Trampoline is available since Linux kernel commit - # fec56f5890d9 ("bpf: Introduce BPF trampoline") (in v5.5). - # Skip trampoline if current kernel doesn't support it. - return - +def get_progs_from_tramp(trampoline): if not tr: return @@ -86,13 +83,53 @@ def get_tramp_progs(bpf_prog): yield tramp_aux.prog +def get_progs_from_tracing_link(bpf_prog): + for link in bpf_link_for_each(prog): + if link.prog.aux.id.value_() == bpf_prog.aux.id.value_(): + tr_link = container_of(link, "struct bpf_tracing_link", "link") + if tr_link and tr_link.tgt_prog: + yield tr_link.tgt_prog + + +def get_tramp_progs(bpf_prog): + # dst_rampoline replaces "trampoline" since Linux kernel commit + # 3aac1ead5eb6 ("bpf: Move prog->aux->linked_prog and trampoline into + # bpf_link on attach") (in v5.10). + try: + tramp = bpf_prog.aux.member_("dst_trampoline") + if tramp: + yield from get_progs_from_tramp(tramp) + else: + yield from get_progs_from_tracing_link(bpf_prog) + except LookupError: + # Before that, "trampoline" is available since Linux kernel commit + # fec56f5890d9 ("bpf: Introduce BPF trampoline") (in v5.5). + try: + tramp = bpf_prog.aux.member_("trampoline") + except LookupError: + # This kernel doesn't support trampolines at all. + return + yield from get_progs_from_tramp(tramp) + + def list_bpf_progs(args): for bpf_prog in bpf_prog_for_each(prog): id_ = bpf_prog.aux.id.value_() type_ = BpfProgType(bpf_prog.type).name name = get_prog_name(bpf_prog) - linked = ", ".join([get_linked_func(p) for p in get_tramp_progs(bpf_prog)]) + progs = [] + for p in get_tramp_progs(bpf_prog): + try: + linked_prog = p.aux.member_("linked_prog") + caller_prog = p + except LookupError: + # Linux 5.10+ + linked_prog = p + caller_prog = bpf_prog + progs.append(get_linked_func(caller_prog, linked_prog)) + + linked = ", ".join(progs) if linked: linked = f" linked:[{linked}]"