1*858ea5e5SAndroid Build Coastguard Worker // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2*858ea5e5SAndroid Build Coastguard Worker /* Copyright (C) 2020 Facebook */
3*858ea5e5SAndroid Build Coastguard Worker #include <errno.h>
4*858ea5e5SAndroid Build Coastguard Worker #include <linux/err.h>
5*858ea5e5SAndroid Build Coastguard Worker #include <stdbool.h>
6*858ea5e5SAndroid Build Coastguard Worker #include <stdio.h>
7*858ea5e5SAndroid Build Coastguard Worker #include <stdlib.h>
8*858ea5e5SAndroid Build Coastguard Worker #include <string.h>
9*858ea5e5SAndroid Build Coastguard Worker #include <unistd.h>
10*858ea5e5SAndroid Build Coastguard Worker
11*858ea5e5SAndroid Build Coastguard Worker #include <bpf/bpf.h>
12*858ea5e5SAndroid Build Coastguard Worker #include <bpf/hashmap.h>
13*858ea5e5SAndroid Build Coastguard Worker
14*858ea5e5SAndroid Build Coastguard Worker #include "main.h"
15*858ea5e5SAndroid Build Coastguard Worker #include "skeleton/pid_iter.h"
16*858ea5e5SAndroid Build Coastguard Worker
17*858ea5e5SAndroid Build Coastguard Worker #ifdef BPFTOOL_WITHOUT_SKELETONS
18*858ea5e5SAndroid Build Coastguard Worker
build_obj_refs_table(struct hashmap ** map,enum bpf_obj_type type)19*858ea5e5SAndroid Build Coastguard Worker int build_obj_refs_table(struct hashmap **map, enum bpf_obj_type type)
20*858ea5e5SAndroid Build Coastguard Worker {
21*858ea5e5SAndroid Build Coastguard Worker return -ENOTSUP;
22*858ea5e5SAndroid Build Coastguard Worker }
delete_obj_refs_table(struct hashmap * map)23*858ea5e5SAndroid Build Coastguard Worker void delete_obj_refs_table(struct hashmap *map) {}
emit_obj_refs_plain(struct hashmap * map,__u32 id,const char * prefix)24*858ea5e5SAndroid Build Coastguard Worker void emit_obj_refs_plain(struct hashmap *map, __u32 id, const char *prefix) {}
emit_obj_refs_json(struct hashmap * map,__u32 id,json_writer_t * json_writer)25*858ea5e5SAndroid Build Coastguard Worker void emit_obj_refs_json(struct hashmap *map, __u32 id, json_writer_t *json_writer) {}
26*858ea5e5SAndroid Build Coastguard Worker
27*858ea5e5SAndroid Build Coastguard Worker #else /* BPFTOOL_WITHOUT_SKELETONS */
28*858ea5e5SAndroid Build Coastguard Worker
29*858ea5e5SAndroid Build Coastguard Worker #include "pid_iter.skel.h"
30*858ea5e5SAndroid Build Coastguard Worker
add_ref(struct hashmap * map,struct pid_iter_entry * e)31*858ea5e5SAndroid Build Coastguard Worker static void add_ref(struct hashmap *map, struct pid_iter_entry *e)
32*858ea5e5SAndroid Build Coastguard Worker {
33*858ea5e5SAndroid Build Coastguard Worker struct hashmap_entry *entry;
34*858ea5e5SAndroid Build Coastguard Worker struct obj_refs *refs;
35*858ea5e5SAndroid Build Coastguard Worker struct obj_ref *ref;
36*858ea5e5SAndroid Build Coastguard Worker int err, i;
37*858ea5e5SAndroid Build Coastguard Worker void *tmp;
38*858ea5e5SAndroid Build Coastguard Worker
39*858ea5e5SAndroid Build Coastguard Worker hashmap__for_each_key_entry(map, entry, e->id) {
40*858ea5e5SAndroid Build Coastguard Worker refs = entry->pvalue;
41*858ea5e5SAndroid Build Coastguard Worker
42*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < refs->ref_cnt; i++) {
43*858ea5e5SAndroid Build Coastguard Worker if (refs->refs[i].pid == e->pid)
44*858ea5e5SAndroid Build Coastguard Worker return;
45*858ea5e5SAndroid Build Coastguard Worker }
46*858ea5e5SAndroid Build Coastguard Worker
47*858ea5e5SAndroid Build Coastguard Worker tmp = realloc(refs->refs, (refs->ref_cnt + 1) * sizeof(*ref));
48*858ea5e5SAndroid Build Coastguard Worker if (!tmp) {
49*858ea5e5SAndroid Build Coastguard Worker p_err("failed to re-alloc memory for ID %u, PID %d, COMM %s...",
50*858ea5e5SAndroid Build Coastguard Worker e->id, e->pid, e->comm);
51*858ea5e5SAndroid Build Coastguard Worker return;
52*858ea5e5SAndroid Build Coastguard Worker }
53*858ea5e5SAndroid Build Coastguard Worker refs->refs = tmp;
54*858ea5e5SAndroid Build Coastguard Worker ref = &refs->refs[refs->ref_cnt];
55*858ea5e5SAndroid Build Coastguard Worker ref->pid = e->pid;
56*858ea5e5SAndroid Build Coastguard Worker memcpy(ref->comm, e->comm, sizeof(ref->comm));
57*858ea5e5SAndroid Build Coastguard Worker refs->ref_cnt++;
58*858ea5e5SAndroid Build Coastguard Worker
59*858ea5e5SAndroid Build Coastguard Worker return;
60*858ea5e5SAndroid Build Coastguard Worker }
61*858ea5e5SAndroid Build Coastguard Worker
62*858ea5e5SAndroid Build Coastguard Worker /* new ref */
63*858ea5e5SAndroid Build Coastguard Worker refs = calloc(1, sizeof(*refs));
64*858ea5e5SAndroid Build Coastguard Worker if (!refs) {
65*858ea5e5SAndroid Build Coastguard Worker p_err("failed to alloc memory for ID %u, PID %d, COMM %s...",
66*858ea5e5SAndroid Build Coastguard Worker e->id, e->pid, e->comm);
67*858ea5e5SAndroid Build Coastguard Worker return;
68*858ea5e5SAndroid Build Coastguard Worker }
69*858ea5e5SAndroid Build Coastguard Worker
70*858ea5e5SAndroid Build Coastguard Worker refs->refs = malloc(sizeof(*refs->refs));
71*858ea5e5SAndroid Build Coastguard Worker if (!refs->refs) {
72*858ea5e5SAndroid Build Coastguard Worker free(refs);
73*858ea5e5SAndroid Build Coastguard Worker p_err("failed to alloc memory for ID %u, PID %d, COMM %s...",
74*858ea5e5SAndroid Build Coastguard Worker e->id, e->pid, e->comm);
75*858ea5e5SAndroid Build Coastguard Worker return;
76*858ea5e5SAndroid Build Coastguard Worker }
77*858ea5e5SAndroid Build Coastguard Worker ref = &refs->refs[0];
78*858ea5e5SAndroid Build Coastguard Worker ref->pid = e->pid;
79*858ea5e5SAndroid Build Coastguard Worker memcpy(ref->comm, e->comm, sizeof(ref->comm));
80*858ea5e5SAndroid Build Coastguard Worker refs->ref_cnt = 1;
81*858ea5e5SAndroid Build Coastguard Worker refs->has_bpf_cookie = e->has_bpf_cookie;
82*858ea5e5SAndroid Build Coastguard Worker refs->bpf_cookie = e->bpf_cookie;
83*858ea5e5SAndroid Build Coastguard Worker
84*858ea5e5SAndroid Build Coastguard Worker err = hashmap__append(map, e->id, refs);
85*858ea5e5SAndroid Build Coastguard Worker if (err)
86*858ea5e5SAndroid Build Coastguard Worker p_err("failed to append entry to hashmap for ID %u: %s",
87*858ea5e5SAndroid Build Coastguard Worker e->id, strerror(errno));
88*858ea5e5SAndroid Build Coastguard Worker }
89*858ea5e5SAndroid Build Coastguard Worker
90*858ea5e5SAndroid Build Coastguard Worker static int __printf(2, 0)
libbpf_print_none(__maybe_unused enum libbpf_print_level level,__maybe_unused const char * format,__maybe_unused va_list args)91*858ea5e5SAndroid Build Coastguard Worker libbpf_print_none(__maybe_unused enum libbpf_print_level level,
92*858ea5e5SAndroid Build Coastguard Worker __maybe_unused const char *format,
93*858ea5e5SAndroid Build Coastguard Worker __maybe_unused va_list args)
94*858ea5e5SAndroid Build Coastguard Worker {
95*858ea5e5SAndroid Build Coastguard Worker return 0;
96*858ea5e5SAndroid Build Coastguard Worker }
97*858ea5e5SAndroid Build Coastguard Worker
build_obj_refs_table(struct hashmap ** map,enum bpf_obj_type type)98*858ea5e5SAndroid Build Coastguard Worker int build_obj_refs_table(struct hashmap **map, enum bpf_obj_type type)
99*858ea5e5SAndroid Build Coastguard Worker {
100*858ea5e5SAndroid Build Coastguard Worker struct pid_iter_entry *e;
101*858ea5e5SAndroid Build Coastguard Worker char buf[4096 / sizeof(*e) * sizeof(*e)];
102*858ea5e5SAndroid Build Coastguard Worker struct pid_iter_bpf *skel;
103*858ea5e5SAndroid Build Coastguard Worker int err, ret, fd = -1, i;
104*858ea5e5SAndroid Build Coastguard Worker
105*858ea5e5SAndroid Build Coastguard Worker *map = hashmap__new(hash_fn_for_key_as_id, equal_fn_for_key_as_id, NULL);
106*858ea5e5SAndroid Build Coastguard Worker if (IS_ERR(*map)) {
107*858ea5e5SAndroid Build Coastguard Worker p_err("failed to create hashmap for PID references");
108*858ea5e5SAndroid Build Coastguard Worker return -1;
109*858ea5e5SAndroid Build Coastguard Worker }
110*858ea5e5SAndroid Build Coastguard Worker set_max_rlimit();
111*858ea5e5SAndroid Build Coastguard Worker
112*858ea5e5SAndroid Build Coastguard Worker skel = pid_iter_bpf__open();
113*858ea5e5SAndroid Build Coastguard Worker if (!skel) {
114*858ea5e5SAndroid Build Coastguard Worker p_err("failed to open PID iterator skeleton");
115*858ea5e5SAndroid Build Coastguard Worker return -1;
116*858ea5e5SAndroid Build Coastguard Worker }
117*858ea5e5SAndroid Build Coastguard Worker
118*858ea5e5SAndroid Build Coastguard Worker skel->rodata->obj_type = type;
119*858ea5e5SAndroid Build Coastguard Worker
120*858ea5e5SAndroid Build Coastguard Worker if (!verifier_logs) {
121*858ea5e5SAndroid Build Coastguard Worker libbpf_print_fn_t default_print;
122*858ea5e5SAndroid Build Coastguard Worker
123*858ea5e5SAndroid Build Coastguard Worker /* Unless debug information is on, we don't want the output to
124*858ea5e5SAndroid Build Coastguard Worker * be polluted with libbpf errors if bpf_iter is not supported.
125*858ea5e5SAndroid Build Coastguard Worker */
126*858ea5e5SAndroid Build Coastguard Worker default_print = libbpf_set_print(libbpf_print_none);
127*858ea5e5SAndroid Build Coastguard Worker err = pid_iter_bpf__load(skel);
128*858ea5e5SAndroid Build Coastguard Worker libbpf_set_print(default_print);
129*858ea5e5SAndroid Build Coastguard Worker } else {
130*858ea5e5SAndroid Build Coastguard Worker err = pid_iter_bpf__load(skel);
131*858ea5e5SAndroid Build Coastguard Worker }
132*858ea5e5SAndroid Build Coastguard Worker if (err) {
133*858ea5e5SAndroid Build Coastguard Worker /* too bad, kernel doesn't support BPF iterators yet */
134*858ea5e5SAndroid Build Coastguard Worker err = 0;
135*858ea5e5SAndroid Build Coastguard Worker goto out;
136*858ea5e5SAndroid Build Coastguard Worker }
137*858ea5e5SAndroid Build Coastguard Worker err = pid_iter_bpf__attach(skel);
138*858ea5e5SAndroid Build Coastguard Worker if (err) {
139*858ea5e5SAndroid Build Coastguard Worker /* if we loaded above successfully, attach has to succeed */
140*858ea5e5SAndroid Build Coastguard Worker p_err("failed to attach PID iterator: %d", err);
141*858ea5e5SAndroid Build Coastguard Worker goto out;
142*858ea5e5SAndroid Build Coastguard Worker }
143*858ea5e5SAndroid Build Coastguard Worker
144*858ea5e5SAndroid Build Coastguard Worker fd = bpf_iter_create(bpf_link__fd(skel->links.iter));
145*858ea5e5SAndroid Build Coastguard Worker if (fd < 0) {
146*858ea5e5SAndroid Build Coastguard Worker err = -errno;
147*858ea5e5SAndroid Build Coastguard Worker p_err("failed to create PID iterator session: %d", err);
148*858ea5e5SAndroid Build Coastguard Worker goto out;
149*858ea5e5SAndroid Build Coastguard Worker }
150*858ea5e5SAndroid Build Coastguard Worker
151*858ea5e5SAndroid Build Coastguard Worker while (true) {
152*858ea5e5SAndroid Build Coastguard Worker ret = read(fd, buf, sizeof(buf));
153*858ea5e5SAndroid Build Coastguard Worker if (ret < 0) {
154*858ea5e5SAndroid Build Coastguard Worker if (errno == EAGAIN)
155*858ea5e5SAndroid Build Coastguard Worker continue;
156*858ea5e5SAndroid Build Coastguard Worker err = -errno;
157*858ea5e5SAndroid Build Coastguard Worker p_err("failed to read PID iterator output: %d", err);
158*858ea5e5SAndroid Build Coastguard Worker goto out;
159*858ea5e5SAndroid Build Coastguard Worker }
160*858ea5e5SAndroid Build Coastguard Worker if (ret == 0)
161*858ea5e5SAndroid Build Coastguard Worker break;
162*858ea5e5SAndroid Build Coastguard Worker if (ret % sizeof(*e)) {
163*858ea5e5SAndroid Build Coastguard Worker err = -EINVAL;
164*858ea5e5SAndroid Build Coastguard Worker p_err("invalid PID iterator output format");
165*858ea5e5SAndroid Build Coastguard Worker goto out;
166*858ea5e5SAndroid Build Coastguard Worker }
167*858ea5e5SAndroid Build Coastguard Worker ret /= sizeof(*e);
168*858ea5e5SAndroid Build Coastguard Worker
169*858ea5e5SAndroid Build Coastguard Worker e = (void *)buf;
170*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < ret; i++, e++) {
171*858ea5e5SAndroid Build Coastguard Worker add_ref(*map, e);
172*858ea5e5SAndroid Build Coastguard Worker }
173*858ea5e5SAndroid Build Coastguard Worker }
174*858ea5e5SAndroid Build Coastguard Worker err = 0;
175*858ea5e5SAndroid Build Coastguard Worker out:
176*858ea5e5SAndroid Build Coastguard Worker if (fd >= 0)
177*858ea5e5SAndroid Build Coastguard Worker close(fd);
178*858ea5e5SAndroid Build Coastguard Worker pid_iter_bpf__destroy(skel);
179*858ea5e5SAndroid Build Coastguard Worker return err;
180*858ea5e5SAndroid Build Coastguard Worker }
181*858ea5e5SAndroid Build Coastguard Worker
delete_obj_refs_table(struct hashmap * map)182*858ea5e5SAndroid Build Coastguard Worker void delete_obj_refs_table(struct hashmap *map)
183*858ea5e5SAndroid Build Coastguard Worker {
184*858ea5e5SAndroid Build Coastguard Worker struct hashmap_entry *entry;
185*858ea5e5SAndroid Build Coastguard Worker size_t bkt;
186*858ea5e5SAndroid Build Coastguard Worker
187*858ea5e5SAndroid Build Coastguard Worker if (!map)
188*858ea5e5SAndroid Build Coastguard Worker return;
189*858ea5e5SAndroid Build Coastguard Worker
190*858ea5e5SAndroid Build Coastguard Worker hashmap__for_each_entry(map, entry, bkt) {
191*858ea5e5SAndroid Build Coastguard Worker struct obj_refs *refs = entry->pvalue;
192*858ea5e5SAndroid Build Coastguard Worker
193*858ea5e5SAndroid Build Coastguard Worker free(refs->refs);
194*858ea5e5SAndroid Build Coastguard Worker free(refs);
195*858ea5e5SAndroid Build Coastguard Worker }
196*858ea5e5SAndroid Build Coastguard Worker
197*858ea5e5SAndroid Build Coastguard Worker hashmap__free(map);
198*858ea5e5SAndroid Build Coastguard Worker }
199*858ea5e5SAndroid Build Coastguard Worker
emit_obj_refs_json(struct hashmap * map,__u32 id,json_writer_t * json_writer)200*858ea5e5SAndroid Build Coastguard Worker void emit_obj_refs_json(struct hashmap *map, __u32 id,
201*858ea5e5SAndroid Build Coastguard Worker json_writer_t *json_writer)
202*858ea5e5SAndroid Build Coastguard Worker {
203*858ea5e5SAndroid Build Coastguard Worker struct hashmap_entry *entry;
204*858ea5e5SAndroid Build Coastguard Worker
205*858ea5e5SAndroid Build Coastguard Worker if (hashmap__empty(map))
206*858ea5e5SAndroid Build Coastguard Worker return;
207*858ea5e5SAndroid Build Coastguard Worker
208*858ea5e5SAndroid Build Coastguard Worker hashmap__for_each_key_entry(map, entry, id) {
209*858ea5e5SAndroid Build Coastguard Worker struct obj_refs *refs = entry->pvalue;
210*858ea5e5SAndroid Build Coastguard Worker int i;
211*858ea5e5SAndroid Build Coastguard Worker
212*858ea5e5SAndroid Build Coastguard Worker if (refs->ref_cnt == 0)
213*858ea5e5SAndroid Build Coastguard Worker break;
214*858ea5e5SAndroid Build Coastguard Worker
215*858ea5e5SAndroid Build Coastguard Worker if (refs->has_bpf_cookie)
216*858ea5e5SAndroid Build Coastguard Worker jsonw_lluint_field(json_writer, "bpf_cookie", refs->bpf_cookie);
217*858ea5e5SAndroid Build Coastguard Worker
218*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_writer, "pids");
219*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(json_writer);
220*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < refs->ref_cnt; i++) {
221*858ea5e5SAndroid Build Coastguard Worker struct obj_ref *ref = &refs->refs[i];
222*858ea5e5SAndroid Build Coastguard Worker
223*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(json_writer);
224*858ea5e5SAndroid Build Coastguard Worker jsonw_int_field(json_writer, "pid", ref->pid);
225*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(json_writer, "comm", ref->comm);
226*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_writer);
227*858ea5e5SAndroid Build Coastguard Worker }
228*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(json_writer);
229*858ea5e5SAndroid Build Coastguard Worker break;
230*858ea5e5SAndroid Build Coastguard Worker }
231*858ea5e5SAndroid Build Coastguard Worker }
232*858ea5e5SAndroid Build Coastguard Worker
emit_obj_refs_plain(struct hashmap * map,__u32 id,const char * prefix)233*858ea5e5SAndroid Build Coastguard Worker void emit_obj_refs_plain(struct hashmap *map, __u32 id, const char *prefix)
234*858ea5e5SAndroid Build Coastguard Worker {
235*858ea5e5SAndroid Build Coastguard Worker struct hashmap_entry *entry;
236*858ea5e5SAndroid Build Coastguard Worker
237*858ea5e5SAndroid Build Coastguard Worker if (hashmap__empty(map))
238*858ea5e5SAndroid Build Coastguard Worker return;
239*858ea5e5SAndroid Build Coastguard Worker
240*858ea5e5SAndroid Build Coastguard Worker hashmap__for_each_key_entry(map, entry, id) {
241*858ea5e5SAndroid Build Coastguard Worker struct obj_refs *refs = entry->pvalue;
242*858ea5e5SAndroid Build Coastguard Worker int i;
243*858ea5e5SAndroid Build Coastguard Worker
244*858ea5e5SAndroid Build Coastguard Worker if (refs->ref_cnt == 0)
245*858ea5e5SAndroid Build Coastguard Worker break;
246*858ea5e5SAndroid Build Coastguard Worker
247*858ea5e5SAndroid Build Coastguard Worker if (refs->has_bpf_cookie)
248*858ea5e5SAndroid Build Coastguard Worker printf("\n\tbpf_cookie %llu", (unsigned long long) refs->bpf_cookie);
249*858ea5e5SAndroid Build Coastguard Worker
250*858ea5e5SAndroid Build Coastguard Worker printf("%s", prefix);
251*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < refs->ref_cnt; i++) {
252*858ea5e5SAndroid Build Coastguard Worker struct obj_ref *ref = &refs->refs[i];
253*858ea5e5SAndroid Build Coastguard Worker
254*858ea5e5SAndroid Build Coastguard Worker printf("%s%s(%d)", i == 0 ? "" : ", ", ref->comm, ref->pid);
255*858ea5e5SAndroid Build Coastguard Worker }
256*858ea5e5SAndroid Build Coastguard Worker break;
257*858ea5e5SAndroid Build Coastguard Worker }
258*858ea5e5SAndroid Build Coastguard Worker }
259*858ea5e5SAndroid Build Coastguard Worker
260*858ea5e5SAndroid Build Coastguard Worker
261*858ea5e5SAndroid Build Coastguard Worker #endif
262