Skip to content

Commit aea28a6

Browse files
anakryikoAlexei Starovoitov
authored andcommitted
libbpf: Mark BPF subprogs with hidden visibility as static for BPF verifier
Define __hidden helper macro in bpf_helpers.h, which is a short-hand for __attribute__((visibility("hidden"))). Add libbpf support to mark BPF subprograms marked with __hidden as static in BTF information to enforce BPF verifier's static function validation algorithm, which takes more information (caller's context) into account during a subprogram validation. Signed-off-by: Andrii Nakryiko <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Yonghong Song <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 0fec7a3 commit aea28a6

File tree

4 files changed

+58
-6
lines changed

4 files changed

+58
-6
lines changed

tools/lib/bpf/bpf_helpers.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@
4747
#define __weak __attribute__((weak))
4848
#endif
4949

50+
/*
51+
* Use __hidden attribute to mark a non-static BPF subprogram effectively
52+
* static for BPF verifier's verification algorithm purposes, allowing more
53+
* extensive and permissive BPF verification process, taking into account
54+
* subprogram's caller context.
55+
*/
56+
#define __hidden __attribute__((visibility("hidden")))
57+
5058
/* When utilizing vmlinux.h with BPF CO-RE, user BPF programs can't include
5159
* any system-level headers (such as stddef.h, linux/version.h, etc), and
5260
* commonly-used macros like NULL and KERNEL_VERSION aren't available through

tools/lib/bpf/btf.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,11 +1605,6 @@ static void *btf_add_type_mem(struct btf *btf, size_t add_sz)
16051605
btf->hdr->type_len, UINT_MAX, add_sz);
16061606
}
16071607

1608-
static __u32 btf_type_info(int kind, int vlen, int kflag)
1609-
{
1610-
return (kflag << 31) | (kind << 24) | vlen;
1611-
}
1612-
16131608
static void btf_type_inc_vlen(struct btf_type *t)
16141609
{
16151610
t->info = btf_type_info(btf_kind(t), btf_vlen(t) + 1, btf_kflag(t));

tools/lib/bpf/libbpf.c

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
static struct bpf_map *bpf_object__add_map(struct bpf_object *obj);
7272
static const struct btf_type *
7373
skip_mods_and_typedefs(const struct btf *btf, __u32 id, __u32 *res_id);
74+
static bool prog_is_subprog(const struct bpf_object *obj, const struct bpf_program *prog);
7475

7576
static int __base_pr(enum libbpf_print_level level, const char *format,
7677
va_list args)
@@ -274,6 +275,7 @@ struct bpf_program {
274275
bpf_program_clear_priv_t clear_priv;
275276

276277
bool load;
278+
bool mark_btf_static;
277279
enum bpf_prog_type type;
278280
enum bpf_attach_type expected_attach_type;
279281
int prog_ifindex;
@@ -698,6 +700,15 @@ bpf_object__add_programs(struct bpf_object *obj, Elf_Data *sec_data,
698700
if (err)
699701
return err;
700702

703+
/* if function is a global/weak symbol, but has hidden
704+
* visibility (STV_HIDDEN), mark its BTF FUNC as static to
705+
* enable more permissive BPF verification mode with more
706+
* outside context available to BPF verifier
707+
*/
708+
if (GELF_ST_BIND(sym.st_info) != STB_LOCAL
709+
&& GELF_ST_VISIBILITY(sym.st_other) == STV_HIDDEN)
710+
prog->mark_btf_static = true;
711+
701712
nr_progs++;
702713
obj->nr_programs = nr_progs;
703714

@@ -2618,7 +2629,7 @@ static int bpf_object__sanitize_and_load_btf(struct bpf_object *obj)
26182629
{
26192630
struct btf *kern_btf = obj->btf;
26202631
bool btf_mandatory, sanitize;
2621-
int err = 0;
2632+
int i, err = 0;
26222633

26232634
if (!obj->btf)
26242635
return 0;
@@ -2632,6 +2643,38 @@ static int bpf_object__sanitize_and_load_btf(struct bpf_object *obj)
26322643
return 0;
26332644
}
26342645

2646+
/* Even though some subprogs are global/weak, user might prefer more
2647+
* permissive BPF verification process that BPF verifier performs for
2648+
* static functions, taking into account more context from the caller
2649+
* functions. In such case, they need to mark such subprogs with
2650+
* __attribute__((visibility("hidden"))) and libbpf will adjust
2651+
* corresponding FUNC BTF type to be marked as static and trigger more
2652+
* involved BPF verification process.
2653+
*/
2654+
for (i = 0; i < obj->nr_programs; i++) {
2655+
struct bpf_program *prog = &obj->programs[i];
2656+
struct btf_type *t;
2657+
const char *name;
2658+
int j, n;
2659+
2660+
if (!prog->mark_btf_static || !prog_is_subprog(obj, prog))
2661+
continue;
2662+
2663+
n = btf__get_nr_types(obj->btf);
2664+
for (j = 1; j <= n; j++) {
2665+
t = btf_type_by_id(obj->btf, j);
2666+
if (!btf_is_func(t) || btf_func_linkage(t) != BTF_FUNC_GLOBAL)
2667+
continue;
2668+
2669+
name = btf__str_by_offset(obj->btf, t->name_off);
2670+
if (strcmp(name, prog->name) != 0)
2671+
continue;
2672+
2673+
t->info = btf_type_info(BTF_KIND_FUNC, BTF_FUNC_STATIC, 0);
2674+
break;
2675+
}
2676+
}
2677+
26352678
sanitize = btf_needs_sanitization(obj);
26362679
if (sanitize) {
26372680
const void *raw_data;

tools/lib/bpf/libbpf_internal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#pragma GCC poison reallocarray
2020

2121
#include "libbpf.h"
22+
#include "btf.h"
2223

2324
#ifndef EM_BPF
2425
#define EM_BPF 247
@@ -132,6 +133,11 @@ struct btf_type;
132133

133134
struct btf_type *btf_type_by_id(struct btf *btf, __u32 type_id);
134135

136+
static inline __u32 btf_type_info(int kind, int vlen, int kflag)
137+
{
138+
return (kflag << 31) | (kind << 24) | vlen;
139+
}
140+
135141
void *libbpf_add_mem(void **data, size_t *cap_cnt, size_t elem_sz,
136142
size_t cur_cnt, size_t max_cnt, size_t add_cnt);
137143
int libbpf_ensure_mem(void **data, size_t *cap_cnt, size_t elem_sz, size_t need_cnt);

0 commit comments

Comments
 (0)