Skip to content

Commit d703256

Browse files
author
Martin KaFai Lau
committed
Merge branch 'Fix wrong cgroup attach flags being assigned to effective progs'
Pu Lehui says: ==================== From: Pu Lehui <pulehui@huawei.com> 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 For cg1, obviously, the attach flags of prog6 and prog13 can not be OVERRIDE. And for query with EFFECTIVE flags, exporting attach flags does not make sense. So let's remove the AttachFlags field and the associated logic. After these patches, 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 v5: - Adapt selftests for effective query uapi change. v4: https://lore.kernel.org/bpf/20220920154233.1494352-1-pulehui@huaweicloud.com - Reject prog_attach_flags array when effective query. (Martin) - Target to bpf tree. (Martin) v3: https://lore.kernel.org/bpf/20220914161742.3180731-1-pulehui@huaweicloud.com - Don't show attach flags when effective query. (John, sdf, Martin) v2: https://lore.kernel.org/bpf/20220908145304.3436139-1-pulehui@huaweicloud.com - Limit prog_cnt to avoid overflow. (John) - Add more detail message. v1: https://lore.kernel.org/bpf/20220820120234.2121044-1-pulehui@huawei.com ==================== Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
2 parents 83c10cc + d2aa993 commit d703256

File tree

5 files changed

+81
-26
lines changed

5 files changed

+81
-26
lines changed

include/uapi/linux/bpf.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,7 +1233,7 @@ enum {
12331233

12341234
/* Query effective (directly attached + inherited from ancestor cgroups)
12351235
* programs that will be executed for events within a cgroup.
1236-
* attach_flags with this flag are returned only for directly attached programs.
1236+
* attach_flags with this flag are always returned 0.
12371237
*/
12381238
#define BPF_F_QUERY_EFFECTIVE (1U << 0)
12391239

@@ -1432,7 +1432,10 @@ union bpf_attr {
14321432
__u32 attach_flags;
14331433
__aligned_u64 prog_ids;
14341434
__u32 prog_cnt;
1435-
__aligned_u64 prog_attach_flags; /* output: per-program attach_flags */
1435+
/* output: per-program attach_flags.
1436+
* not allowed to be set during effective query.
1437+
*/
1438+
__aligned_u64 prog_attach_flags;
14361439
} query;
14371440

14381441
struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */

kernel/bpf/cgroup.c

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,7 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
10201020
union bpf_attr __user *uattr)
10211021
{
10221022
__u32 __user *prog_attach_flags = u64_to_user_ptr(attr->query.prog_attach_flags);
1023+
bool effective_query = attr->query.query_flags & BPF_F_QUERY_EFFECTIVE;
10231024
__u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids);
10241025
enum bpf_attach_type type = attr->query.attach_type;
10251026
enum cgroup_bpf_attach_type from_atype, to_atype;
@@ -1029,8 +1030,12 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
10291030
int total_cnt = 0;
10301031
u32 flags;
10311032

1033+
if (effective_query && prog_attach_flags)
1034+
return -EINVAL;
1035+
10321036
if (type == BPF_LSM_CGROUP) {
1033-
if (attr->query.prog_cnt && prog_ids && !prog_attach_flags)
1037+
if (!effective_query && attr->query.prog_cnt &&
1038+
prog_ids && !prog_attach_flags)
10341039
return -EINVAL;
10351040

10361041
from_atype = CGROUP_LSM_START;
@@ -1045,7 +1050,7 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
10451050
}
10461051

10471052
for (atype = from_atype; atype <= to_atype; atype++) {
1048-
if (attr->query.query_flags & BPF_F_QUERY_EFFECTIVE) {
1053+
if (effective_query) {
10491054
effective = rcu_dereference_protected(cgrp->bpf.effective[atype],
10501055
lockdep_is_held(&cgroup_mutex));
10511056
total_cnt += bpf_prog_array_length(effective);
@@ -1054,6 +1059,8 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
10541059
}
10551060
}
10561061

1062+
/* always output uattr->query.attach_flags as 0 during effective query */
1063+
flags = effective_query ? 0 : flags;
10571064
if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)))
10581065
return -EFAULT;
10591066
if (copy_to_user(&uattr->query.prog_cnt, &total_cnt, sizeof(total_cnt)))
@@ -1068,7 +1075,7 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
10681075
}
10691076

10701077
for (atype = from_atype; atype <= to_atype && total_cnt; atype++) {
1071-
if (attr->query.query_flags & BPF_F_QUERY_EFFECTIVE) {
1078+
if (effective_query) {
10721079
effective = rcu_dereference_protected(cgrp->bpf.effective[atype],
10731080
lockdep_is_held(&cgroup_mutex));
10741081
cnt = min_t(int, bpf_prog_array_length(effective), total_cnt);
@@ -1090,15 +1097,16 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
10901097
if (++i == cnt)
10911098
break;
10921099
}
1093-
}
10941100

1095-
if (prog_attach_flags) {
1096-
flags = cgrp->bpf.flags[atype];
1101+
if (prog_attach_flags) {
1102+
flags = cgrp->bpf.flags[atype];
10971103

1098-
for (i = 0; i < cnt; i++)
1099-
if (copy_to_user(prog_attach_flags + i, &flags, sizeof(flags)))
1100-
return -EFAULT;
1101-
prog_attach_flags += cnt;
1104+
for (i = 0; i < cnt; i++)
1105+
if (copy_to_user(prog_attach_flags + i,
1106+
&flags, sizeof(flags)))
1107+
return -EFAULT;
1108+
prog_attach_flags += cnt;
1109+
}
11021110
}
11031111

11041112
prog_ids += cnt;

tools/bpf/bpftool/cgroup.c

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ static int show_bpf_prog(int id, enum bpf_attach_type attach_type,
136136
jsonw_string_field(json_wtr, "attach_type", attach_type_str);
137137
else
138138
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);
141141
jsonw_string_field(json_wtr, "name", prog_name);
142142
if (attach_btf_name)
143143
jsonw_string_field(json_wtr, "attach_btf_name", attach_btf_name);
@@ -150,7 +150,10 @@ static int show_bpf_prog(int id, enum bpf_attach_type attach_type,
150150
printf("%-15s", attach_type_str);
151151
else
152152
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);
154157
if (attach_btf_name)
155158
printf(" %-15s", attach_btf_name);
156159
else if (info.attach_btf_id)
@@ -195,6 +198,32 @@ static int cgroup_has_attached_progs(int cgroup_fd)
195198

196199
return no_prog ? 0 : 1;
197200
}
201+
202+
static int show_effective_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
203+
int level)
204+
{
205+
LIBBPF_OPTS(bpf_prog_query_opts, p);
206+
__u32 prog_ids[1024] = {0};
207+
__u32 iter;
208+
int ret;
209+
210+
p.query_flags = query_flags;
211+
p.prog_cnt = ARRAY_SIZE(prog_ids);
212+
p.prog_ids = prog_ids;
213+
214+
ret = bpf_prog_query_opts(cgroup_fd, type, &p);
215+
if (ret)
216+
return ret;
217+
218+
if (p.prog_cnt == 0)
219+
return 0;
220+
221+
for (iter = 0; iter < p.prog_cnt; iter++)
222+
show_bpf_prog(prog_ids[iter], type, NULL, level);
223+
224+
return 0;
225+
}
226+
198227
static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
199228
int level)
200229
{
@@ -245,6 +274,14 @@ static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
245274
return 0;
246275
}
247276

277+
static int show_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
278+
int level)
279+
{
280+
return query_flags & BPF_F_QUERY_EFFECTIVE ?
281+
show_effective_bpf_progs(cgroup_fd, type, level) :
282+
show_attached_bpf_progs(cgroup_fd, type, level);
283+
}
284+
248285
static int do_show(int argc, char **argv)
249286
{
250287
enum bpf_attach_type type;
@@ -292,6 +329,8 @@ static int do_show(int argc, char **argv)
292329

293330
if (json_output)
294331
jsonw_start_array(json_wtr);
332+
else if (query_flags & BPF_F_QUERY_EFFECTIVE)
333+
printf("%-8s %-15s %-15s\n", "ID", "AttachType", "Name");
295334
else
296335
printf("%-8s %-15s %-15s %-15s\n", "ID", "AttachType",
297336
"AttachFlags", "Name");
@@ -304,7 +343,7 @@ static int do_show(int argc, char **argv)
304343
* If we were able to get the show for at least one
305344
* attach type, let's return 0.
306345
*/
307-
if (show_attached_bpf_progs(cgroup_fd, type, 0) == 0)
346+
if (show_bpf_progs(cgroup_fd, type, 0) == 0)
308347
ret = 0;
309348
}
310349

@@ -362,7 +401,7 @@ static int do_show_tree_fn(const char *fpath, const struct stat *sb,
362401

363402
btf_vmlinux = libbpf_find_kernel_btf();
364403
for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++)
365-
show_attached_bpf_progs(cgroup_fd, type, ftw->level);
404+
show_bpf_progs(cgroup_fd, type, ftw->level);
366405

367406
if (errno == EINVAL)
368407
/* Last attach type does not support query.
@@ -436,6 +475,11 @@ static int do_show_tree(int argc, char **argv)
436475

437476
if (json_output)
438477
jsonw_start_array(json_wtr);
478+
else if (query_flags & BPF_F_QUERY_EFFECTIVE)
479+
printf("%s\n"
480+
"%-8s %-15s %-15s\n",
481+
"CgroupPath",
482+
"ID", "AttachType", "Name");
439483
else
440484
printf("%s\n"
441485
"%-8s %-15s %-15s %-15s\n",

tools/include/uapi/linux/bpf.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,7 +1233,7 @@ enum {
12331233

12341234
/* Query effective (directly attached + inherited from ancestor cgroups)
12351235
* programs that will be executed for events within a cgroup.
1236-
* attach_flags with this flag are returned only for directly attached programs.
1236+
* attach_flags with this flag are always returned 0.
12371237
*/
12381238
#define BPF_F_QUERY_EFFECTIVE (1U << 0)
12391239

@@ -1432,7 +1432,10 @@ union bpf_attr {
14321432
__u32 attach_flags;
14331433
__aligned_u64 prog_ids;
14341434
__u32 prog_cnt;
1435-
__aligned_u64 prog_attach_flags; /* output: per-program attach_flags */
1435+
/* output: per-program attach_flags.
1436+
* not allowed to be set during effective query.
1437+
*/
1438+
__aligned_u64 prog_attach_flags;
14361439
} query;
14371440

14381441
struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */

tools/testing/selftests/bpf/prog_tests/cgroup_link.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,9 @@ void serial_test_cgroup_link(void)
7171

7272
ping_and_check(cg_nr, 0);
7373

74-
/* query the number of effective progs and attach flags in root cg */
74+
/* query the number of attached progs and attach flags in root cg */
7575
err = bpf_prog_query(cgs[0].fd, BPF_CGROUP_INET_EGRESS,
76-
BPF_F_QUERY_EFFECTIVE, &attach_flags, NULL,
77-
&prog_cnt);
76+
0, &attach_flags, NULL, &prog_cnt);
7877
CHECK_FAIL(err);
7978
CHECK_FAIL(attach_flags != BPF_F_ALLOW_MULTI);
8079
if (CHECK(prog_cnt != 1, "effect_cnt", "exp %d, got %d\n", 1, prog_cnt))
@@ -85,17 +84,15 @@ void serial_test_cgroup_link(void)
8584
BPF_F_QUERY_EFFECTIVE, NULL, NULL,
8685
&prog_cnt);
8786
CHECK_FAIL(err);
88-
CHECK_FAIL(attach_flags != BPF_F_ALLOW_MULTI);
8987
if (CHECK(prog_cnt != cg_nr, "effect_cnt", "exp %d, got %d\n",
9088
cg_nr, prog_cnt))
9189
goto cleanup;
9290

9391
/* query the effective prog IDs in last cg */
9492
err = bpf_prog_query(cgs[last_cg].fd, BPF_CGROUP_INET_EGRESS,
95-
BPF_F_QUERY_EFFECTIVE, &attach_flags,
96-
prog_ids, &prog_cnt);
93+
BPF_F_QUERY_EFFECTIVE, NULL, prog_ids,
94+
&prog_cnt);
9795
CHECK_FAIL(err);
98-
CHECK_FAIL(attach_flags != BPF_F_ALLOW_MULTI);
9996
if (CHECK(prog_cnt != cg_nr, "effect_cnt", "exp %d, got %d\n",
10097
cg_nr, prog_cnt))
10198
goto cleanup;

0 commit comments

Comments
 (0)