xref: /aosp_15_r20/external/bpftool/src/cgroup.c (revision 858ea5e570667251cdc31d3fe7b846b591105938)
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