Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

authored by

Alexei Starovoitov and committed by
Daniel Borkmann
2d3eb67f f41aa387

+40 -1
+6
tools/include/uapi/linux/btf.h
··· 146 146 BTF_VAR_GLOBAL_EXTERN = 2, 147 147 }; 148 148 149 + enum btf_func_linkage { 150 + BTF_FUNC_STATIC = 0, 151 + BTF_FUNC_GLOBAL = 1, 152 + BTF_FUNC_EXTERN = 2, 153 + }; 154 + 149 155 /* BTF_KIND_VAR is followed by a single "struct btf_var" to describe 150 156 * additional information related to the variable such as its linkage. 151 157 */
+34 -1
tools/lib/bpf/libbpf.c
··· 173 173 __u32 btf_datasec:1; 174 174 /* BPF_F_MMAPABLE is supported for arrays */ 175 175 __u32 array_mmap:1; 176 + /* BTF_FUNC_GLOBAL is supported */ 177 + __u32 btf_func_global:1; 176 178 }; 177 179 178 180 enum reloc_type { ··· 2211 2209 2212 2210 static void bpf_object__sanitize_btf(struct bpf_object *obj) 2213 2211 { 2212 + bool has_func_global = obj->caps.btf_func_global; 2214 2213 bool has_datasec = obj->caps.btf_datasec; 2215 2214 bool has_func = obj->caps.btf_func; 2216 2215 struct btf *btf = obj->btf; 2217 2216 struct btf_type *t; 2218 2217 int i, j, vlen; 2219 2218 2220 - if (!obj->btf || (has_func && has_datasec)) 2219 + if (!obj->btf || (has_func && has_datasec && has_func_global)) 2221 2220 return; 2222 2221 2223 2222 for (i = 1; i <= btf__get_nr_types(btf); i++) { ··· 2266 2263 } else if (!has_func && btf_is_func(t)) { 2267 2264 /* replace FUNC with TYPEDEF */ 2268 2265 t->info = BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0); 2266 + } else if (!has_func_global && btf_is_func(t)) { 2267 + /* replace BTF_FUNC_GLOBAL with BTF_FUNC_STATIC */ 2268 + t->info = BTF_INFO_ENC(BTF_KIND_FUNC, 0, 0); 2269 2269 } 2270 2270 } 2271 2271 } ··· 3211 3205 return 0; 3212 3206 } 3213 3207 3208 + static int bpf_object__probe_btf_func_global(struct bpf_object *obj) 3209 + { 3210 + static const char strs[] = "\0int\0x\0a"; 3211 + /* static void x(int a) {} */ 3212 + __u32 types[] = { 3213 + /* int */ 3214 + BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 3215 + /* FUNC_PROTO */ /* [2] */ 3216 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 1), 0), 3217 + BTF_PARAM_ENC(7, 1), 3218 + /* FUNC x BTF_FUNC_GLOBAL */ /* [3] */ 3219 + BTF_TYPE_ENC(5, BTF_INFO_ENC(BTF_KIND_FUNC, 0, BTF_FUNC_GLOBAL), 2), 3220 + }; 3221 + int btf_fd; 3222 + 3223 + btf_fd = libbpf__load_raw_btf((char *)types, sizeof(types), 3224 + strs, sizeof(strs)); 3225 + if (btf_fd >= 0) { 3226 + obj->caps.btf_func_global = 1; 3227 + close(btf_fd); 3228 + return 1; 3229 + } 3230 + 3231 + return 0; 3232 + } 3233 + 3214 3234 static int bpf_object__probe_btf_datasec(struct bpf_object *obj) 3215 3235 { 3216 3236 static const char strs[] = "\0x\0.data"; ··· 3292 3260 bpf_object__probe_name, 3293 3261 bpf_object__probe_global_data, 3294 3262 bpf_object__probe_btf_func, 3263 + bpf_object__probe_btf_func_global, 3295 3264 bpf_object__probe_btf_datasec, 3296 3265 bpf_object__probe_array_mmap, 3297 3266 };