Last active
March 31, 2020 03:50
-
-
Save anakryiko/562dff8e39c619a5ee247bb55aa057c7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env drgn | |
"""List all active bpf_links and its owners""" | |
from drgn.helpers import enum_type_to_class | |
from drgn.helpers.linux.fs import for_each_file | |
from drgn.helpers.linux.pid import for_each_task | |
from drgn.helpers.linux import cgroup_path | |
from drgn import FaultError, cast, container_of | |
BpfProgType = enum_type_to_class(prog.type("enum bpf_prog_type"), "BpfProgType") | |
BpfAttachType = enum_type_to_class( prog.type("enum bpf_attach_type"), "BpfAttachType") | |
try: | |
bpf_link_fops = prog["bpf_link_fops"].address_of_(); | |
except KeyError: | |
print("Current kernel doesn't support bpf_links.") | |
exit(0) | |
bpf_raw_tp_lops = prog["bpf_raw_tp_lops"].address_of_(); | |
bpf_tracing_link_lops = prog["bpf_tracing_link_lops"].address_of_(); | |
try: | |
bpf_cgroup_link_lops = prog["bpf_cgroup_link_lops"].address_of_(); | |
except KeyError: | |
bpf_cgroup_link_lops = None | |
def get_btf_name(btf, btf_id): | |
type_ = btf.types[btf_id] | |
if type_.name_off < btf.hdr.str_len: | |
return btf.strings[type_.name_off].address_of_().string_().decode() | |
return "" | |
def get_prog_btf_name(bpf_prog): | |
aux = bpf_prog.aux | |
if aux.btf: | |
# func_info[0] points to BPF program function itself. | |
return get_btf_name(aux.btf, aux.func_info[0].type_id) | |
return "" | |
def get_prog_name(bpf_prog): | |
return get_prog_btf_name(bpf_prog) or bpf_prog.aux.name.string_().decode() | |
def print_prog_info(bpf_prog): | |
id_ = bpf_prog.aux.id.value_() | |
type_ = BpfProgType(bpf_prog.type).name | |
name = get_prog_name(bpf_prog) | |
print(f"prog:\t'{name}' id:{id_} type:{type_}") | |
class LinkData: | |
def __init__(self, link): | |
self.link = link | |
self.pids = set({}) | |
self.tasks = [] | |
links = {} | |
for task in for_each_task(prog): | |
try: | |
for fd, file in for_each_file(task): | |
try: | |
if not file or file.f_op != bpf_link_fops: | |
continue | |
link = cast("struct bpf_link *", file.private_data) | |
if link.value_() not in links: | |
links[link.value_()] = LinkData(link) | |
link_data = links[link.value_()] | |
if task.tgid.value_() not in link_data.pids: | |
link_data.tasks.append(task.group_leader) | |
except FaultError: | |
continue | |
except FaultError: | |
continue | |
print("Found total {} bpf_links.".format(len(links))) | |
print("-------------------------------------------------") | |
for _, data in links.items(): | |
try: | |
bpf_link = data.link | |
lops = bpf_link.ops.read_() | |
if lops == bpf_raw_tp_lops: | |
link = container_of(bpf_link, 'struct bpf_raw_tp_link', 'link'); | |
print("type:\traw_tp") | |
print_prog_info(link.link.prog) | |
print("tp:\t{}".format(link.btp.tp.name.string_().decode())) | |
elif lops == bpf_tracing_link_lops: | |
link = container_of(bpf_link, 'struct bpf_tracing_link', 'link'); | |
print("type:\ttracing") | |
print_prog_info(link.link.prog) | |
elif lops == bpf_cgroup_link_lops: | |
link = container_of(bpf_link, 'struct bpf_cgroup_link', 'link'); | |
print("type:\tcgroup") | |
print_prog_info(link.link.prog) | |
print("attach:\t{}".format(BpfAttachType(link.type).name)); | |
if link.cgroup: | |
print("cgroup:\t{}".format(cgroup_path(link.cgroup).decode())) | |
else: | |
print("cgroup:\t<detached>") | |
else: | |
print("unknown kind of bpf_link: {}".format(link)) | |
print("pids:\t{}".format(", ".join([str(t.tgid.value_()) for t in data.tasks]))) | |
print("-------------------------------------------------") | |
except FaultError: | |
continue |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment