libbpf: Sanitize global functions
In case the kernel doesn't support BTF_FUNC_GLOBAL sanitize BTF produced by the compiler for global functions. Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Song Liu <songliubraving@fb.com> Link: https://lore.kernel.org/bpf/20200110064124.1760511-2-ast@kernel.org
This commit is contained in:

committed by
Daniel Borkmann

parent
f41aa387a7
commit
2d3eb67f64
@@ -146,6 +146,12 @@ enum {
|
|||||||
BTF_VAR_GLOBAL_EXTERN = 2,
|
BTF_VAR_GLOBAL_EXTERN = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum btf_func_linkage {
|
||||||
|
BTF_FUNC_STATIC = 0,
|
||||||
|
BTF_FUNC_GLOBAL = 1,
|
||||||
|
BTF_FUNC_EXTERN = 2,
|
||||||
|
};
|
||||||
|
|
||||||
/* BTF_KIND_VAR is followed by a single "struct btf_var" to describe
|
/* BTF_KIND_VAR is followed by a single "struct btf_var" to describe
|
||||||
* additional information related to the variable such as its linkage.
|
* additional information related to the variable such as its linkage.
|
||||||
*/
|
*/
|
||||||
|
@@ -173,6 +173,8 @@ struct bpf_capabilities {
|
|||||||
__u32 btf_datasec:1;
|
__u32 btf_datasec:1;
|
||||||
/* BPF_F_MMAPABLE is supported for arrays */
|
/* BPF_F_MMAPABLE is supported for arrays */
|
||||||
__u32 array_mmap:1;
|
__u32 array_mmap:1;
|
||||||
|
/* BTF_FUNC_GLOBAL is supported */
|
||||||
|
__u32 btf_func_global:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum reloc_type {
|
enum reloc_type {
|
||||||
@@ -2209,13 +2211,14 @@ static bool section_have_execinstr(struct bpf_object *obj, int idx)
|
|||||||
|
|
||||||
static void bpf_object__sanitize_btf(struct bpf_object *obj)
|
static void bpf_object__sanitize_btf(struct bpf_object *obj)
|
||||||
{
|
{
|
||||||
|
bool has_func_global = obj->caps.btf_func_global;
|
||||||
bool has_datasec = obj->caps.btf_datasec;
|
bool has_datasec = obj->caps.btf_datasec;
|
||||||
bool has_func = obj->caps.btf_func;
|
bool has_func = obj->caps.btf_func;
|
||||||
struct btf *btf = obj->btf;
|
struct btf *btf = obj->btf;
|
||||||
struct btf_type *t;
|
struct btf_type *t;
|
||||||
int i, j, vlen;
|
int i, j, vlen;
|
||||||
|
|
||||||
if (!obj->btf || (has_func && has_datasec))
|
if (!obj->btf || (has_func && has_datasec && has_func_global))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 1; i <= btf__get_nr_types(btf); i++) {
|
for (i = 1; i <= btf__get_nr_types(btf); i++) {
|
||||||
@@ -2263,6 +2266,9 @@ static void bpf_object__sanitize_btf(struct bpf_object *obj)
|
|||||||
} else if (!has_func && btf_is_func(t)) {
|
} else if (!has_func && btf_is_func(t)) {
|
||||||
/* replace FUNC with TYPEDEF */
|
/* replace FUNC with TYPEDEF */
|
||||||
t->info = BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0);
|
t->info = BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0);
|
||||||
|
} else if (!has_func_global && btf_is_func(t)) {
|
||||||
|
/* replace BTF_FUNC_GLOBAL with BTF_FUNC_STATIC */
|
||||||
|
t->info = BTF_INFO_ENC(BTF_KIND_FUNC, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3205,6 +3211,32 @@ static int bpf_object__probe_btf_func(struct bpf_object *obj)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bpf_object__probe_btf_func_global(struct bpf_object *obj)
|
||||||
|
{
|
||||||
|
static const char strs[] = "\0int\0x\0a";
|
||||||
|
/* static void x(int a) {} */
|
||||||
|
__u32 types[] = {
|
||||||
|
/* int */
|
||||||
|
BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
|
||||||
|
/* FUNC_PROTO */ /* [2] */
|
||||||
|
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 1), 0),
|
||||||
|
BTF_PARAM_ENC(7, 1),
|
||||||
|
/* FUNC x BTF_FUNC_GLOBAL */ /* [3] */
|
||||||
|
BTF_TYPE_ENC(5, BTF_INFO_ENC(BTF_KIND_FUNC, 0, BTF_FUNC_GLOBAL), 2),
|
||||||
|
};
|
||||||
|
int btf_fd;
|
||||||
|
|
||||||
|
btf_fd = libbpf__load_raw_btf((char *)types, sizeof(types),
|
||||||
|
strs, sizeof(strs));
|
||||||
|
if (btf_fd >= 0) {
|
||||||
|
obj->caps.btf_func_global = 1;
|
||||||
|
close(btf_fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int bpf_object__probe_btf_datasec(struct bpf_object *obj)
|
static int bpf_object__probe_btf_datasec(struct bpf_object *obj)
|
||||||
{
|
{
|
||||||
static const char strs[] = "\0x\0.data";
|
static const char strs[] = "\0x\0.data";
|
||||||
@@ -3260,6 +3292,7 @@ bpf_object__probe_caps(struct bpf_object *obj)
|
|||||||
bpf_object__probe_name,
|
bpf_object__probe_name,
|
||||||
bpf_object__probe_global_data,
|
bpf_object__probe_global_data,
|
||||||
bpf_object__probe_btf_func,
|
bpf_object__probe_btf_func,
|
||||||
|
bpf_object__probe_btf_func_global,
|
||||||
bpf_object__probe_btf_datasec,
|
bpf_object__probe_btf_datasec,
|
||||||
bpf_object__probe_array_mmap,
|
bpf_object__probe_array_mmap,
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user