Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) // Copyright (C) 2017 Facebook
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) // Author: Roman Gushchin <guro@fb.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #define _XOPEN_SOURCE 500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <ftw.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <mntent.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <bpf/bpf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "main.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define HELP_SPEC_ATTACH_FLAGS						\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	"ATTACH_FLAGS := { multi | override }"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define HELP_SPEC_ATTACH_TYPES						       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	"       ATTACH_TYPE := { ingress | egress | sock_create |\n"	       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	"                        sock_ops | device | bind4 | bind6 |\n"	       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	"                        post_bind4 | post_bind6 | connect4 |\n"       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	"                        connect6 | getpeername4 | getpeername6 |\n"   \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	"                        getsockname4 | getsockname6 | sendmsg4 |\n"   \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	"                        sendmsg6 | recvmsg4 | recvmsg6 |\n"           \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	"                        sysctl | getsockopt | setsockopt |\n"	       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	"                        sock_release }"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) static unsigned int query_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) static enum bpf_attach_type parse_attach_type(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	enum bpf_attach_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		if (attach_type_name[type] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		    is_prefix(str, attach_type_name[type]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 			return type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	return __MAX_BPF_ATTACH_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) static int show_bpf_prog(int id, enum bpf_attach_type attach_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 			 const char *attach_flags_str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 			 int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	struct bpf_prog_info info = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	__u32 info_len = sizeof(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	int prog_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	prog_fd = bpf_prog_get_fd_by_id(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	if (prog_fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	if (bpf_obj_get_info_by_fd(prog_fd, &info, &info_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		close(prog_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	if (json_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		jsonw_start_object(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		jsonw_uint_field(json_wtr, "id", info.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		if (attach_type < ARRAY_SIZE(attach_type_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 			jsonw_string_field(json_wtr, "attach_type",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 					   attach_type_name[attach_type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 			jsonw_uint_field(json_wtr, "attach_type", attach_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		jsonw_string_field(json_wtr, "attach_flags",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 				   attach_flags_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		jsonw_string_field(json_wtr, "name", info.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		jsonw_end_object(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		printf("%s%-8u ", level ? "    " : "", info.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		if (attach_type < ARRAY_SIZE(attach_type_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 			printf("%-15s", attach_type_name[attach_type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 			printf("type %-10u", attach_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		printf(" %-15s %-15s\n", attach_flags_str, info.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	close(prog_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) static int count_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	__u32 prog_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	ret = bpf_prog_query(cgroup_fd, type, query_flags, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 			     NULL, &prog_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	return prog_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static int cgroup_has_attached_progs(int cgroup_fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	enum bpf_attach_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	bool no_prog = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		int count = count_attached_bpf_progs(cgroup_fd, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		if (count < 0 && errno != EINVAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		if (count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 			no_prog = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	return no_prog ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 				   int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	const char *attach_flags_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	__u32 prog_ids[1024] = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	__u32 prog_cnt, iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	__u32 attach_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	char buf[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	prog_cnt = ARRAY_SIZE(prog_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	ret = bpf_prog_query(cgroup_fd, type, query_flags, &attach_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 			     prog_ids, &prog_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	if (prog_cnt == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	switch (attach_flags) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	case BPF_F_ALLOW_MULTI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		attach_flags_str = "multi";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	case BPF_F_ALLOW_OVERRIDE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		attach_flags_str = "override";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		attach_flags_str = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		snprintf(buf, sizeof(buf), "unknown(%x)", attach_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		attach_flags_str = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	for (iter = 0; iter < prog_cnt; iter++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		show_bpf_prog(prog_ids[iter], type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			      attach_flags_str, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static int do_show(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	enum bpf_attach_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	int has_attached_progs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	const char *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	int cgroup_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	int ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	query_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	if (!REQ_ARGS(1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	path = GET_ARG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	while (argc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		if (is_prefix(*argv, "effective")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 			if (query_flags & BPF_F_QUERY_EFFECTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 				p_err("duplicated argument: %s", *argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 			query_flags |= BPF_F_QUERY_EFFECTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 			NEXT_ARG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 			p_err("expected no more arguments, 'effective', got: '%s'?",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 			      *argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	cgroup_fd = open(path, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	if (cgroup_fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		p_err("can't open cgroup %s", path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	has_attached_progs = cgroup_has_attached_progs(cgroup_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	if (has_attached_progs < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		p_err("can't query bpf programs attached to %s: %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		      path, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		goto exit_cgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	} else if (!has_attached_progs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		goto exit_cgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	if (json_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		jsonw_start_array(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		printf("%-8s %-15s %-15s %-15s\n", "ID", "AttachType",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		       "AttachFlags", "Name");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		 * Not all attach types may be supported, so it's expected,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		 * that some requests will fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		 * If we were able to get the show for at least one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		 * attach type, let's return 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		if (show_attached_bpf_progs(cgroup_fd, type, 0) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 			ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	if (json_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		jsonw_end_array(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) exit_cgroup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	close(cgroup_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)  * To distinguish nftw() errors and do_show_tree_fn() errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)  * and avoid duplicating error messages, let's return -2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)  * from do_show_tree_fn() in case of error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #define NFTW_ERR		-1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) #define SHOW_TREE_FN_ERR	-2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static int do_show_tree_fn(const char *fpath, const struct stat *sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 			   int typeflag, struct FTW *ftw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	enum bpf_attach_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	int has_attached_progs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	int cgroup_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	if (typeflag != FTW_D)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	cgroup_fd = open(fpath, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	if (cgroup_fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		p_err("can't open cgroup %s: %s", fpath, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		return SHOW_TREE_FN_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	has_attached_progs = cgroup_has_attached_progs(cgroup_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	if (has_attached_progs < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		p_err("can't query bpf programs attached to %s: %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		      fpath, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		close(cgroup_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		return SHOW_TREE_FN_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	} else if (!has_attached_progs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		close(cgroup_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	if (json_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		jsonw_start_object(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		jsonw_string_field(json_wtr, "cgroup", fpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		jsonw_name(json_wtr, "programs");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		jsonw_start_array(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		printf("%s\n", fpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		show_attached_bpf_progs(cgroup_fd, type, ftw->level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	if (errno == EINVAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		/* Last attach type does not support query.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		 * Do not report an error for this, especially because batch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		 * mode would stop processing commands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		errno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	if (json_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		jsonw_end_array(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		jsonw_end_object(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	close(cgroup_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static char *find_cgroup_root(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	struct mntent *mnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	FILE *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	f = fopen("/proc/mounts", "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	if (f == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	while ((mnt = getmntent(f))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		if (strcmp(mnt->mnt_type, "cgroup2") == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 			fclose(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 			return strdup(mnt->mnt_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	fclose(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static int do_show_tree(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	char *cgroup_root, *cgroup_alloced = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	query_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	if (!argc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		cgroup_alloced = find_cgroup_root();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 		if (!cgroup_alloced) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 			p_err("cgroup v2 isn't mounted");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		cgroup_root = cgroup_alloced;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		cgroup_root = GET_ARG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		while (argc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 			if (is_prefix(*argv, "effective")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 				if (query_flags & BPF_F_QUERY_EFFECTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 					p_err("duplicated argument: %s", *argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 					return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 				query_flags |= BPF_F_QUERY_EFFECTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 				NEXT_ARG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 				p_err("expected no more arguments, 'effective', got: '%s'?",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 				      *argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	if (json_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		jsonw_start_array(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		printf("%s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		       "%-8s %-15s %-15s %-15s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		       "CgroupPath",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		       "ID", "AttachType", "AttachFlags", "Name");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	switch (nftw(cgroup_root, do_show_tree_fn, 1024, FTW_MOUNT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	case NFTW_ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		p_err("can't iterate over %s: %s", cgroup_root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		      strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	case SHOW_TREE_FN_ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	if (json_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 		jsonw_end_array(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	free(cgroup_alloced);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static int do_attach(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	enum bpf_attach_type attach_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	int cgroup_fd, prog_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	int attach_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	int ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	if (argc < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		p_err("too few parameters for cgroup attach");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	cgroup_fd = open(argv[0], O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	if (cgroup_fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 		p_err("can't open cgroup %s", argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	attach_type = parse_attach_type(argv[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	if (attach_type == __MAX_BPF_ATTACH_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 		p_err("invalid attach type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		goto exit_cgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	argc -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	argv = &argv[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	prog_fd = prog_parse_fd(&argc, &argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	if (prog_fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 		goto exit_cgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	for (i = 0; i < argc; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		if (is_prefix(argv[i], "multi")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 			attach_flags |= BPF_F_ALLOW_MULTI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		} else if (is_prefix(argv[i], "override")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 			attach_flags |= BPF_F_ALLOW_OVERRIDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 			p_err("unknown option: %s", argv[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 			goto exit_cgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	if (bpf_prog_attach(prog_fd, cgroup_fd, attach_type, attach_flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 		p_err("failed to attach program");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 		goto exit_prog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	if (json_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 		jsonw_null(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) exit_prog:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	close(prog_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) exit_cgroup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	close(cgroup_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) static int do_detach(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	enum bpf_attach_type attach_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	int prog_fd, cgroup_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	int ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	if (argc < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 		p_err("too few parameters for cgroup detach");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	cgroup_fd = open(argv[0], O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	if (cgroup_fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		p_err("can't open cgroup %s", argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	attach_type = parse_attach_type(argv[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	if (attach_type == __MAX_BPF_ATTACH_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		p_err("invalid attach type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 		goto exit_cgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	argc -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	argv = &argv[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	prog_fd = prog_parse_fd(&argc, &argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	if (prog_fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		goto exit_cgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	if (bpf_prog_detach2(prog_fd, cgroup_fd, attach_type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		p_err("failed to detach program");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		goto exit_prog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	if (json_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 		jsonw_null(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) exit_prog:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	close(prog_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) exit_cgroup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	close(cgroup_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) static int do_help(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	if (json_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		jsonw_null(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	fprintf(stderr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		"Usage: %1$s %2$s { show | list } CGROUP [**effective**]\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		"       %1$s %2$s tree [CGROUP_ROOT] [**effective**]\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		"       %1$s %2$s attach CGROUP ATTACH_TYPE PROG [ATTACH_FLAGS]\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 		"       %1$s %2$s detach CGROUP ATTACH_TYPE PROG\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		"       %1$s %2$s help\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		HELP_SPEC_ATTACH_TYPES "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 		"       " HELP_SPEC_ATTACH_FLAGS "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		"       " HELP_SPEC_PROGRAM "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		"       " HELP_SPEC_OPTIONS "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		"",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 		bin_name, argv[-2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static const struct cmd cmds[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	{ "show",	do_show },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	{ "list",	do_show },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	{ "tree",       do_show_tree },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	{ "attach",	do_attach },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	{ "detach",	do_detach },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	{ "help",	do_help },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	{ 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) int do_cgroup(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	return cmd_select(cmds, argc, argv, do_help);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }