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