Skip to content

Commit 8aeaed2

Browse files
LPhghMartin KaFai Lau
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]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin KaFai Lau <[email protected]>
1 parent 23dc986 commit 8aeaed2

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

kernel/bpf/btf.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6523,6 +6523,9 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
65236523
if (prog_args_trusted(prog))
65246524
info->reg_type |= PTR_TRUSTED;
65256525

6526+
if (btf_param_match_suffix(btf, &args[arg], "__nullable"))
6527+
info->reg_type |= PTR_MAYBE_NULL;
6528+
65266529
if (tgt_prog) {
65276530
enum bpf_prog_type tgt_type;
65286531

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

@@ -21154,11 +21156,13 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
2115421156
{
2115521157
bool prog_extension = prog->type == BPF_PROG_TYPE_EXT;
2115621158
bool prog_tracing = prog->type == BPF_PROG_TYPE_TRACING;
21159+
char trace_symbol[KSYM_SYMBOL_LEN];
2115721160
const char prefix[] = "btf_trace_";
21161+
struct bpf_raw_event_map *btp;
2115821162
int ret = 0, subprog = -1, i;
2115921163
const struct btf_type *t;
2116021164
bool conservative = true;
21161-
const char *tname;
21165+
const char *tname, *fname;
2116221166
struct btf *btf;
2116321167
long addr = 0;
2116421168
struct module *mod = NULL;
@@ -21289,10 +21293,34 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
2128921293
return -EINVAL;
2129021294
}
2129121295
tname += sizeof(prefix) - 1;
21292-
t = btf_type_by_id(btf, t->type);
21293-
if (!btf_type_is_ptr(t))
21294-
/* should never happen in valid vmlinux build */
21296+
21297+
/* The func_proto of "btf_trace_##tname" is generated from typedef without argument
21298+
* names. Thus using bpf_raw_event_map to get argument names.
21299+
*/
21300+
btp = bpf_get_raw_tracepoint(tname);
21301+
if (!btp)
2129521302
return -EINVAL;
21303+
fname = kallsyms_lookup((unsigned long)btp->bpf_func, NULL, NULL, NULL,
21304+
trace_symbol);
21305+
bpf_put_raw_tracepoint(btp);
21306+
21307+
if (fname)
21308+
ret = btf_find_by_name_kind(btf, fname, BTF_KIND_FUNC);
21309+
21310+
if (!fname || ret < 0) {
21311+
bpf_log(log, "Cannot find btf of tracepoint template, fall back to %s%s.\n",
21312+
prefix, tname);
21313+
t = btf_type_by_id(btf, t->type);
21314+
if (!btf_type_is_ptr(t))
21315+
/* should never happen in valid vmlinux build */
21316+
return -EINVAL;
21317+
} else {
21318+
t = btf_type_by_id(btf, ret);
21319+
if (!btf_type_is_func(t))
21320+
/* should never happen in valid vmlinux build */
21321+
return -EINVAL;
21322+
}
21323+
2129621324
t = btf_type_by_id(btf, t->type);
2129721325
if (!btf_type_is_func_proto(t))
2129821326
/* should never happen in valid vmlinux build */

0 commit comments

Comments
 (0)