Skip to content

Commit e42ac14

Browse files
Martin KaFai Lauanakryiko
authored andcommitted
bpf: Check unsupported ops from the bpf_struct_ops's cfi_stubs
The bpf_tcp_ca struct_ops currently uses a "u32 unsupported_ops[]" array to track which ops is not supported. After cfi_stubs had been added, the function pointer in cfi_stubs is also NULL for the unsupported ops. Thus, the "u32 unsupported_ops[]" becomes redundant. This observation was originally brought up in the bpf/cfi discussion: https://lore.kernel.org/bpf/CAADnVQJoEkdjyCEJRPASjBw1QGsKYrF33QdMGc1RZa9b88bAEA@mail.gmail.com/ The recent bpf qdisc patch (https://lore.kernel.org/bpf/[email protected]/) also needs to specify quite many unsupported ops. It is a good time to clean it up. This patch removes the need of "u32 unsupported_ops[]" and tests for null-ness in the cfi_stubs instead. Testing the cfi_stubs is done in a new function bpf_struct_ops_supported(). The verifier will call bpf_struct_ops_supported() when loading the struct_ops program. The ".check_member" is removed from the bpf_tcp_ca in this patch. ".check_member" could still be useful for other subsytems to enforce other restrictions (e.g. sched_ext checks for prog->sleepable). To keep the same error return, ENOTSUPP is used. Cc: Amery Hung <[email protected]> Signed-off-by: Martin KaFai Lau <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]>
1 parent 0d7c061 commit e42ac14

File tree

4 files changed

+21
-27
lines changed

4 files changed

+21
-27
lines changed

include/linux/bpf.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1795,6 +1795,7 @@ struct bpf_struct_ops_common_value {
17951795
#define BPF_MODULE_OWNER ((void *)((0xeB9FUL << 2) + POISON_POINTER_DELTA))
17961796
bool bpf_struct_ops_get(const void *kdata);
17971797
void bpf_struct_ops_put(const void *kdata);
1798+
int bpf_struct_ops_supported(const struct bpf_struct_ops *st_ops, u32 moff);
17981799
int bpf_struct_ops_map_sys_lookup_elem(struct bpf_map *map, void *key,
17991800
void *value);
18001801
int bpf_struct_ops_prepare_trampoline(struct bpf_tramp_links *tlinks,
@@ -1851,6 +1852,10 @@ static inline void bpf_module_put(const void *data, struct module *owner)
18511852
{
18521853
module_put(owner);
18531854
}
1855+
static inline int bpf_struct_ops_supported(const struct bpf_struct_ops *st_ops, u32 moff)
1856+
{
1857+
return -ENOTSUPP;
1858+
}
18541859
static inline int bpf_struct_ops_map_sys_lookup_elem(struct bpf_map *map,
18551860
void *key,
18561861
void *value)

kernel/bpf/bpf_struct_ops.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,13 @@ void bpf_struct_ops_put(const void *kdata)
10401040
bpf_map_put(&st_map->map);
10411041
}
10421042

1043+
int bpf_struct_ops_supported(const struct bpf_struct_ops *st_ops, u32 moff)
1044+
{
1045+
void *func_ptr = *(void **)(st_ops->cfi_stubs + moff);
1046+
1047+
return func_ptr ? 0 : -ENOTSUPP;
1048+
}
1049+
10431050
static bool bpf_struct_ops_valid_to_reg(struct bpf_map *map)
10441051
{
10451052
struct bpf_struct_ops_map *st_map = (struct bpf_struct_ops_map *)map;

kernel/bpf/verifier.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21132,6 +21132,7 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env)
2113221132
u32 btf_id, member_idx;
2113321133
struct btf *btf;
2113421134
const char *mname;
21135+
int err;
2113521136

2113621137
if (!prog->gpl_compatible) {
2113721138
verbose(env, "struct ops programs must have a GPL compatible license\n");
@@ -21179,8 +21180,15 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env)
2117921180
return -EINVAL;
2118021181
}
2118121182

21183+
err = bpf_struct_ops_supported(st_ops, __btf_member_bit_offset(t, member) / 8);
21184+
if (err) {
21185+
verbose(env, "attach to unsupported member %s of struct %s\n",
21186+
mname, st_ops->name);
21187+
return err;
21188+
}
21189+
2118221190
if (st_ops->check_member) {
21183-
int err = st_ops->check_member(t, member, prog);
21191+
err = st_ops->check_member(t, member, prog);
2118421192

2118521193
if (err) {
2118621194
verbose(env, "attach to unsupported member %s of struct %s\n",

net/ipv4/bpf_tcp_ca.c

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@
1414
/* "extern" is to avoid sparse warning. It is only used in bpf_struct_ops.c. */
1515
static struct bpf_struct_ops bpf_tcp_congestion_ops;
1616

17-
static u32 unsupported_ops[] = {
18-
offsetof(struct tcp_congestion_ops, get_info),
19-
};
20-
2117
static const struct btf_type *tcp_sock_type;
2218
static u32 tcp_sock_id, sock_id;
2319
static const struct btf_type *tcp_congestion_ops_type;
@@ -45,18 +41,6 @@ static int bpf_tcp_ca_init(struct btf *btf)
4541
return 0;
4642
}
4743

48-
static bool is_unsupported(u32 member_offset)
49-
{
50-
unsigned int i;
51-
52-
for (i = 0; i < ARRAY_SIZE(unsupported_ops); i++) {
53-
if (member_offset == unsupported_ops[i])
54-
return true;
55-
}
56-
57-
return false;
58-
}
59-
6044
static bool bpf_tcp_ca_is_valid_access(int off, int size,
6145
enum bpf_access_type type,
6246
const struct bpf_prog *prog,
@@ -251,15 +235,6 @@ static int bpf_tcp_ca_init_member(const struct btf_type *t,
251235
return 0;
252236
}
253237

254-
static int bpf_tcp_ca_check_member(const struct btf_type *t,
255-
const struct btf_member *member,
256-
const struct bpf_prog *prog)
257-
{
258-
if (is_unsupported(__btf_member_bit_offset(t, member) / 8))
259-
return -ENOTSUPP;
260-
return 0;
261-
}
262-
263238
static int bpf_tcp_ca_reg(void *kdata, struct bpf_link *link)
264239
{
265240
return tcp_register_congestion_control(kdata);
@@ -354,7 +329,6 @@ static struct bpf_struct_ops bpf_tcp_congestion_ops = {
354329
.reg = bpf_tcp_ca_reg,
355330
.unreg = bpf_tcp_ca_unreg,
356331
.update = bpf_tcp_ca_update,
357-
.check_member = bpf_tcp_ca_check_member,
358332
.init_member = bpf_tcp_ca_init_member,
359333
.init = bpf_tcp_ca_init,
360334
.validate = bpf_tcp_ca_validate,

0 commit comments

Comments
 (0)