Skip to content

Commit c839a50

Browse files
Philo LuKernel Patches Daemon
authored andcommitted
bpf: Support __nullable argument suffix for tp_btf
Pointers passed to tp_btf were trusted to be valid, but some tracepoints do take NULL pointer as input, such as trace_tcp_send_reset(). Then the invalid memory access cannot be detected by verifier. This patch fix it by add a suffix "__nullable" to the unreliable argument. The suffix is shown in btf, and PTR_MAYBE_NULL will be added to nullable arguments. Then users must check the pointer before use it. A problem here is that we use "btf_trace_##call" to search func_proto. As it is a typedef, argument names as well as the suffix are not recorded. To solve this, I use bpf_raw_event_map to find "__bpf_trace##template" from "btf_trace_##call", and then we can see the suffix. Suggested-by: Alexei Starovoitov <[email protected]> Signed-off-by: Philo Lu <[email protected]>
1 parent b79aafe commit c839a50

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

kernel/bpf/btf.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6385,6 +6385,12 @@ static bool prog_args_trusted(const struct bpf_prog *prog)
63856385
}
63866386
}
63876387

6388+
static bool prog_arg_maybe_null(const struct bpf_prog *prog, const struct btf *btf,
6389+
const struct btf_param *arg)
6390+
{
6391+
return btf_param_match_suffix(btf, arg, "__nullable");
6392+
}
6393+
63886394
int btf_ctx_arg_offset(const struct btf *btf, const struct btf_type *func_proto,
63896395
u32 arg_no)
63906396
{
@@ -6554,6 +6560,9 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
65546560
if (prog_args_trusted(prog))
65556561
info->reg_type |= PTR_TRUSTED;
65566562

6563+
if (prog_arg_maybe_null(prog, btf, &args[arg]))
6564+
info->reg_type |= PTR_MAYBE_NULL;
6565+
65576566
if (tgt_prog) {
65586567
enum bpf_prog_type tgt_type;
65596568

kernel/bpf/verifier.c

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#include <linux/cpumask.h>
2929
#include <linux/bpf_mem_alloc.h>
3030
#include <net/xdp.h>
31+
#include <linux/trace_events.h>
32+
#include <linux/kallsyms.h>
3133

3234
#include "disasm.h"
3335

@@ -21785,11 +21787,13 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
2178521787
{
2178621788
bool prog_extension = prog->type == BPF_PROG_TYPE_EXT;
2178721789
bool prog_tracing = prog->type == BPF_PROG_TYPE_TRACING;
21790+
char trace_symbol[KSYM_SYMBOL_LEN];
2178821791
const char prefix[] = "btf_trace_";
21792+
struct bpf_raw_event_map *btp;
2178921793
int ret = 0, subprog = -1, i;
2179021794
const struct btf_type *t;
2179121795
bool conservative = true;
21792-
const char *tname;
21796+
const char *tname, *fname;
2179321797
struct btf *btf;
2179421798
long addr = 0;
2179521799
struct module *mod = NULL;
@@ -21920,10 +21924,34 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
2192021924
return -EINVAL;
2192121925
}
2192221926
tname += sizeof(prefix) - 1;
21923-
t = btf_type_by_id(btf, t->type);
21924-
if (!btf_type_is_ptr(t))
21925-
/* should never happen in valid vmlinux build */
21927+
21928+
/* The func_proto of "btf_trace_##tname" is generated from typedef without argument
21929+
* names. Thus using bpf_raw_event_map to get argument names.
21930+
*/
21931+
btp = bpf_get_raw_tracepoint(tname);
21932+
if (!btp)
2192621933
return -EINVAL;
21934+
fname = kallsyms_lookup((unsigned long)btp->bpf_func, NULL, NULL, NULL,
21935+
trace_symbol);
21936+
bpf_put_raw_tracepoint(btp);
21937+
21938+
if (fname)
21939+
ret = btf_find_by_name_kind(btf, fname, BTF_KIND_FUNC);
21940+
21941+
if (!fname || ret < 0) {
21942+
bpf_log(log, "Cannot find btf of tracepoint template, fall back to %s%s.\n",
21943+
prefix, tname);
21944+
t = btf_type_by_id(btf, t->type);
21945+
if (!btf_type_is_ptr(t))
21946+
/* should never happen in valid vmlinux build */
21947+
return -EINVAL;
21948+
} else {
21949+
t = btf_type_by_id(btf, ret);
21950+
if (!btf_type_is_func(t))
21951+
/* should never happen in valid vmlinux build */
21952+
return -EINVAL;
21953+
}
21954+
2192721955
t = btf_type_by_id(btf, t->type);
2192821956
if (!btf_type_is_func_proto(t))
2192921957
/* should never happen in valid vmlinux build */

0 commit comments

Comments
 (0)