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_map_fops __ksym; 33 extern const void bpf_prog_fops __ksym; 34 extern const void btf_fops __ksym; 35 36 const volatile enum bpf_obj_type obj_type = BPF_OBJ_UNKNOWN; 37 38 static __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 */ 55 static __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 65 SEC("iter/task_file") 66 int 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 (BPF_CORE_READ(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 119 char LICENSE[] SEC("license") = "Dual BSD/GPL"; 120