Skip to content

Commit 4153b89

Browse files
author
Alexei Starovoitov
committed
Merge branch 'refactor-check_func_arg'
Lorenz Bauer says: ==================== Changes in v4: - Output the desired type on BTF ID mismatch (Martin) Changes in v3: - Fix BTF_ID_LIST_SINGLE if BTF is disabled (Martin) - Drop incorrect arg_btf_id in bpf_sk_storage.c (Martin) - Check for arg_btf_id in check_func_proto (Martin) - Drop incorrect PTR_TO_BTF_ID from fullsock_types (Martin) - Introduce btf_seq_file_ids in bpf_trace.c to reduce duplication Changes in v2: - Make the series stand alone (Martin) - Drop incorrect BTF_SET_START fix (Andrii) - Only support a single BTF ID per argument (Martin) - Introduce BTF_ID_LIST_SINGLE macro (Andrii) - Skip check_ctx_reg iff register is NULL - Change output of check_reg_type slightly, to avoid touching tests Original cover letter: Currently, check_func_arg has this pretty gnarly if statement that compares the valid arg_type with the actualy reg_type. Sprinkled in-between are checks for register_is_null, to short circuit these tests if we're dealing with a nullable arg_type. There is also some code for later bounds / access checking hidden away in there. This series of patches refactors the function into something like this: if (reg_is_null && arg_type_is_nullable) skip type checking do type checking, including BTF validation do bounds / access checking The type checking is now table driven, which makes it easy to extend the acceptable types. Maybe more importantly, using a table makes it easy to provide more helpful verifier output (see the last patch). ==================== Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2 parents 31f23a6 + f79e7ea commit 4153b89

File tree

11 files changed

+239
-237
lines changed

11 files changed

+239
-237
lines changed

include/linux/bpf.h

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ enum bpf_arg_type {
292292
ARG_PTR_TO_ALLOC_MEM, /* pointer to dynamically allocated memory */
293293
ARG_PTR_TO_ALLOC_MEM_OR_NULL, /* pointer to dynamically allocated memory or NULL */
294294
ARG_CONST_ALLOC_SIZE_OR_ZERO, /* number of allocated bytes requested */
295+
__BPF_ARG_TYPE_MAX,
295296
};
296297

297298
/* type of values returned from helper functions */
@@ -326,12 +327,16 @@ struct bpf_func_proto {
326327
};
327328
enum bpf_arg_type arg_type[5];
328329
};
329-
int *btf_id; /* BTF ids of arguments */
330-
bool (*check_btf_id)(u32 btf_id, u32 arg); /* if the argument btf_id is
331-
* valid. Often used if more
332-
* than one btf id is permitted
333-
* for this argument.
334-
*/
330+
union {
331+
struct {
332+
u32 *arg1_btf_id;
333+
u32 *arg2_btf_id;
334+
u32 *arg3_btf_id;
335+
u32 *arg4_btf_id;
336+
u32 *arg5_btf_id;
337+
};
338+
u32 *arg_btf_id[5];
339+
};
335340
int *ret_btf_id; /* return value btf_id */
336341
bool (*allowed)(const struct bpf_prog *prog);
337342
};
@@ -1385,8 +1390,6 @@ int btf_struct_access(struct bpf_verifier_log *log,
13851390
u32 *next_btf_id);
13861391
bool btf_struct_ids_match(struct bpf_verifier_log *log,
13871392
int off, u32 id, u32 need_type_id);
1388-
int btf_resolve_helper_id(struct bpf_verifier_log *log,
1389-
const struct bpf_func_proto *fn, int);
13901393

13911394
int btf_distill_func_proto(struct bpf_verifier_log *log,
13921395
struct btf *btf,
@@ -1905,6 +1908,6 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
19051908
void *addr1, void *addr2);
19061909

19071910
struct btf_id_set;
1908-
bool btf_id_set_contains(struct btf_id_set *set, u32 id);
1911+
bool btf_id_set_contains(const struct btf_id_set *set, u32 id);
19091912

19101913
#endif /* _LINUX_BPF_H */

include/linux/btf_ids.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ extern u32 name[];
7676
#define BTF_ID_LIST_GLOBAL(name) \
7777
__BTF_ID_LIST(name, globl)
7878

79+
/* The BTF_ID_LIST_SINGLE macro defines a BTF_ID_LIST with
80+
* a single entry.
81+
*/
82+
#define BTF_ID_LIST_SINGLE(name, prefix, typename) \
83+
BTF_ID_LIST(name) \
84+
BTF_ID(prefix, typename)
85+
7986
/*
8087
* The BTF_ID_UNUSED macro defines 4 zero bytes.
8188
* It's used when we want to define 'unused' entry
@@ -140,6 +147,7 @@ extern struct btf_id_set name;
140147
#define BTF_ID(prefix, name)
141148
#define BTF_ID_UNUSED
142149
#define BTF_ID_LIST_GLOBAL(name) u32 name[1];
150+
#define BTF_ID_LIST_SINGLE(name, prefix, typename) static u32 name[1];
143151
#define BTF_SET_START(name) static struct btf_id_set name = { 0 };
144152
#define BTF_SET_START_GLOBAL(name) static struct btf_id_set name = { 0 };
145153
#define BTF_SET_END(name)

kernel/bpf/bpf_inode_storage.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,19 +249,17 @@ const struct bpf_map_ops inode_storage_map_ops = {
249249
.map_owner_storage_ptr = inode_storage_ptr,
250250
};
251251

252-
BTF_ID_LIST(bpf_inode_storage_btf_ids)
253-
BTF_ID_UNUSED
254-
BTF_ID(struct, inode)
252+
BTF_ID_LIST_SINGLE(bpf_inode_storage_btf_ids, struct, inode)
255253

256254
const struct bpf_func_proto bpf_inode_storage_get_proto = {
257255
.func = bpf_inode_storage_get,
258256
.gpl_only = false,
259257
.ret_type = RET_PTR_TO_MAP_VALUE_OR_NULL,
260258
.arg1_type = ARG_CONST_MAP_PTR,
261259
.arg2_type = ARG_PTR_TO_BTF_ID,
260+
.arg2_btf_id = &bpf_inode_storage_btf_ids[0],
262261
.arg3_type = ARG_PTR_TO_MAP_VALUE_OR_NULL,
263262
.arg4_type = ARG_ANYTHING,
264-
.btf_id = bpf_inode_storage_btf_ids,
265263
};
266264

267265
const struct bpf_func_proto bpf_inode_storage_delete_proto = {
@@ -270,5 +268,5 @@ const struct bpf_func_proto bpf_inode_storage_delete_proto = {
270268
.ret_type = RET_INTEGER,
271269
.arg1_type = ARG_CONST_MAP_PTR,
272270
.arg2_type = ARG_PTR_TO_BTF_ID,
273-
.btf_id = bpf_inode_storage_btf_ids,
271+
.arg2_btf_id = &bpf_inode_storage_btf_ids[0],
274272
};

kernel/bpf/btf.c

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4193,19 +4193,6 @@ bool btf_struct_ids_match(struct bpf_verifier_log *log,
41934193
return true;
41944194
}
41954195

4196-
int btf_resolve_helper_id(struct bpf_verifier_log *log,
4197-
const struct bpf_func_proto *fn, int arg)
4198-
{
4199-
int id;
4200-
4201-
if (fn->arg_type[arg] != ARG_PTR_TO_BTF_ID || !btf_vmlinux)
4202-
return -EINVAL;
4203-
id = fn->btf_id[arg];
4204-
if (!id || id > btf_vmlinux->nr_types)
4205-
return -EINVAL;
4206-
return id;
4207-
}
4208-
42094196
static int __get_type_size(struct btf *btf, u32 btf_id,
42104197
const struct btf_type **bad_type)
42114198
{
@@ -4772,7 +4759,7 @@ static int btf_id_cmp_func(const void *a, const void *b)
47724759
return *pa - *pb;
47734760
}
47744761

4775-
bool btf_id_set_contains(struct btf_id_set *set, u32 id)
4762+
bool btf_id_set_contains(const struct btf_id_set *set, u32 id)
47764763
{
47774764
return bsearch(&id, set->ids, set->cnt, sizeof(u32), btf_id_cmp_func) != NULL;
47784765
}

kernel/bpf/stackmap.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -665,18 +665,17 @@ BPF_CALL_4(bpf_get_task_stack, struct task_struct *, task, void *, buf,
665665
return __bpf_get_stack(regs, task, NULL, buf, size, flags);
666666
}
667667

668-
BTF_ID_LIST(bpf_get_task_stack_btf_ids)
669-
BTF_ID(struct, task_struct)
668+
BTF_ID_LIST_SINGLE(bpf_get_task_stack_btf_ids, struct, task_struct)
670669

671670
const struct bpf_func_proto bpf_get_task_stack_proto = {
672671
.func = bpf_get_task_stack,
673672
.gpl_only = false,
674673
.ret_type = RET_INTEGER,
675674
.arg1_type = ARG_PTR_TO_BTF_ID,
675+
.arg1_btf_id = &bpf_get_task_stack_btf_ids[0],
676676
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
677677
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
678678
.arg4_type = ARG_ANYTHING,
679-
.btf_id = bpf_get_task_stack_btf_ids,
680679
};
681680

682681
BPF_CALL_4(bpf_get_stack_pe, struct bpf_perf_event_data_kern *, ctx,

0 commit comments

Comments
 (0)