Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpftool: Fix wrong cgroup attach flags being assigned to effective progs

When root-cgroup attach multi progs and sub-cgroup attach a override prog,
bpftool will display incorrectly for the attach flags of the sub-cgroup’s
effective progs:

$ bpftool cgroup tree /sys/fs/cgroup effective
CgroupPath
ID AttachType AttachFlags Name
/sys/fs/cgroup
6 cgroup_sysctl multi sysctl_tcp_mem
13 cgroup_sysctl multi sysctl_tcp_mem
/sys/fs/cgroup/cg1
20 cgroup_sysctl override sysctl_tcp_mem
6 cgroup_sysctl override sysctl_tcp_mem <- wrong
13 cgroup_sysctl override sysctl_tcp_mem <- wrong
/sys/fs/cgroup/cg1/cg2
20 cgroup_sysctl sysctl_tcp_mem
6 cgroup_sysctl sysctl_tcp_mem
13 cgroup_sysctl sysctl_tcp_mem

Attach flags is only valid for attached progs of this layer cgroup,
but not for effective progs. For querying with EFFECTIVE flags,
exporting attach flags does not make sense. So let's remove the
AttachFlags field and the associated logic. After this patch, the
above effective cgroup tree will show as bellow:

$ bpftool cgroup tree /sys/fs/cgroup effective
CgroupPath
ID AttachType Name
/sys/fs/cgroup
6 cgroup_sysctl sysctl_tcp_mem
13 cgroup_sysctl sysctl_tcp_mem
/sys/fs/cgroup/cg1
20 cgroup_sysctl sysctl_tcp_mem
6 cgroup_sysctl sysctl_tcp_mem
13 cgroup_sysctl sysctl_tcp_mem
/sys/fs/cgroup/cg1/cg2
20 cgroup_sysctl sysctl_tcp_mem
6 cgroup_sysctl sysctl_tcp_mem
13 cgroup_sysctl sysctl_tcp_mem

Fixes: b79c9fc9551b ("bpf: implement BPF_PROG_QUERY for BPF_LSM_CGROUP")
Fixes: a98bf57391a2 ("tools: bpftool: add support for reporting the effective cgroup progs")
Signed-off-by: Pu Lehui <pulehui@huawei.com>
Link: https://lore.kernel.org/r/20220921104604.2340580-3-pulehui@huaweicloud.com
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>

authored by

Pu Lehui and committed by
Martin KaFai Lau
bdcee1b0 0e426a3a

+49 -5
+49 -5
tools/bpf/bpftool/cgroup.c
··· 136 136 jsonw_string_field(json_wtr, "attach_type", attach_type_str); 137 137 else 138 138 jsonw_uint_field(json_wtr, "attach_type", attach_type); 139 - jsonw_string_field(json_wtr, "attach_flags", 140 - attach_flags_str); 139 + if (!(query_flags & BPF_F_QUERY_EFFECTIVE)) 140 + jsonw_string_field(json_wtr, "attach_flags", attach_flags_str); 141 141 jsonw_string_field(json_wtr, "name", prog_name); 142 142 if (attach_btf_name) 143 143 jsonw_string_field(json_wtr, "attach_btf_name", attach_btf_name); ··· 150 150 printf("%-15s", attach_type_str); 151 151 else 152 152 printf("type %-10u", attach_type); 153 - printf(" %-15s %-15s", attach_flags_str, prog_name); 153 + if (query_flags & BPF_F_QUERY_EFFECTIVE) 154 + printf(" %-15s", prog_name); 155 + else 156 + printf(" %-15s %-15s", attach_flags_str, prog_name); 154 157 if (attach_btf_name) 155 158 printf(" %-15s", attach_btf_name); 156 159 else if (info.attach_btf_id) ··· 198 195 199 196 return no_prog ? 0 : 1; 200 197 } 198 + 199 + static int show_effective_bpf_progs(int cgroup_fd, enum bpf_attach_type type, 200 + int level) 201 + { 202 + LIBBPF_OPTS(bpf_prog_query_opts, p); 203 + __u32 prog_ids[1024] = {0}; 204 + __u32 iter; 205 + int ret; 206 + 207 + p.query_flags = query_flags; 208 + p.prog_cnt = ARRAY_SIZE(prog_ids); 209 + p.prog_ids = prog_ids; 210 + 211 + ret = bpf_prog_query_opts(cgroup_fd, type, &p); 212 + if (ret) 213 + return ret; 214 + 215 + if (p.prog_cnt == 0) 216 + return 0; 217 + 218 + for (iter = 0; iter < p.prog_cnt; iter++) 219 + show_bpf_prog(prog_ids[iter], type, NULL, level); 220 + 221 + return 0; 222 + } 223 + 201 224 static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type, 202 225 int level) 203 226 { ··· 274 245 return 0; 275 246 } 276 247 248 + static int show_bpf_progs(int cgroup_fd, enum bpf_attach_type type, 249 + int level) 250 + { 251 + return query_flags & BPF_F_QUERY_EFFECTIVE ? 252 + show_effective_bpf_progs(cgroup_fd, type, level) : 253 + show_attached_bpf_progs(cgroup_fd, type, level); 254 + } 255 + 277 256 static int do_show(int argc, char **argv) 278 257 { 279 258 enum bpf_attach_type type; ··· 329 292 330 293 if (json_output) 331 294 jsonw_start_array(json_wtr); 295 + else if (query_flags & BPF_F_QUERY_EFFECTIVE) 296 + printf("%-8s %-15s %-15s\n", "ID", "AttachType", "Name"); 332 297 else 333 298 printf("%-8s %-15s %-15s %-15s\n", "ID", "AttachType", 334 299 "AttachFlags", "Name"); ··· 343 304 * If we were able to get the show for at least one 344 305 * attach type, let's return 0. 345 306 */ 346 - if (show_attached_bpf_progs(cgroup_fd, type, 0) == 0) 307 + if (show_bpf_progs(cgroup_fd, type, 0) == 0) 347 308 ret = 0; 348 309 } 349 310 ··· 401 362 402 363 btf_vmlinux = libbpf_find_kernel_btf(); 403 364 for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) 404 - show_attached_bpf_progs(cgroup_fd, type, ftw->level); 365 + show_bpf_progs(cgroup_fd, type, ftw->level); 405 366 406 367 if (errno == EINVAL) 407 368 /* Last attach type does not support query. ··· 475 436 476 437 if (json_output) 477 438 jsonw_start_array(json_wtr); 439 + else if (query_flags & BPF_F_QUERY_EFFECTIVE) 440 + printf("%s\n" 441 + "%-8s %-15s %-15s\n", 442 + "CgroupPath", 443 + "ID", "AttachType", "Name"); 478 444 else 479 445 printf("%s\n" 480 446 "%-8s %-15s %-15s %-15s\n",