1*858ea5e5SAndroid Build Coastguard Worker // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2*858ea5e5SAndroid Build Coastguard Worker // Copyright (C) 2017 Facebook
3*858ea5e5SAndroid Build Coastguard Worker // Author: Roman Gushchin <[email protected]>
4*858ea5e5SAndroid Build Coastguard Worker
5*858ea5e5SAndroid Build Coastguard Worker #define _XOPEN_SOURCE 500
6*858ea5e5SAndroid Build Coastguard Worker #include <errno.h>
7*858ea5e5SAndroid Build Coastguard Worker #include <fcntl.h>
8*858ea5e5SAndroid Build Coastguard Worker #include <ftw.h>
9*858ea5e5SAndroid Build Coastguard Worker #include <mntent.h>
10*858ea5e5SAndroid Build Coastguard Worker #include <stdio.h>
11*858ea5e5SAndroid Build Coastguard Worker #include <stdlib.h>
12*858ea5e5SAndroid Build Coastguard Worker #include <string.h>
13*858ea5e5SAndroid Build Coastguard Worker #include <sys/stat.h>
14*858ea5e5SAndroid Build Coastguard Worker #include <sys/types.h>
15*858ea5e5SAndroid Build Coastguard Worker #include <unistd.h>
16*858ea5e5SAndroid Build Coastguard Worker
17*858ea5e5SAndroid Build Coastguard Worker #include <bpf/bpf.h>
18*858ea5e5SAndroid Build Coastguard Worker #include <bpf/btf.h>
19*858ea5e5SAndroid Build Coastguard Worker
20*858ea5e5SAndroid Build Coastguard Worker #include "main.h"
21*858ea5e5SAndroid Build Coastguard Worker
22*858ea5e5SAndroid Build Coastguard Worker #define HELP_SPEC_ATTACH_FLAGS \
23*858ea5e5SAndroid Build Coastguard Worker "ATTACH_FLAGS := { multi | override }"
24*858ea5e5SAndroid Build Coastguard Worker
25*858ea5e5SAndroid Build Coastguard Worker #define HELP_SPEC_ATTACH_TYPES \
26*858ea5e5SAndroid Build Coastguard Worker " ATTACH_TYPE := { cgroup_inet_ingress | cgroup_inet_egress |\n" \
27*858ea5e5SAndroid Build Coastguard Worker " cgroup_inet_sock_create | cgroup_sock_ops |\n" \
28*858ea5e5SAndroid Build Coastguard Worker " cgroup_device | cgroup_inet4_bind |\n" \
29*858ea5e5SAndroid Build Coastguard Worker " cgroup_inet6_bind | cgroup_inet4_post_bind |\n" \
30*858ea5e5SAndroid Build Coastguard Worker " cgroup_inet6_post_bind | cgroup_inet4_connect |\n" \
31*858ea5e5SAndroid Build Coastguard Worker " cgroup_inet6_connect | cgroup_unix_connect |\n" \
32*858ea5e5SAndroid Build Coastguard Worker " cgroup_inet4_getpeername | cgroup_inet6_getpeername |\n" \
33*858ea5e5SAndroid Build Coastguard Worker " cgroup_unix_getpeername | cgroup_inet4_getsockname |\n" \
34*858ea5e5SAndroid Build Coastguard Worker " cgroup_inet6_getsockname | cgroup_unix_getsockname |\n" \
35*858ea5e5SAndroid Build Coastguard Worker " cgroup_udp4_sendmsg | cgroup_udp6_sendmsg |\n" \
36*858ea5e5SAndroid Build Coastguard Worker " cgroup_unix_sendmsg | cgroup_udp4_recvmsg |\n" \
37*858ea5e5SAndroid Build Coastguard Worker " cgroup_udp6_recvmsg | cgroup_unix_recvmsg |\n" \
38*858ea5e5SAndroid Build Coastguard Worker " cgroup_sysctl | cgroup_getsockopt |\n" \
39*858ea5e5SAndroid Build Coastguard Worker " cgroup_setsockopt | cgroup_inet_sock_release }"
40*858ea5e5SAndroid Build Coastguard Worker
41*858ea5e5SAndroid Build Coastguard Worker static unsigned int query_flags;
42*858ea5e5SAndroid Build Coastguard Worker static struct btf *btf_vmlinux;
43*858ea5e5SAndroid Build Coastguard Worker static __u32 btf_vmlinux_id;
44*858ea5e5SAndroid Build Coastguard Worker
parse_attach_type(const char * str)45*858ea5e5SAndroid Build Coastguard Worker static enum bpf_attach_type parse_attach_type(const char *str)
46*858ea5e5SAndroid Build Coastguard Worker {
47*858ea5e5SAndroid Build Coastguard Worker const char *attach_type_str;
48*858ea5e5SAndroid Build Coastguard Worker enum bpf_attach_type type;
49*858ea5e5SAndroid Build Coastguard Worker
50*858ea5e5SAndroid Build Coastguard Worker for (type = 0; ; type++) {
51*858ea5e5SAndroid Build Coastguard Worker attach_type_str = libbpf_bpf_attach_type_str(type);
52*858ea5e5SAndroid Build Coastguard Worker if (!attach_type_str)
53*858ea5e5SAndroid Build Coastguard Worker break;
54*858ea5e5SAndroid Build Coastguard Worker if (!strcmp(str, attach_type_str))
55*858ea5e5SAndroid Build Coastguard Worker return type;
56*858ea5e5SAndroid Build Coastguard Worker }
57*858ea5e5SAndroid Build Coastguard Worker
58*858ea5e5SAndroid Build Coastguard Worker /* Also check traditionally used attach type strings. For these we keep
59*858ea5e5SAndroid Build Coastguard Worker * allowing prefixed usage.
60*858ea5e5SAndroid Build Coastguard Worker */
61*858ea5e5SAndroid Build Coastguard Worker for (type = 0; ; type++) {
62*858ea5e5SAndroid Build Coastguard Worker attach_type_str = bpf_attach_type_input_str(type);
63*858ea5e5SAndroid Build Coastguard Worker if (!attach_type_str)
64*858ea5e5SAndroid Build Coastguard Worker break;
65*858ea5e5SAndroid Build Coastguard Worker if (is_prefix(str, attach_type_str))
66*858ea5e5SAndroid Build Coastguard Worker return type;
67*858ea5e5SAndroid Build Coastguard Worker }
68*858ea5e5SAndroid Build Coastguard Worker
69*858ea5e5SAndroid Build Coastguard Worker return __MAX_BPF_ATTACH_TYPE;
70*858ea5e5SAndroid Build Coastguard Worker }
71*858ea5e5SAndroid Build Coastguard Worker
guess_vmlinux_btf_id(__u32 attach_btf_obj_id)72*858ea5e5SAndroid Build Coastguard Worker static void guess_vmlinux_btf_id(__u32 attach_btf_obj_id)
73*858ea5e5SAndroid Build Coastguard Worker {
74*858ea5e5SAndroid Build Coastguard Worker struct bpf_btf_info btf_info = {};
75*858ea5e5SAndroid Build Coastguard Worker __u32 btf_len = sizeof(btf_info);
76*858ea5e5SAndroid Build Coastguard Worker char name[16] = {};
77*858ea5e5SAndroid Build Coastguard Worker int err;
78*858ea5e5SAndroid Build Coastguard Worker int fd;
79*858ea5e5SAndroid Build Coastguard Worker
80*858ea5e5SAndroid Build Coastguard Worker btf_info.name = ptr_to_u64(name);
81*858ea5e5SAndroid Build Coastguard Worker btf_info.name_len = sizeof(name);
82*858ea5e5SAndroid Build Coastguard Worker
83*858ea5e5SAndroid Build Coastguard Worker fd = bpf_btf_get_fd_by_id(attach_btf_obj_id);
84*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
85*858ea5e5SAndroid Build Coastguard Worker return;
86*858ea5e5SAndroid Build Coastguard Worker
87*858ea5e5SAndroid Build Coastguard Worker err = bpf_btf_get_info_by_fd(fd, &btf_info, &btf_len);
88*858ea5e5SAndroid Build Coastguard Worker if (err)
89*858ea5e5SAndroid Build Coastguard Worker goto out;
90*858ea5e5SAndroid Build Coastguard Worker
91*858ea5e5SAndroid Build Coastguard Worker if (btf_info.kernel_btf && strncmp(name, "vmlinux", sizeof(name)) == 0)
92*858ea5e5SAndroid Build Coastguard Worker btf_vmlinux_id = btf_info.id;
93*858ea5e5SAndroid Build Coastguard Worker
94*858ea5e5SAndroid Build Coastguard Worker out:
95*858ea5e5SAndroid Build Coastguard Worker close(fd);
96*858ea5e5SAndroid Build Coastguard Worker }
97*858ea5e5SAndroid Build Coastguard Worker
show_bpf_prog(int id,enum bpf_attach_type attach_type,const char * attach_flags_str,int level)98*858ea5e5SAndroid Build Coastguard Worker static int show_bpf_prog(int id, enum bpf_attach_type attach_type,
99*858ea5e5SAndroid Build Coastguard Worker const char *attach_flags_str,
100*858ea5e5SAndroid Build Coastguard Worker int level)
101*858ea5e5SAndroid Build Coastguard Worker {
102*858ea5e5SAndroid Build Coastguard Worker char prog_name[MAX_PROG_FULL_NAME];
103*858ea5e5SAndroid Build Coastguard Worker const char *attach_btf_name = NULL;
104*858ea5e5SAndroid Build Coastguard Worker struct bpf_prog_info info = {};
105*858ea5e5SAndroid Build Coastguard Worker const char *attach_type_str;
106*858ea5e5SAndroid Build Coastguard Worker __u32 info_len = sizeof(info);
107*858ea5e5SAndroid Build Coastguard Worker int prog_fd;
108*858ea5e5SAndroid Build Coastguard Worker
109*858ea5e5SAndroid Build Coastguard Worker prog_fd = bpf_prog_get_fd_by_id(id);
110*858ea5e5SAndroid Build Coastguard Worker if (prog_fd < 0)
111*858ea5e5SAndroid Build Coastguard Worker return -1;
112*858ea5e5SAndroid Build Coastguard Worker
113*858ea5e5SAndroid Build Coastguard Worker if (bpf_prog_get_info_by_fd(prog_fd, &info, &info_len)) {
114*858ea5e5SAndroid Build Coastguard Worker close(prog_fd);
115*858ea5e5SAndroid Build Coastguard Worker return -1;
116*858ea5e5SAndroid Build Coastguard Worker }
117*858ea5e5SAndroid Build Coastguard Worker
118*858ea5e5SAndroid Build Coastguard Worker attach_type_str = libbpf_bpf_attach_type_str(attach_type);
119*858ea5e5SAndroid Build Coastguard Worker
120*858ea5e5SAndroid Build Coastguard Worker if (btf_vmlinux) {
121*858ea5e5SAndroid Build Coastguard Worker if (!btf_vmlinux_id)
122*858ea5e5SAndroid Build Coastguard Worker guess_vmlinux_btf_id(info.attach_btf_obj_id);
123*858ea5e5SAndroid Build Coastguard Worker
124*858ea5e5SAndroid Build Coastguard Worker if (btf_vmlinux_id == info.attach_btf_obj_id &&
125*858ea5e5SAndroid Build Coastguard Worker info.attach_btf_id < btf__type_cnt(btf_vmlinux)) {
126*858ea5e5SAndroid Build Coastguard Worker const struct btf_type *t =
127*858ea5e5SAndroid Build Coastguard Worker btf__type_by_id(btf_vmlinux, info.attach_btf_id);
128*858ea5e5SAndroid Build Coastguard Worker attach_btf_name =
129*858ea5e5SAndroid Build Coastguard Worker btf__name_by_offset(btf_vmlinux, t->name_off);
130*858ea5e5SAndroid Build Coastguard Worker }
131*858ea5e5SAndroid Build Coastguard Worker }
132*858ea5e5SAndroid Build Coastguard Worker
133*858ea5e5SAndroid Build Coastguard Worker get_prog_full_name(&info, prog_fd, prog_name, sizeof(prog_name));
134*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
135*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(json_wtr);
136*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(json_wtr, "id", info.id);
137*858ea5e5SAndroid Build Coastguard Worker if (attach_type_str)
138*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(json_wtr, "attach_type", attach_type_str);
139*858ea5e5SAndroid Build Coastguard Worker else
140*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(json_wtr, "attach_type", attach_type);
141*858ea5e5SAndroid Build Coastguard Worker if (!(query_flags & BPF_F_QUERY_EFFECTIVE))
142*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(json_wtr, "attach_flags", attach_flags_str);
143*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(json_wtr, "name", prog_name);
144*858ea5e5SAndroid Build Coastguard Worker if (attach_btf_name)
145*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(json_wtr, "attach_btf_name", attach_btf_name);
146*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(json_wtr, "attach_btf_obj_id", info.attach_btf_obj_id);
147*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(json_wtr, "attach_btf_id", info.attach_btf_id);
148*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_wtr);
149*858ea5e5SAndroid Build Coastguard Worker } else {
150*858ea5e5SAndroid Build Coastguard Worker printf("%s%-8u ", level ? " " : "", info.id);
151*858ea5e5SAndroid Build Coastguard Worker if (attach_type_str)
152*858ea5e5SAndroid Build Coastguard Worker printf("%-15s", attach_type_str);
153*858ea5e5SAndroid Build Coastguard Worker else
154*858ea5e5SAndroid Build Coastguard Worker printf("type %-10u", attach_type);
155*858ea5e5SAndroid Build Coastguard Worker if (query_flags & BPF_F_QUERY_EFFECTIVE)
156*858ea5e5SAndroid Build Coastguard Worker printf(" %-15s", prog_name);
157*858ea5e5SAndroid Build Coastguard Worker else
158*858ea5e5SAndroid Build Coastguard Worker printf(" %-15s %-15s", attach_flags_str, prog_name);
159*858ea5e5SAndroid Build Coastguard Worker if (attach_btf_name)
160*858ea5e5SAndroid Build Coastguard Worker printf(" %-15s", attach_btf_name);
161*858ea5e5SAndroid Build Coastguard Worker else if (info.attach_btf_id)
162*858ea5e5SAndroid Build Coastguard Worker printf(" attach_btf_obj_id=%d attach_btf_id=%d",
163*858ea5e5SAndroid Build Coastguard Worker info.attach_btf_obj_id, info.attach_btf_id);
164*858ea5e5SAndroid Build Coastguard Worker printf("\n");
165*858ea5e5SAndroid Build Coastguard Worker }
166*858ea5e5SAndroid Build Coastguard Worker
167*858ea5e5SAndroid Build Coastguard Worker close(prog_fd);
168*858ea5e5SAndroid Build Coastguard Worker return 0;
169*858ea5e5SAndroid Build Coastguard Worker }
170*858ea5e5SAndroid Build Coastguard Worker
count_attached_bpf_progs(int cgroup_fd,enum bpf_attach_type type)171*858ea5e5SAndroid Build Coastguard Worker static int count_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type)
172*858ea5e5SAndroid Build Coastguard Worker {
173*858ea5e5SAndroid Build Coastguard Worker __u32 prog_cnt = 0;
174*858ea5e5SAndroid Build Coastguard Worker int ret;
175*858ea5e5SAndroid Build Coastguard Worker
176*858ea5e5SAndroid Build Coastguard Worker ret = bpf_prog_query(cgroup_fd, type, query_flags, NULL,
177*858ea5e5SAndroid Build Coastguard Worker NULL, &prog_cnt);
178*858ea5e5SAndroid Build Coastguard Worker if (ret)
179*858ea5e5SAndroid Build Coastguard Worker return -1;
180*858ea5e5SAndroid Build Coastguard Worker
181*858ea5e5SAndroid Build Coastguard Worker return prog_cnt;
182*858ea5e5SAndroid Build Coastguard Worker }
183*858ea5e5SAndroid Build Coastguard Worker
cgroup_has_attached_progs(int cgroup_fd)184*858ea5e5SAndroid Build Coastguard Worker static int cgroup_has_attached_progs(int cgroup_fd)
185*858ea5e5SAndroid Build Coastguard Worker {
186*858ea5e5SAndroid Build Coastguard Worker enum bpf_attach_type type;
187*858ea5e5SAndroid Build Coastguard Worker bool no_prog = true;
188*858ea5e5SAndroid Build Coastguard Worker
189*858ea5e5SAndroid Build Coastguard Worker for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
190*858ea5e5SAndroid Build Coastguard Worker int count = count_attached_bpf_progs(cgroup_fd, type);
191*858ea5e5SAndroid Build Coastguard Worker
192*858ea5e5SAndroid Build Coastguard Worker if (count < 0 && errno != EINVAL)
193*858ea5e5SAndroid Build Coastguard Worker return -1;
194*858ea5e5SAndroid Build Coastguard Worker
195*858ea5e5SAndroid Build Coastguard Worker if (count > 0) {
196*858ea5e5SAndroid Build Coastguard Worker no_prog = false;
197*858ea5e5SAndroid Build Coastguard Worker break;
198*858ea5e5SAndroid Build Coastguard Worker }
199*858ea5e5SAndroid Build Coastguard Worker }
200*858ea5e5SAndroid Build Coastguard Worker
201*858ea5e5SAndroid Build Coastguard Worker return no_prog ? 0 : 1;
202*858ea5e5SAndroid Build Coastguard Worker }
203*858ea5e5SAndroid Build Coastguard Worker
show_effective_bpf_progs(int cgroup_fd,enum bpf_attach_type type,int level)204*858ea5e5SAndroid Build Coastguard Worker static int show_effective_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
205*858ea5e5SAndroid Build Coastguard Worker int level)
206*858ea5e5SAndroid Build Coastguard Worker {
207*858ea5e5SAndroid Build Coastguard Worker LIBBPF_OPTS(bpf_prog_query_opts, p);
208*858ea5e5SAndroid Build Coastguard Worker __u32 prog_ids[1024] = {0};
209*858ea5e5SAndroid Build Coastguard Worker __u32 iter;
210*858ea5e5SAndroid Build Coastguard Worker int ret;
211*858ea5e5SAndroid Build Coastguard Worker
212*858ea5e5SAndroid Build Coastguard Worker p.query_flags = query_flags;
213*858ea5e5SAndroid Build Coastguard Worker p.prog_cnt = ARRAY_SIZE(prog_ids);
214*858ea5e5SAndroid Build Coastguard Worker p.prog_ids = prog_ids;
215*858ea5e5SAndroid Build Coastguard Worker
216*858ea5e5SAndroid Build Coastguard Worker ret = bpf_prog_query_opts(cgroup_fd, type, &p);
217*858ea5e5SAndroid Build Coastguard Worker if (ret)
218*858ea5e5SAndroid Build Coastguard Worker return ret;
219*858ea5e5SAndroid Build Coastguard Worker
220*858ea5e5SAndroid Build Coastguard Worker if (p.prog_cnt == 0)
221*858ea5e5SAndroid Build Coastguard Worker return 0;
222*858ea5e5SAndroid Build Coastguard Worker
223*858ea5e5SAndroid Build Coastguard Worker for (iter = 0; iter < p.prog_cnt; iter++)
224*858ea5e5SAndroid Build Coastguard Worker show_bpf_prog(prog_ids[iter], type, NULL, level);
225*858ea5e5SAndroid Build Coastguard Worker
226*858ea5e5SAndroid Build Coastguard Worker return 0;
227*858ea5e5SAndroid Build Coastguard Worker }
228*858ea5e5SAndroid Build Coastguard Worker
show_attached_bpf_progs(int cgroup_fd,enum bpf_attach_type type,int level)229*858ea5e5SAndroid Build Coastguard Worker static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
230*858ea5e5SAndroid Build Coastguard Worker int level)
231*858ea5e5SAndroid Build Coastguard Worker {
232*858ea5e5SAndroid Build Coastguard Worker LIBBPF_OPTS(bpf_prog_query_opts, p);
233*858ea5e5SAndroid Build Coastguard Worker __u32 prog_attach_flags[1024] = {0};
234*858ea5e5SAndroid Build Coastguard Worker const char *attach_flags_str;
235*858ea5e5SAndroid Build Coastguard Worker __u32 prog_ids[1024] = {0};
236*858ea5e5SAndroid Build Coastguard Worker char buf[32];
237*858ea5e5SAndroid Build Coastguard Worker __u32 iter;
238*858ea5e5SAndroid Build Coastguard Worker int ret;
239*858ea5e5SAndroid Build Coastguard Worker
240*858ea5e5SAndroid Build Coastguard Worker p.query_flags = query_flags;
241*858ea5e5SAndroid Build Coastguard Worker p.prog_cnt = ARRAY_SIZE(prog_ids);
242*858ea5e5SAndroid Build Coastguard Worker p.prog_ids = prog_ids;
243*858ea5e5SAndroid Build Coastguard Worker p.prog_attach_flags = prog_attach_flags;
244*858ea5e5SAndroid Build Coastguard Worker
245*858ea5e5SAndroid Build Coastguard Worker ret = bpf_prog_query_opts(cgroup_fd, type, &p);
246*858ea5e5SAndroid Build Coastguard Worker if (ret)
247*858ea5e5SAndroid Build Coastguard Worker return ret;
248*858ea5e5SAndroid Build Coastguard Worker
249*858ea5e5SAndroid Build Coastguard Worker if (p.prog_cnt == 0)
250*858ea5e5SAndroid Build Coastguard Worker return 0;
251*858ea5e5SAndroid Build Coastguard Worker
252*858ea5e5SAndroid Build Coastguard Worker for (iter = 0; iter < p.prog_cnt; iter++) {
253*858ea5e5SAndroid Build Coastguard Worker __u32 attach_flags;
254*858ea5e5SAndroid Build Coastguard Worker
255*858ea5e5SAndroid Build Coastguard Worker attach_flags = prog_attach_flags[iter] ?: p.attach_flags;
256*858ea5e5SAndroid Build Coastguard Worker
257*858ea5e5SAndroid Build Coastguard Worker switch (attach_flags) {
258*858ea5e5SAndroid Build Coastguard Worker case BPF_F_ALLOW_MULTI:
259*858ea5e5SAndroid Build Coastguard Worker attach_flags_str = "multi";
260*858ea5e5SAndroid Build Coastguard Worker break;
261*858ea5e5SAndroid Build Coastguard Worker case BPF_F_ALLOW_OVERRIDE:
262*858ea5e5SAndroid Build Coastguard Worker attach_flags_str = "override";
263*858ea5e5SAndroid Build Coastguard Worker break;
264*858ea5e5SAndroid Build Coastguard Worker case 0:
265*858ea5e5SAndroid Build Coastguard Worker attach_flags_str = "";
266*858ea5e5SAndroid Build Coastguard Worker break;
267*858ea5e5SAndroid Build Coastguard Worker default:
268*858ea5e5SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "unknown(%x)", attach_flags);
269*858ea5e5SAndroid Build Coastguard Worker attach_flags_str = buf;
270*858ea5e5SAndroid Build Coastguard Worker }
271*858ea5e5SAndroid Build Coastguard Worker
272*858ea5e5SAndroid Build Coastguard Worker show_bpf_prog(prog_ids[iter], type,
273*858ea5e5SAndroid Build Coastguard Worker attach_flags_str, level);
274*858ea5e5SAndroid Build Coastguard Worker }
275*858ea5e5SAndroid Build Coastguard Worker
276*858ea5e5SAndroid Build Coastguard Worker return 0;
277*858ea5e5SAndroid Build Coastguard Worker }
278*858ea5e5SAndroid Build Coastguard Worker
show_bpf_progs(int cgroup_fd,enum bpf_attach_type type,int level)279*858ea5e5SAndroid Build Coastguard Worker static int show_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
280*858ea5e5SAndroid Build Coastguard Worker int level)
281*858ea5e5SAndroid Build Coastguard Worker {
282*858ea5e5SAndroid Build Coastguard Worker return query_flags & BPF_F_QUERY_EFFECTIVE ?
283*858ea5e5SAndroid Build Coastguard Worker show_effective_bpf_progs(cgroup_fd, type, level) :
284*858ea5e5SAndroid Build Coastguard Worker show_attached_bpf_progs(cgroup_fd, type, level);
285*858ea5e5SAndroid Build Coastguard Worker }
286*858ea5e5SAndroid Build Coastguard Worker
do_show(int argc,char ** argv)287*858ea5e5SAndroid Build Coastguard Worker static int do_show(int argc, char **argv)
288*858ea5e5SAndroid Build Coastguard Worker {
289*858ea5e5SAndroid Build Coastguard Worker enum bpf_attach_type type;
290*858ea5e5SAndroid Build Coastguard Worker int has_attached_progs;
291*858ea5e5SAndroid Build Coastguard Worker const char *path;
292*858ea5e5SAndroid Build Coastguard Worker int cgroup_fd;
293*858ea5e5SAndroid Build Coastguard Worker int ret = -1;
294*858ea5e5SAndroid Build Coastguard Worker
295*858ea5e5SAndroid Build Coastguard Worker query_flags = 0;
296*858ea5e5SAndroid Build Coastguard Worker
297*858ea5e5SAndroid Build Coastguard Worker if (!REQ_ARGS(1))
298*858ea5e5SAndroid Build Coastguard Worker return -1;
299*858ea5e5SAndroid Build Coastguard Worker path = GET_ARG();
300*858ea5e5SAndroid Build Coastguard Worker
301*858ea5e5SAndroid Build Coastguard Worker while (argc) {
302*858ea5e5SAndroid Build Coastguard Worker if (is_prefix(*argv, "effective")) {
303*858ea5e5SAndroid Build Coastguard Worker if (query_flags & BPF_F_QUERY_EFFECTIVE) {
304*858ea5e5SAndroid Build Coastguard Worker p_err("duplicated argument: %s", *argv);
305*858ea5e5SAndroid Build Coastguard Worker return -1;
306*858ea5e5SAndroid Build Coastguard Worker }
307*858ea5e5SAndroid Build Coastguard Worker query_flags |= BPF_F_QUERY_EFFECTIVE;
308*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
309*858ea5e5SAndroid Build Coastguard Worker } else {
310*858ea5e5SAndroid Build Coastguard Worker p_err("expected no more arguments, 'effective', got: '%s'?",
311*858ea5e5SAndroid Build Coastguard Worker *argv);
312*858ea5e5SAndroid Build Coastguard Worker return -1;
313*858ea5e5SAndroid Build Coastguard Worker }
314*858ea5e5SAndroid Build Coastguard Worker }
315*858ea5e5SAndroid Build Coastguard Worker
316*858ea5e5SAndroid Build Coastguard Worker cgroup_fd = open(path, O_RDONLY);
317*858ea5e5SAndroid Build Coastguard Worker if (cgroup_fd < 0) {
318*858ea5e5SAndroid Build Coastguard Worker p_err("can't open cgroup %s", path);
319*858ea5e5SAndroid Build Coastguard Worker goto exit;
320*858ea5e5SAndroid Build Coastguard Worker }
321*858ea5e5SAndroid Build Coastguard Worker
322*858ea5e5SAndroid Build Coastguard Worker has_attached_progs = cgroup_has_attached_progs(cgroup_fd);
323*858ea5e5SAndroid Build Coastguard Worker if (has_attached_progs < 0) {
324*858ea5e5SAndroid Build Coastguard Worker p_err("can't query bpf programs attached to %s: %s",
325*858ea5e5SAndroid Build Coastguard Worker path, strerror(errno));
326*858ea5e5SAndroid Build Coastguard Worker goto exit_cgroup;
327*858ea5e5SAndroid Build Coastguard Worker } else if (!has_attached_progs) {
328*858ea5e5SAndroid Build Coastguard Worker ret = 0;
329*858ea5e5SAndroid Build Coastguard Worker goto exit_cgroup;
330*858ea5e5SAndroid Build Coastguard Worker }
331*858ea5e5SAndroid Build Coastguard Worker
332*858ea5e5SAndroid Build Coastguard Worker if (json_output)
333*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(json_wtr);
334*858ea5e5SAndroid Build Coastguard Worker else if (query_flags & BPF_F_QUERY_EFFECTIVE)
335*858ea5e5SAndroid Build Coastguard Worker printf("%-8s %-15s %-15s\n", "ID", "AttachType", "Name");
336*858ea5e5SAndroid Build Coastguard Worker else
337*858ea5e5SAndroid Build Coastguard Worker printf("%-8s %-15s %-15s %-15s\n", "ID", "AttachType",
338*858ea5e5SAndroid Build Coastguard Worker "AttachFlags", "Name");
339*858ea5e5SAndroid Build Coastguard Worker
340*858ea5e5SAndroid Build Coastguard Worker btf_vmlinux = libbpf_find_kernel_btf();
341*858ea5e5SAndroid Build Coastguard Worker for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
342*858ea5e5SAndroid Build Coastguard Worker /*
343*858ea5e5SAndroid Build Coastguard Worker * Not all attach types may be supported, so it's expected,
344*858ea5e5SAndroid Build Coastguard Worker * that some requests will fail.
345*858ea5e5SAndroid Build Coastguard Worker * If we were able to get the show for at least one
346*858ea5e5SAndroid Build Coastguard Worker * attach type, let's return 0.
347*858ea5e5SAndroid Build Coastguard Worker */
348*858ea5e5SAndroid Build Coastguard Worker if (show_bpf_progs(cgroup_fd, type, 0) == 0)
349*858ea5e5SAndroid Build Coastguard Worker ret = 0;
350*858ea5e5SAndroid Build Coastguard Worker }
351*858ea5e5SAndroid Build Coastguard Worker
352*858ea5e5SAndroid Build Coastguard Worker if (json_output)
353*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(json_wtr);
354*858ea5e5SAndroid Build Coastguard Worker
355*858ea5e5SAndroid Build Coastguard Worker exit_cgroup:
356*858ea5e5SAndroid Build Coastguard Worker close(cgroup_fd);
357*858ea5e5SAndroid Build Coastguard Worker exit:
358*858ea5e5SAndroid Build Coastguard Worker return ret;
359*858ea5e5SAndroid Build Coastguard Worker }
360*858ea5e5SAndroid Build Coastguard Worker
361*858ea5e5SAndroid Build Coastguard Worker /*
362*858ea5e5SAndroid Build Coastguard Worker * To distinguish nftw() errors and do_show_tree_fn() errors
363*858ea5e5SAndroid Build Coastguard Worker * and avoid duplicating error messages, let's return -2
364*858ea5e5SAndroid Build Coastguard Worker * from do_show_tree_fn() in case of error.
365*858ea5e5SAndroid Build Coastguard Worker */
366*858ea5e5SAndroid Build Coastguard Worker #define NFTW_ERR -1
367*858ea5e5SAndroid Build Coastguard Worker #define SHOW_TREE_FN_ERR -2
do_show_tree_fn(const char * fpath,const struct stat * sb,int typeflag,struct FTW * ftw)368*858ea5e5SAndroid Build Coastguard Worker static int do_show_tree_fn(const char *fpath, const struct stat *sb,
369*858ea5e5SAndroid Build Coastguard Worker int typeflag, struct FTW *ftw)
370*858ea5e5SAndroid Build Coastguard Worker {
371*858ea5e5SAndroid Build Coastguard Worker enum bpf_attach_type type;
372*858ea5e5SAndroid Build Coastguard Worker int has_attached_progs;
373*858ea5e5SAndroid Build Coastguard Worker int cgroup_fd;
374*858ea5e5SAndroid Build Coastguard Worker
375*858ea5e5SAndroid Build Coastguard Worker if (typeflag != FTW_D)
376*858ea5e5SAndroid Build Coastguard Worker return 0;
377*858ea5e5SAndroid Build Coastguard Worker
378*858ea5e5SAndroid Build Coastguard Worker cgroup_fd = open(fpath, O_RDONLY);
379*858ea5e5SAndroid Build Coastguard Worker if (cgroup_fd < 0) {
380*858ea5e5SAndroid Build Coastguard Worker p_err("can't open cgroup %s: %s", fpath, strerror(errno));
381*858ea5e5SAndroid Build Coastguard Worker return SHOW_TREE_FN_ERR;
382*858ea5e5SAndroid Build Coastguard Worker }
383*858ea5e5SAndroid Build Coastguard Worker
384*858ea5e5SAndroid Build Coastguard Worker has_attached_progs = cgroup_has_attached_progs(cgroup_fd);
385*858ea5e5SAndroid Build Coastguard Worker if (has_attached_progs < 0) {
386*858ea5e5SAndroid Build Coastguard Worker p_err("can't query bpf programs attached to %s: %s",
387*858ea5e5SAndroid Build Coastguard Worker fpath, strerror(errno));
388*858ea5e5SAndroid Build Coastguard Worker close(cgroup_fd);
389*858ea5e5SAndroid Build Coastguard Worker return SHOW_TREE_FN_ERR;
390*858ea5e5SAndroid Build Coastguard Worker } else if (!has_attached_progs) {
391*858ea5e5SAndroid Build Coastguard Worker close(cgroup_fd);
392*858ea5e5SAndroid Build Coastguard Worker return 0;
393*858ea5e5SAndroid Build Coastguard Worker }
394*858ea5e5SAndroid Build Coastguard Worker
395*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
396*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(json_wtr);
397*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(json_wtr, "cgroup", fpath);
398*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "programs");
399*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(json_wtr);
400*858ea5e5SAndroid Build Coastguard Worker } else {
401*858ea5e5SAndroid Build Coastguard Worker printf("%s\n", fpath);
402*858ea5e5SAndroid Build Coastguard Worker }
403*858ea5e5SAndroid Build Coastguard Worker
404*858ea5e5SAndroid Build Coastguard Worker btf_vmlinux = libbpf_find_kernel_btf();
405*858ea5e5SAndroid Build Coastguard Worker for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++)
406*858ea5e5SAndroid Build Coastguard Worker show_bpf_progs(cgroup_fd, type, ftw->level);
407*858ea5e5SAndroid Build Coastguard Worker
408*858ea5e5SAndroid Build Coastguard Worker if (errno == EINVAL)
409*858ea5e5SAndroid Build Coastguard Worker /* Last attach type does not support query.
410*858ea5e5SAndroid Build Coastguard Worker * Do not report an error for this, especially because batch
411*858ea5e5SAndroid Build Coastguard Worker * mode would stop processing commands.
412*858ea5e5SAndroid Build Coastguard Worker */
413*858ea5e5SAndroid Build Coastguard Worker errno = 0;
414*858ea5e5SAndroid Build Coastguard Worker
415*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
416*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(json_wtr);
417*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_wtr);
418*858ea5e5SAndroid Build Coastguard Worker }
419*858ea5e5SAndroid Build Coastguard Worker
420*858ea5e5SAndroid Build Coastguard Worker close(cgroup_fd);
421*858ea5e5SAndroid Build Coastguard Worker
422*858ea5e5SAndroid Build Coastguard Worker return 0;
423*858ea5e5SAndroid Build Coastguard Worker }
424*858ea5e5SAndroid Build Coastguard Worker
find_cgroup_root(void)425*858ea5e5SAndroid Build Coastguard Worker static char *find_cgroup_root(void)
426*858ea5e5SAndroid Build Coastguard Worker {
427*858ea5e5SAndroid Build Coastguard Worker struct mntent *mnt;
428*858ea5e5SAndroid Build Coastguard Worker FILE *f;
429*858ea5e5SAndroid Build Coastguard Worker
430*858ea5e5SAndroid Build Coastguard Worker f = fopen("/proc/mounts", "r");
431*858ea5e5SAndroid Build Coastguard Worker if (f == NULL)
432*858ea5e5SAndroid Build Coastguard Worker return NULL;
433*858ea5e5SAndroid Build Coastguard Worker
434*858ea5e5SAndroid Build Coastguard Worker while ((mnt = getmntent(f))) {
435*858ea5e5SAndroid Build Coastguard Worker if (strcmp(mnt->mnt_type, "cgroup2") == 0) {
436*858ea5e5SAndroid Build Coastguard Worker fclose(f);
437*858ea5e5SAndroid Build Coastguard Worker return strdup(mnt->mnt_dir);
438*858ea5e5SAndroid Build Coastguard Worker }
439*858ea5e5SAndroid Build Coastguard Worker }
440*858ea5e5SAndroid Build Coastguard Worker
441*858ea5e5SAndroid Build Coastguard Worker fclose(f);
442*858ea5e5SAndroid Build Coastguard Worker return NULL;
443*858ea5e5SAndroid Build Coastguard Worker }
444*858ea5e5SAndroid Build Coastguard Worker
do_show_tree(int argc,char ** argv)445*858ea5e5SAndroid Build Coastguard Worker static int do_show_tree(int argc, char **argv)
446*858ea5e5SAndroid Build Coastguard Worker {
447*858ea5e5SAndroid Build Coastguard Worker char *cgroup_root, *cgroup_alloced = NULL;
448*858ea5e5SAndroid Build Coastguard Worker int ret;
449*858ea5e5SAndroid Build Coastguard Worker
450*858ea5e5SAndroid Build Coastguard Worker query_flags = 0;
451*858ea5e5SAndroid Build Coastguard Worker
452*858ea5e5SAndroid Build Coastguard Worker if (!argc) {
453*858ea5e5SAndroid Build Coastguard Worker cgroup_alloced = find_cgroup_root();
454*858ea5e5SAndroid Build Coastguard Worker if (!cgroup_alloced) {
455*858ea5e5SAndroid Build Coastguard Worker p_err("cgroup v2 isn't mounted");
456*858ea5e5SAndroid Build Coastguard Worker return -1;
457*858ea5e5SAndroid Build Coastguard Worker }
458*858ea5e5SAndroid Build Coastguard Worker cgroup_root = cgroup_alloced;
459*858ea5e5SAndroid Build Coastguard Worker } else {
460*858ea5e5SAndroid Build Coastguard Worker cgroup_root = GET_ARG();
461*858ea5e5SAndroid Build Coastguard Worker
462*858ea5e5SAndroid Build Coastguard Worker while (argc) {
463*858ea5e5SAndroid Build Coastguard Worker if (is_prefix(*argv, "effective")) {
464*858ea5e5SAndroid Build Coastguard Worker if (query_flags & BPF_F_QUERY_EFFECTIVE) {
465*858ea5e5SAndroid Build Coastguard Worker p_err("duplicated argument: %s", *argv);
466*858ea5e5SAndroid Build Coastguard Worker return -1;
467*858ea5e5SAndroid Build Coastguard Worker }
468*858ea5e5SAndroid Build Coastguard Worker query_flags |= BPF_F_QUERY_EFFECTIVE;
469*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
470*858ea5e5SAndroid Build Coastguard Worker } else {
471*858ea5e5SAndroid Build Coastguard Worker p_err("expected no more arguments, 'effective', got: '%s'?",
472*858ea5e5SAndroid Build Coastguard Worker *argv);
473*858ea5e5SAndroid Build Coastguard Worker return -1;
474*858ea5e5SAndroid Build Coastguard Worker }
475*858ea5e5SAndroid Build Coastguard Worker }
476*858ea5e5SAndroid Build Coastguard Worker }
477*858ea5e5SAndroid Build Coastguard Worker
478*858ea5e5SAndroid Build Coastguard Worker if (json_output)
479*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(json_wtr);
480*858ea5e5SAndroid Build Coastguard Worker else if (query_flags & BPF_F_QUERY_EFFECTIVE)
481*858ea5e5SAndroid Build Coastguard Worker printf("%s\n"
482*858ea5e5SAndroid Build Coastguard Worker "%-8s %-15s %-15s\n",
483*858ea5e5SAndroid Build Coastguard Worker "CgroupPath",
484*858ea5e5SAndroid Build Coastguard Worker "ID", "AttachType", "Name");
485*858ea5e5SAndroid Build Coastguard Worker else
486*858ea5e5SAndroid Build Coastguard Worker printf("%s\n"
487*858ea5e5SAndroid Build Coastguard Worker "%-8s %-15s %-15s %-15s\n",
488*858ea5e5SAndroid Build Coastguard Worker "CgroupPath",
489*858ea5e5SAndroid Build Coastguard Worker "ID", "AttachType", "AttachFlags", "Name");
490*858ea5e5SAndroid Build Coastguard Worker
491*858ea5e5SAndroid Build Coastguard Worker switch (nftw(cgroup_root, do_show_tree_fn, 1024, FTW_MOUNT)) {
492*858ea5e5SAndroid Build Coastguard Worker case NFTW_ERR:
493*858ea5e5SAndroid Build Coastguard Worker p_err("can't iterate over %s: %s", cgroup_root,
494*858ea5e5SAndroid Build Coastguard Worker strerror(errno));
495*858ea5e5SAndroid Build Coastguard Worker ret = -1;
496*858ea5e5SAndroid Build Coastguard Worker break;
497*858ea5e5SAndroid Build Coastguard Worker case SHOW_TREE_FN_ERR:
498*858ea5e5SAndroid Build Coastguard Worker ret = -1;
499*858ea5e5SAndroid Build Coastguard Worker break;
500*858ea5e5SAndroid Build Coastguard Worker default:
501*858ea5e5SAndroid Build Coastguard Worker ret = 0;
502*858ea5e5SAndroid Build Coastguard Worker }
503*858ea5e5SAndroid Build Coastguard Worker
504*858ea5e5SAndroid Build Coastguard Worker if (json_output)
505*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(json_wtr);
506*858ea5e5SAndroid Build Coastguard Worker
507*858ea5e5SAndroid Build Coastguard Worker free(cgroup_alloced);
508*858ea5e5SAndroid Build Coastguard Worker
509*858ea5e5SAndroid Build Coastguard Worker return ret;
510*858ea5e5SAndroid Build Coastguard Worker }
511*858ea5e5SAndroid Build Coastguard Worker
do_attach(int argc,char ** argv)512*858ea5e5SAndroid Build Coastguard Worker static int do_attach(int argc, char **argv)
513*858ea5e5SAndroid Build Coastguard Worker {
514*858ea5e5SAndroid Build Coastguard Worker enum bpf_attach_type attach_type;
515*858ea5e5SAndroid Build Coastguard Worker int cgroup_fd, prog_fd;
516*858ea5e5SAndroid Build Coastguard Worker int attach_flags = 0;
517*858ea5e5SAndroid Build Coastguard Worker int ret = -1;
518*858ea5e5SAndroid Build Coastguard Worker int i;
519*858ea5e5SAndroid Build Coastguard Worker
520*858ea5e5SAndroid Build Coastguard Worker if (argc < 4) {
521*858ea5e5SAndroid Build Coastguard Worker p_err("too few parameters for cgroup attach");
522*858ea5e5SAndroid Build Coastguard Worker goto exit;
523*858ea5e5SAndroid Build Coastguard Worker }
524*858ea5e5SAndroid Build Coastguard Worker
525*858ea5e5SAndroid Build Coastguard Worker cgroup_fd = open(argv[0], O_RDONLY);
526*858ea5e5SAndroid Build Coastguard Worker if (cgroup_fd < 0) {
527*858ea5e5SAndroid Build Coastguard Worker p_err("can't open cgroup %s", argv[0]);
528*858ea5e5SAndroid Build Coastguard Worker goto exit;
529*858ea5e5SAndroid Build Coastguard Worker }
530*858ea5e5SAndroid Build Coastguard Worker
531*858ea5e5SAndroid Build Coastguard Worker attach_type = parse_attach_type(argv[1]);
532*858ea5e5SAndroid Build Coastguard Worker if (attach_type == __MAX_BPF_ATTACH_TYPE) {
533*858ea5e5SAndroid Build Coastguard Worker p_err("invalid attach type");
534*858ea5e5SAndroid Build Coastguard Worker goto exit_cgroup;
535*858ea5e5SAndroid Build Coastguard Worker }
536*858ea5e5SAndroid Build Coastguard Worker
537*858ea5e5SAndroid Build Coastguard Worker argc -= 2;
538*858ea5e5SAndroid Build Coastguard Worker argv = &argv[2];
539*858ea5e5SAndroid Build Coastguard Worker prog_fd = prog_parse_fd(&argc, &argv);
540*858ea5e5SAndroid Build Coastguard Worker if (prog_fd < 0)
541*858ea5e5SAndroid Build Coastguard Worker goto exit_cgroup;
542*858ea5e5SAndroid Build Coastguard Worker
543*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < argc; i++) {
544*858ea5e5SAndroid Build Coastguard Worker if (is_prefix(argv[i], "multi")) {
545*858ea5e5SAndroid Build Coastguard Worker attach_flags |= BPF_F_ALLOW_MULTI;
546*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(argv[i], "override")) {
547*858ea5e5SAndroid Build Coastguard Worker attach_flags |= BPF_F_ALLOW_OVERRIDE;
548*858ea5e5SAndroid Build Coastguard Worker } else {
549*858ea5e5SAndroid Build Coastguard Worker p_err("unknown option: %s", argv[i]);
550*858ea5e5SAndroid Build Coastguard Worker goto exit_cgroup;
551*858ea5e5SAndroid Build Coastguard Worker }
552*858ea5e5SAndroid Build Coastguard Worker }
553*858ea5e5SAndroid Build Coastguard Worker
554*858ea5e5SAndroid Build Coastguard Worker if (bpf_prog_attach(prog_fd, cgroup_fd, attach_type, attach_flags)) {
555*858ea5e5SAndroid Build Coastguard Worker p_err("failed to attach program");
556*858ea5e5SAndroid Build Coastguard Worker goto exit_prog;
557*858ea5e5SAndroid Build Coastguard Worker }
558*858ea5e5SAndroid Build Coastguard Worker
559*858ea5e5SAndroid Build Coastguard Worker if (json_output)
560*858ea5e5SAndroid Build Coastguard Worker jsonw_null(json_wtr);
561*858ea5e5SAndroid Build Coastguard Worker
562*858ea5e5SAndroid Build Coastguard Worker ret = 0;
563*858ea5e5SAndroid Build Coastguard Worker
564*858ea5e5SAndroid Build Coastguard Worker exit_prog:
565*858ea5e5SAndroid Build Coastguard Worker close(prog_fd);
566*858ea5e5SAndroid Build Coastguard Worker exit_cgroup:
567*858ea5e5SAndroid Build Coastguard Worker close(cgroup_fd);
568*858ea5e5SAndroid Build Coastguard Worker exit:
569*858ea5e5SAndroid Build Coastguard Worker return ret;
570*858ea5e5SAndroid Build Coastguard Worker }
571*858ea5e5SAndroid Build Coastguard Worker
do_detach(int argc,char ** argv)572*858ea5e5SAndroid Build Coastguard Worker static int do_detach(int argc, char **argv)
573*858ea5e5SAndroid Build Coastguard Worker {
574*858ea5e5SAndroid Build Coastguard Worker enum bpf_attach_type attach_type;
575*858ea5e5SAndroid Build Coastguard Worker int prog_fd, cgroup_fd;
576*858ea5e5SAndroid Build Coastguard Worker int ret = -1;
577*858ea5e5SAndroid Build Coastguard Worker
578*858ea5e5SAndroid Build Coastguard Worker if (argc < 4) {
579*858ea5e5SAndroid Build Coastguard Worker p_err("too few parameters for cgroup detach");
580*858ea5e5SAndroid Build Coastguard Worker goto exit;
581*858ea5e5SAndroid Build Coastguard Worker }
582*858ea5e5SAndroid Build Coastguard Worker
583*858ea5e5SAndroid Build Coastguard Worker cgroup_fd = open(argv[0], O_RDONLY);
584*858ea5e5SAndroid Build Coastguard Worker if (cgroup_fd < 0) {
585*858ea5e5SAndroid Build Coastguard Worker p_err("can't open cgroup %s", argv[0]);
586*858ea5e5SAndroid Build Coastguard Worker goto exit;
587*858ea5e5SAndroid Build Coastguard Worker }
588*858ea5e5SAndroid Build Coastguard Worker
589*858ea5e5SAndroid Build Coastguard Worker attach_type = parse_attach_type(argv[1]);
590*858ea5e5SAndroid Build Coastguard Worker if (attach_type == __MAX_BPF_ATTACH_TYPE) {
591*858ea5e5SAndroid Build Coastguard Worker p_err("invalid attach type");
592*858ea5e5SAndroid Build Coastguard Worker goto exit_cgroup;
593*858ea5e5SAndroid Build Coastguard Worker }
594*858ea5e5SAndroid Build Coastguard Worker
595*858ea5e5SAndroid Build Coastguard Worker argc -= 2;
596*858ea5e5SAndroid Build Coastguard Worker argv = &argv[2];
597*858ea5e5SAndroid Build Coastguard Worker prog_fd = prog_parse_fd(&argc, &argv);
598*858ea5e5SAndroid Build Coastguard Worker if (prog_fd < 0)
599*858ea5e5SAndroid Build Coastguard Worker goto exit_cgroup;
600*858ea5e5SAndroid Build Coastguard Worker
601*858ea5e5SAndroid Build Coastguard Worker if (bpf_prog_detach2(prog_fd, cgroup_fd, attach_type)) {
602*858ea5e5SAndroid Build Coastguard Worker p_err("failed to detach program");
603*858ea5e5SAndroid Build Coastguard Worker goto exit_prog;
604*858ea5e5SAndroid Build Coastguard Worker }
605*858ea5e5SAndroid Build Coastguard Worker
606*858ea5e5SAndroid Build Coastguard Worker if (json_output)
607*858ea5e5SAndroid Build Coastguard Worker jsonw_null(json_wtr);
608*858ea5e5SAndroid Build Coastguard Worker
609*858ea5e5SAndroid Build Coastguard Worker ret = 0;
610*858ea5e5SAndroid Build Coastguard Worker
611*858ea5e5SAndroid Build Coastguard Worker exit_prog:
612*858ea5e5SAndroid Build Coastguard Worker close(prog_fd);
613*858ea5e5SAndroid Build Coastguard Worker exit_cgroup:
614*858ea5e5SAndroid Build Coastguard Worker close(cgroup_fd);
615*858ea5e5SAndroid Build Coastguard Worker exit:
616*858ea5e5SAndroid Build Coastguard Worker return ret;
617*858ea5e5SAndroid Build Coastguard Worker }
618*858ea5e5SAndroid Build Coastguard Worker
do_help(int argc,char ** argv)619*858ea5e5SAndroid Build Coastguard Worker static int do_help(int argc, char **argv)
620*858ea5e5SAndroid Build Coastguard Worker {
621*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
622*858ea5e5SAndroid Build Coastguard Worker jsonw_null(json_wtr);
623*858ea5e5SAndroid Build Coastguard Worker return 0;
624*858ea5e5SAndroid Build Coastguard Worker }
625*858ea5e5SAndroid Build Coastguard Worker
626*858ea5e5SAndroid Build Coastguard Worker fprintf(stderr,
627*858ea5e5SAndroid Build Coastguard Worker "Usage: %1$s %2$s { show | list } CGROUP [**effective**]\n"
628*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s tree [CGROUP_ROOT] [**effective**]\n"
629*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s attach CGROUP ATTACH_TYPE PROG [ATTACH_FLAGS]\n"
630*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s detach CGROUP ATTACH_TYPE PROG\n"
631*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s help\n"
632*858ea5e5SAndroid Build Coastguard Worker "\n"
633*858ea5e5SAndroid Build Coastguard Worker HELP_SPEC_ATTACH_TYPES "\n"
634*858ea5e5SAndroid Build Coastguard Worker " " HELP_SPEC_ATTACH_FLAGS "\n"
635*858ea5e5SAndroid Build Coastguard Worker " " HELP_SPEC_PROGRAM "\n"
636*858ea5e5SAndroid Build Coastguard Worker " " HELP_SPEC_OPTIONS " |\n"
637*858ea5e5SAndroid Build Coastguard Worker " {-f|--bpffs} }\n"
638*858ea5e5SAndroid Build Coastguard Worker "",
639*858ea5e5SAndroid Build Coastguard Worker bin_name, argv[-2]);
640*858ea5e5SAndroid Build Coastguard Worker
641*858ea5e5SAndroid Build Coastguard Worker return 0;
642*858ea5e5SAndroid Build Coastguard Worker }
643*858ea5e5SAndroid Build Coastguard Worker
644*858ea5e5SAndroid Build Coastguard Worker static const struct cmd cmds[] = {
645*858ea5e5SAndroid Build Coastguard Worker { "show", do_show },
646*858ea5e5SAndroid Build Coastguard Worker { "list", do_show },
647*858ea5e5SAndroid Build Coastguard Worker { "tree", do_show_tree },
648*858ea5e5SAndroid Build Coastguard Worker { "attach", do_attach },
649*858ea5e5SAndroid Build Coastguard Worker { "detach", do_detach },
650*858ea5e5SAndroid Build Coastguard Worker { "help", do_help },
651*858ea5e5SAndroid Build Coastguard Worker { 0 }
652*858ea5e5SAndroid Build Coastguard Worker };
653*858ea5e5SAndroid Build Coastguard Worker
do_cgroup(int argc,char ** argv)654*858ea5e5SAndroid Build Coastguard Worker int do_cgroup(int argc, char **argv)
655*858ea5e5SAndroid Build Coastguard Worker {
656*858ea5e5SAndroid Build Coastguard Worker return cmd_select(cmds, argc, argv, do_help);
657*858ea5e5SAndroid Build Coastguard Worker }
658