1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2/* Copyright (c) 2020 Facebook */ 3#include <vmlinux.h> 4#include <bpf/bpf_helpers.h> 5#include <bpf/bpf_core_read.h> 6#include <bpf/bpf_tracing.h> 7#include "pid_iter.h" 8 9/* keep in sync with the definition in main.h */ 10enum bpf_obj_type { 11 BPF_OBJ_UNKNOWN, 12 BPF_OBJ_PROG, 13 BPF_OBJ_MAP, 14 BPF_OBJ_LINK, 15 BPF_OBJ_BTF, 16}; 17 18struct bpf_perf_link___local { 19 struct bpf_link link; 20 struct file *perf_file; 21} __attribute__((preserve_access_index)); 22 23struct perf_event___local { 24 u64 bpf_cookie; 25} __attribute__((preserve_access_index)); 26 27enum bpf_link_type___local { 28 BPF_LINK_TYPE_PERF_EVENT___local = 7, 29}; 30 31extern const void bpf_link_fops __ksym; 32extern const void bpf_map_fops __ksym; 33extern const void bpf_prog_fops __ksym; 34extern const void btf_fops __ksym; 35 36const volatile enum bpf_obj_type obj_type = BPF_OBJ_UNKNOWN; 37 38static __always_inline __u32 get_obj_id(void *ent, enum bpf_obj_type type) 39{ 40 switch (type) { 41 case BPF_OBJ_PROG: 42 return BPF_CORE_READ((struct bpf_prog *)ent, aux, id); 43 case BPF_OBJ_MAP: 44 return BPF_CORE_READ((struct bpf_map *)ent, id); 45 case BPF_OBJ_BTF: 46 return BPF_CORE_READ((struct btf *)ent, id); 47 case BPF_OBJ_LINK: 48 return BPF_CORE_READ((struct bpf_link *)ent, id); 49 default: 50 return 0; 51 } 52} 53 54/* could be used only with BPF_LINK_TYPE_PERF_EVENT links */ 55static __u64 get_bpf_cookie(struct bpf_link *link) 56{ 57 struct bpf_perf_link___local *perf_link; 58 struct perf_event___local *event; 59 60 perf_link = container_of(link, struct bpf_perf_link___local, link); 61 event = BPF_CORE_READ(perf_link, perf_file, private_data); 62 return BPF_CORE_READ(event, bpf_cookie); 63} 64 65SEC("iter/task_file") 66int iter(struct bpf_iter__task_file *ctx) 67{ 68 struct file *file = ctx->file; 69 struct task_struct *task = ctx->task; 70 struct pid_iter_entry e; 71 const void *fops; 72 73 if (!file || !task) 74 return 0; 75 76 switch (obj_type) { 77 case BPF_OBJ_PROG: 78 fops = &bpf_prog_fops; 79 break; 80 case BPF_OBJ_MAP: 81 fops = &bpf_map_fops; 82 break; 83 case BPF_OBJ_BTF: 84 fops = &btf_fops; 85 break; 86 case BPF_OBJ_LINK: 87 fops = &bpf_link_fops; 88 break; 89 default: 90 return 0; 91 } 92 93 if (file->f_op != fops) 94 return 0; 95 96 __builtin_memset(&e, 0, sizeof(e)); 97 e.pid = task->tgid; 98 e.id = get_obj_id(file->private_data, obj_type); 99 100 if (obj_type == BPF_OBJ_LINK && 101 bpf_core_enum_value_exists(enum bpf_link_type___local, 102 BPF_LINK_TYPE_PERF_EVENT___local)) { 103 struct bpf_link *link = (struct bpf_link *) file->private_data; 104 105 if (link->type == bpf_core_enum_value(enum bpf_link_type___local, 106 BPF_LINK_TYPE_PERF_EVENT___local)) { 107 e.has_bpf_cookie = true; 108 e.bpf_cookie = get_bpf_cookie(link); 109 } 110 } 111 112 bpf_probe_read_kernel_str(&e.comm, sizeof(e.comm), 113 task->group_leader->comm); 114 bpf_seq_write(ctx->meta->seq, &e, sizeof(e)); 115 116 return 0; 117} 118 119char LICENSE[] SEC("license") = "Dual BSD/GPL"; 120