From: Andrii Nakryiko andrii@kernel.org
mainline inclusion from mainline-5.16-rc1 commit 13d35a0cf1741431333ba4aa9bce9c5bbc88f63b category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5EUVD CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
-------------------------------------------------
Move closer to not relying on bpf_sec_def internals that won't be part of public API, when pluggable SEC() handlers will be allowed. Drop pre-calculated prefix length, and in various helpers don't rely on this prefix length availability. Also minimize reliance on knowing bpf_sec_def's prefix for few places where section prefix shortcuts are supported (e.g., tp vs tracepoint, raw_tp vs raw_tracepoint).
Given checking some string for having a given string-constant prefix is such a common operation and so annoying to be done with pure C code, add a small macro helper, str_has_pfx(), and reuse it throughout libbpf.c where prefix comparison is performed. With __builtin_constant_p() it's possible to have a convenient helper that checks some string for having a given prefix, where prefix is either string literal (or compile-time known string due to compiler optimization) or just a runtime string pointer, which is quite convenient and saves a lot of typing and string literal duplication.
Signed-off-by: Andrii Nakryiko andrii@kernel.org Signed-off-by: Alexei Starovoitov ast@kernel.org Acked-by: Dave Marchevsky davemarchevsky@fb.com Link: https://lore.kernel.org/bpf/20210928161946.2512801-7-andrii@kernel.org (cherry picked from commit 13d35a0cf1741431333ba4aa9bce9c5bbc88f63b) Signed-off-by: Wang Yufen wangyufen@huawei.com
Conflicts: tools/lib/bpf/libbpf.c
Signed-off-by: Wang Yufen wangyufen@huawei.com --- tools/lib/bpf/libbpf.c | 41 ++++++++++++++++++--------------- tools/lib/bpf/libbpf_internal.h | 7 ++++++ 2 files changed, 30 insertions(+), 18 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index c3b2f3395e40..0f8f1e41ff22 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -224,7 +224,6 @@ typedef struct bpf_link *(*attach_fn_t)(const struct bpf_program *prog, long coo
struct bpf_sec_def { const char *sec; - size_t len; enum bpf_prog_type prog_type; enum bpf_attach_type expected_attach_type; bool is_exp_attach_type_optional; @@ -1665,7 +1664,7 @@ static int bpf_object__process_kconfig_line(struct bpf_object *obj, void *ext_val; __u64 num;
- if (strncmp(buf, "CONFIG_", 7)) + if (!str_has_pfx(buf, "CONFIG_")) return 0;
sep = strchr(buf, '='); @@ -3015,7 +3014,7 @@ static Elf_Data *elf_sec_data(const struct bpf_object *obj, Elf_Scn *scn) static bool is_sec_name_dwarf(const char *name) { /* approximation, but the actual list is too long */ - return strncmp(name, ".debug_", sizeof(".debug_") - 1) == 0; + return str_has_pfx(name, ".debug_"); }
static bool ignore_elf_section(GElf_Shdr *hdr, const char *name) @@ -3037,7 +3036,7 @@ static bool ignore_elf_section(GElf_Shdr *hdr, const char *name) if (is_sec_name_dwarf(name)) return true;
- if (strncmp(name, ".rel", sizeof(".rel") - 1) == 0) { + if (str_has_pfx(name, ".rel")) { name += sizeof(".rel") - 1; /* DWARF section relocations */ if (is_sec_name_dwarf(name)) @@ -6979,8 +6978,7 @@ static int bpf_object__resolve_externs(struct bpf_object *obj, if (err) return err; pr_debug("extern (kcfg) %s=0x%x\n", ext->name, kver); - } else if (ext->type == EXT_KCFG && - strncmp(ext->name, "CONFIG_", 7) == 0) { + } else if (ext->type == EXT_KCFG && str_has_pfx(ext->name, "CONFIG_")) { need_config = true; } else if (ext->type == EXT_KSYM) { if (ext->ksym.type_id) @@ -8053,7 +8051,6 @@ void bpf_program__set_expected_attach_type(struct bpf_program *prog, attachable, attach_btf) \ { \ .sec = string, \ - .len = sizeof(string) - 1, \ .prog_type = ptype, \ .expected_attach_type = eatype, \ .is_exp_attach_type_optional = eatype_optional, \ @@ -8084,7 +8081,6 @@ void bpf_program__set_expected_attach_type(struct bpf_program *prog,
#define SEC_DEF(sec_pfx, ptype, ...) { \ .sec = sec_pfx, \ - .len = sizeof(sec_pfx) - 1, \ .prog_type = BPF_PROG_TYPE_##ptype, \ .preload_fn = libbpf_preload_prog, \ __VA_ARGS__ \ @@ -8262,10 +8258,8 @@ static const struct bpf_sec_def *find_sec_def(const char *sec_name) int i, n = ARRAY_SIZE(section_defs);
for (i = 0; i < n; i++) { - if (strncmp(sec_name, - section_defs[i].sec, section_defs[i].len)) - continue; - return §ion_defs[i]; + if (str_has_pfx(sec_name, section_defs[i].sec)) + return §ion_defs[i]; } return NULL; } @@ -8624,7 +8618,7 @@ static int libbpf_find_attach_btf_id(struct bpf_program *prog, int *btf_obj_fd, prog->sec_name); return -ESRCH; } - attach_name = prog->sec_name + prog->sec_def->len; + attach_name = prog->sec_name + strlen(prog->sec_def->sec);
/* BPF program's BTF ID */ if (attach_prog_fd) { @@ -9368,8 +9362,11 @@ static struct bpf_link *attach_kprobe(const struct bpf_program *prog, long cooki const char *func_name; bool retprobe;
- func_name = prog->sec_name + prog->sec_def->len; - retprobe = strcmp(prog->sec_def->sec, "kretprobe/") == 0; + retprobe = str_has_pfx(prog->sec_name, "kretprobe/"); + if (retprobe) + func_name = prog->sec_name + sizeof("kretprobe/") - 1; + else + func_name = prog->sec_name + sizeof("kprobe/") - 1;
return bpf_program__attach_kprobe(prog, retprobe, func_name); } @@ -9491,8 +9488,11 @@ static struct bpf_link *attach_tp(const struct bpf_program *prog, long cookie) if (!sec_name) return libbpf_err_ptr(-ENOMEM);
- /* extract "tp/<category>/<name>" */ - tp_cat = sec_name + prog->sec_def->len; + /* extract "tp/<category>/<name>" or "tracepoint/<category>/<name>" */ + if (str_has_pfx(prog->sec_name, "tp/")) + tp_cat = sec_name + sizeof("tp/") - 1; + else + tp_cat = sec_name + sizeof("tracepoint/") - 1; tp_name = strchr(tp_cat, '/'); if (!tp_name) { free(sec_name); @@ -9538,7 +9538,12 @@ struct bpf_link *bpf_program__attach_raw_tracepoint(const struct bpf_program *pr
static struct bpf_link *attach_raw_tp(const struct bpf_program *prog, long cookie) { - const char *tp_name = prog->sec_name + prog->sec_def->len; + const char *tp_name; + + if (str_has_pfx(prog->sec_name, "raw_tp/")) + tp_name = prog->sec_name + sizeof("raw_tp/") - 1; + else + tp_name = prog->sec_name + sizeof("raw_tracepoint/") - 1;
return bpf_program__attach_raw_tracepoint(prog, tp_name); } diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h index f7a7c5fa26cd..63d0d4c7ea1d 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -89,6 +89,13 @@ (offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD)) #endif
+/* Check whether a string `str` has prefix `pfx`, regardless if `pfx` is + * a string literal known at compilation time or char * pointer known only at + * runtime. + */ +#define str_has_pfx(str, pfx) \ + (strncmp(str, pfx, __builtin_constant_p(pfx) ? sizeof(pfx) - 1 : strlen(pfx)) == 0) + /* Symbol versioning is different between static and shared library. * Properly versioned symbols are needed for shared library, but * only the symbol of the new version is needed for static library.