From d273359961166128ccd4c9d7a916c39c6abe52a3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 19 Dec 2022 13:23:49 +0100 Subject: [PATCH] 6.0-stable patches added patches: bpf-rename-__bpf_kprobe_multi_cookie_cmp-to-bpf_kprobe_multi_addrs_cmp.patch bpf-take-module-reference-on-kprobe_multi-link.patch ftrace-add-support-to-resolve-module-symbols-in-ftrace_lookup_symbols.patch kallsyms-make-module_kallsyms_on_each_symbol-generally-available.patch selftests-bpf-add-bpf_testmod_fentry_-functions.patch selftests-bpf-add-kprobe_multi-check-to-module-attach-test.patch selftests-bpf-add-kprobe_multi-kmod-attach-api-tests.patch selftests-bpf-add-load_kallsyms_refresh-function.patch --- ...ie_cmp-to-bpf_kprobe_multi_addrs_cmp.patch | 53 ++++++ ...odule-reference-on-kprobe_multi-link.patch | 176 +++++++++++++++++ ...ule-symbols-in-ftrace_lookup_symbols.patch | 70 +++++++ ...s_on_each_symbol-generally-available.patch | 65 +++++++ ...pf-add-bpf_testmod_fentry_-functions.patch | 68 +++++++ ...be_multi-check-to-module-attach-test.patch | 54 ++++++ ...d-kprobe_multi-kmod-attach-api-tests.patch | 177 ++++++++++++++++++ ...f-add-load_kallsyms_refresh-function.patch | 84 +++++++++ queue-6.0/series | 8 + 9 files changed, 755 insertions(+) create mode 100644 queue-6.0/bpf-rename-__bpf_kprobe_multi_cookie_cmp-to-bpf_kprobe_multi_addrs_cmp.patch create mode 100644 queue-6.0/bpf-take-module-reference-on-kprobe_multi-link.patch create mode 100644 queue-6.0/ftrace-add-support-to-resolve-module-symbols-in-ftrace_lookup_symbols.patch create mode 100644 queue-6.0/kallsyms-make-module_kallsyms_on_each_symbol-generally-available.patch create mode 100644 queue-6.0/selftests-bpf-add-bpf_testmod_fentry_-functions.patch create mode 100644 queue-6.0/selftests-bpf-add-kprobe_multi-check-to-module-attach-test.patch create mode 100644 queue-6.0/selftests-bpf-add-kprobe_multi-kmod-attach-api-tests.patch create mode 100644 queue-6.0/selftests-bpf-add-load_kallsyms_refresh-function.patch diff --git a/queue-6.0/bpf-rename-__bpf_kprobe_multi_cookie_cmp-to-bpf_kprobe_multi_addrs_cmp.patch b/queue-6.0/bpf-rename-__bpf_kprobe_multi_cookie_cmp-to-bpf_kprobe_multi_addrs_cmp.patch new file mode 100644 index 00000000000..b46544d8982 --- /dev/null +++ b/queue-6.0/bpf-rename-__bpf_kprobe_multi_cookie_cmp-to-bpf_kprobe_multi_addrs_cmp.patch @@ -0,0 +1,53 @@ +From stable-owner@vger.kernel.org Fri Dec 16 13:57:05 2022 +From: Jiri Olsa +Date: Fri, 16 Dec 2022 13:56:23 +0100 +Subject: bpf: Rename __bpf_kprobe_multi_cookie_cmp to bpf_kprobe_multi_addrs_cmp +To: stable@vger.kernel.org +Cc: Song Liu , bpf@vger.kernel.org, Martynas Pumputis +Message-ID: <20221216125628.1622505-4-jolsa@kernel.org> + +From: Jiri Olsa + +commit 1a1b0716d36d21f8448bd7d3f1c0ade7230bb294 upstream. + +Renaming __bpf_kprobe_multi_cookie_cmp to bpf_kprobe_multi_addrs_cmp, +because it's more suitable to current and upcoming code. + +Acked-by: Song Liu +Signed-off-by: Jiri Olsa +Link: https://lore.kernel.org/r/20221025134148.3300700-4-jolsa@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/bpf_trace.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/kernel/trace/bpf_trace.c ++++ b/kernel/trace/bpf_trace.c +@@ -2362,7 +2362,7 @@ static void bpf_kprobe_multi_cookie_swap + swap(*cookie_a, *cookie_b); + } + +-static int __bpf_kprobe_multi_cookie_cmp(const void *a, const void *b) ++static int bpf_kprobe_multi_addrs_cmp(const void *a, const void *b) + { + const unsigned long *addr_a = a, *addr_b = b; + +@@ -2373,7 +2373,7 @@ static int __bpf_kprobe_multi_cookie_cmp + + static int bpf_kprobe_multi_cookie_cmp(const void *a, const void *b, const void *priv) + { +- return __bpf_kprobe_multi_cookie_cmp(a, b); ++ return bpf_kprobe_multi_addrs_cmp(a, b); + } + + static u64 bpf_kprobe_multi_cookie(struct bpf_run_ctx *ctx) +@@ -2391,7 +2391,7 @@ static u64 bpf_kprobe_multi_cookie(struc + return 0; + entry_ip = run_ctx->entry_ip; + addr = bsearch(&entry_ip, link->addrs, link->cnt, sizeof(entry_ip), +- __bpf_kprobe_multi_cookie_cmp); ++ bpf_kprobe_multi_addrs_cmp); + if (!addr) + return 0; + cookie = link->cookies + (addr - link->addrs); diff --git a/queue-6.0/bpf-take-module-reference-on-kprobe_multi-link.patch b/queue-6.0/bpf-take-module-reference-on-kprobe_multi-link.patch new file mode 100644 index 00000000000..ba12eb3ab75 --- /dev/null +++ b/queue-6.0/bpf-take-module-reference-on-kprobe_multi-link.patch @@ -0,0 +1,176 @@ +From stable-owner@vger.kernel.org Fri Dec 16 13:57:18 2022 +From: Jiri Olsa +Date: Fri, 16 Dec 2022 13:56:24 +0100 +Subject: bpf: Take module reference on kprobe_multi link +To: stable@vger.kernel.org +Cc: Andrii Nakryiko , bpf@vger.kernel.org, Martynas Pumputis +Message-ID: <20221216125628.1622505-5-jolsa@kernel.org> + +From: Jiri Olsa + +commit e22061b2d3095c12f90336479f24bf5eeb70e1bd upstream. + +Currently we allow to create kprobe multi link on function from kernel +module, but we don't take the module reference to ensure it's not +unloaded while we are tracing it. + +The multi kprobe link is based on fprobe/ftrace layer which takes +different approach and releases ftrace hooks when module is unloaded +even if there's tracer registered on top of it. + +Adding code that gathers all the related modules for the link and takes +their references before it's attached. All kernel module references are +released after link is unregistered. + +Note that we do it the same way already for trampoline probes +(but for single address). + +Acked-by: Andrii Nakryiko +Signed-off-by: Jiri Olsa +Link: https://lore.kernel.org/r/20221025134148.3300700-5-jolsa@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/bpf_trace.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 92 insertions(+) + +--- a/kernel/trace/bpf_trace.c ++++ b/kernel/trace/bpf_trace.c +@@ -2264,6 +2264,8 @@ struct bpf_kprobe_multi_link { + unsigned long *addrs; + u64 *cookies; + u32 cnt; ++ u32 mods_cnt; ++ struct module **mods; + }; + + struct bpf_kprobe_multi_run_ctx { +@@ -2319,6 +2321,14 @@ error: + return err; + } + ++static void kprobe_multi_put_modules(struct module **mods, u32 cnt) ++{ ++ u32 i; ++ ++ for (i = 0; i < cnt; i++) ++ module_put(mods[i]); ++} ++ + static void free_user_syms(struct user_syms *us) + { + kvfree(us->syms); +@@ -2331,6 +2341,7 @@ static void bpf_kprobe_multi_link_releas + + kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link); + unregister_fprobe(&kmulti_link->fp); ++ kprobe_multi_put_modules(kmulti_link->mods, kmulti_link->mods_cnt); + } + + static void bpf_kprobe_multi_link_dealloc(struct bpf_link *link) +@@ -2340,6 +2351,7 @@ static void bpf_kprobe_multi_link_deallo + kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link); + kvfree(kmulti_link->addrs); + kvfree(kmulti_link->cookies); ++ kfree(kmulti_link->mods); + kfree(kmulti_link); + } + +@@ -2475,6 +2487,71 @@ static void symbols_swap_r(void *a, void + } + } + ++struct module_addr_args { ++ unsigned long *addrs; ++ u32 addrs_cnt; ++ struct module **mods; ++ int mods_cnt; ++ int mods_cap; ++}; ++ ++static int module_callback(void *data, const char *name, ++ struct module *mod, unsigned long addr) ++{ ++ struct module_addr_args *args = data; ++ struct module **mods; ++ ++ /* We iterate all modules symbols and for each we: ++ * - search for it in provided addresses array ++ * - if found we check if we already have the module pointer stored ++ * (we iterate modules sequentially, so we can check just the last ++ * module pointer) ++ * - take module reference and store it ++ */ ++ if (!bsearch(&addr, args->addrs, args->addrs_cnt, sizeof(addr), ++ bpf_kprobe_multi_addrs_cmp)) ++ return 0; ++ ++ if (args->mods && args->mods[args->mods_cnt - 1] == mod) ++ return 0; ++ ++ if (args->mods_cnt == args->mods_cap) { ++ args->mods_cap = max(16, args->mods_cap * 3 / 2); ++ mods = krealloc_array(args->mods, args->mods_cap, sizeof(*mods), GFP_KERNEL); ++ if (!mods) ++ return -ENOMEM; ++ args->mods = mods; ++ } ++ ++ if (!try_module_get(mod)) ++ return -EINVAL; ++ ++ args->mods[args->mods_cnt] = mod; ++ args->mods_cnt++; ++ return 0; ++} ++ ++static int get_modules_for_addrs(struct module ***mods, unsigned long *addrs, u32 addrs_cnt) ++{ ++ struct module_addr_args args = { ++ .addrs = addrs, ++ .addrs_cnt = addrs_cnt, ++ }; ++ int err; ++ ++ /* We return either err < 0 in case of error, ... */ ++ err = module_kallsyms_on_each_symbol(module_callback, &args); ++ if (err) { ++ kprobe_multi_put_modules(args.mods, args.mods_cnt); ++ kfree(args.mods); ++ return err; ++ } ++ ++ /* or number of modules found if everything is ok. */ ++ *mods = args.mods; ++ return args.mods_cnt; ++} ++ + int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog) + { + struct bpf_kprobe_multi_link *link = NULL; +@@ -2585,10 +2662,25 @@ int bpf_kprobe_multi_link_attach(const u + bpf_kprobe_multi_cookie_cmp, + bpf_kprobe_multi_cookie_swap, + link); ++ } else { ++ /* ++ * We need to sort addrs array even if there are no cookies ++ * provided, to allow bsearch in get_modules_for_addrs. ++ */ ++ sort(addrs, cnt, sizeof(*addrs), ++ bpf_kprobe_multi_addrs_cmp, NULL); ++ } ++ ++ err = get_modules_for_addrs(&link->mods, addrs, cnt); ++ if (err < 0) { ++ bpf_link_cleanup(&link_primer); ++ return err; + } ++ link->mods_cnt = err; + + err = register_fprobe_ips(&link->fp, addrs, cnt); + if (err) { ++ kprobe_multi_put_modules(link->mods, link->mods_cnt); + bpf_link_cleanup(&link_primer); + return err; + } diff --git a/queue-6.0/ftrace-add-support-to-resolve-module-symbols-in-ftrace_lookup_symbols.patch b/queue-6.0/ftrace-add-support-to-resolve-module-symbols-in-ftrace_lookup_symbols.patch new file mode 100644 index 00000000000..0120d3c4a85 --- /dev/null +++ b/queue-6.0/ftrace-add-support-to-resolve-module-symbols-in-ftrace_lookup_symbols.patch @@ -0,0 +1,70 @@ +From stable-owner@vger.kernel.org Fri Dec 16 13:57:01 2022 +From: Jiri Olsa +Date: Fri, 16 Dec 2022 13:56:22 +0100 +Subject: ftrace: Add support to resolve module symbols in ftrace_lookup_symbols +To: stable@vger.kernel.org +Cc: Martynas Pumputis , Song Liu , bpf@vger.kernel.org +Message-ID: <20221216125628.1622505-3-jolsa@kernel.org> + +From: Jiri Olsa + +commit 3640bf8584f4ab0f5eed6285f09213954acd8b62 upstream. + +Currently ftrace_lookup_symbols iterates only over core symbols, +adding module_kallsyms_on_each_symbol call to check on modules +symbols as well. + +Also removing 'args.found == args.cnt' condition, because it's +already checked in kallsyms_callback function. + +Also removing 'err < 0' check, because both *kallsyms_on_each_symbol +functions do not return error. + +Reported-by: Martynas Pumputis +Acked-by: Song Liu +Signed-off-by: Jiri Olsa +Link: https://lore.kernel.org/r/20221025134148.3300700-3-jolsa@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/ftrace.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -8261,6 +8261,10 @@ struct kallsyms_data { + size_t found; + }; + ++/* This function gets called for all kernel and module symbols ++ * and returns 1 in case we resolved all the requested symbols, ++ * 0 otherwise. ++ */ + static int kallsyms_callback(void *data, const char *name, + struct module *mod, unsigned long addr) + { +@@ -8304,17 +8308,19 @@ static int kallsyms_callback(void *data, + int ftrace_lookup_symbols(const char **sorted_syms, size_t cnt, unsigned long *addrs) + { + struct kallsyms_data args; +- int err; ++ int found_all; + + memset(addrs, 0, sizeof(*addrs) * cnt); + args.addrs = addrs; + args.syms = sorted_syms; + args.cnt = cnt; + args.found = 0; +- err = kallsyms_on_each_symbol(kallsyms_callback, &args); +- if (err < 0) +- return err; +- return args.found == args.cnt ? 0 : -ESRCH; ++ ++ found_all = kallsyms_on_each_symbol(kallsyms_callback, &args); ++ if (found_all) ++ return 0; ++ found_all = module_kallsyms_on_each_symbol(kallsyms_callback, &args); ++ return found_all ? 0 : -ESRCH; + } + + #ifdef CONFIG_SYSCTL diff --git a/queue-6.0/kallsyms-make-module_kallsyms_on_each_symbol-generally-available.patch b/queue-6.0/kallsyms-make-module_kallsyms_on_each_symbol-generally-available.patch new file mode 100644 index 00000000000..f7025070c2f --- /dev/null +++ b/queue-6.0/kallsyms-make-module_kallsyms_on_each_symbol-generally-available.patch @@ -0,0 +1,65 @@ +From stable-owner@vger.kernel.org Fri Dec 16 13:56:47 2022 +From: Jiri Olsa +Date: Fri, 16 Dec 2022 13:56:21 +0100 +Subject: kallsyms: Make module_kallsyms_on_each_symbol generally available +To: stable@vger.kernel.org +Cc: Christoph Hellwig , Song Liu , bpf@vger.kernel.org, Martynas Pumputis +Message-ID: <20221216125628.1622505-2-jolsa@kernel.org> + +From: Jiri Olsa + +commit 73feb8d5fa3b755bb51077c0aabfb6aa556fd498 upstream. + +Making module_kallsyms_on_each_symbol generally available, so it +can be used outside CONFIG_LIVEPATCH option in following changes. + +Rather than adding another ifdef option let's make the function +generally available (when CONFIG_KALLSYMS and CONFIG_MODULES +options are defined). + +Cc: Christoph Hellwig +Acked-by: Song Liu +Signed-off-by: Jiri Olsa +Link: https://lore.kernel.org/r/20221025134148.3300700-2-jolsa@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/module.h | 9 +++++++++ + kernel/module/kallsyms.c | 2 -- + 2 files changed, 9 insertions(+), 2 deletions(-) + +--- a/include/linux/module.h ++++ b/include/linux/module.h +@@ -879,8 +879,17 @@ static inline bool module_sig_ok(struct + } + #endif /* CONFIG_MODULE_SIG */ + ++#if defined(CONFIG_MODULES) && defined(CONFIG_KALLSYMS) + int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, + struct module *, unsigned long), + void *data); ++#else ++static inline int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, ++ struct module *, unsigned long), ++ void *data) ++{ ++ return -EOPNOTSUPP; ++} ++#endif /* CONFIG_MODULES && CONFIG_KALLSYMS */ + + #endif /* _LINUX_MODULE_H */ +--- a/kernel/module/kallsyms.c ++++ b/kernel/module/kallsyms.c +@@ -494,7 +494,6 @@ unsigned long module_kallsyms_lookup_nam + return ret; + } + +-#ifdef CONFIG_LIVEPATCH + int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, + struct module *, unsigned long), + void *data) +@@ -531,4 +530,3 @@ out: + mutex_unlock(&module_mutex); + return ret; + } +-#endif /* CONFIG_LIVEPATCH */ diff --git a/queue-6.0/selftests-bpf-add-bpf_testmod_fentry_-functions.patch b/queue-6.0/selftests-bpf-add-bpf_testmod_fentry_-functions.patch new file mode 100644 index 00000000000..c1b2e88ee26 --- /dev/null +++ b/queue-6.0/selftests-bpf-add-bpf_testmod_fentry_-functions.patch @@ -0,0 +1,68 @@ +From stable-owner@vger.kernel.org Fri Dec 16 13:57:32 2022 +From: Jiri Olsa +Date: Fri, 16 Dec 2022 13:56:26 +0100 +Subject: selftests/bpf: Add bpf_testmod_fentry_* functions +To: stable@vger.kernel.org +Cc: Song Liu , bpf@vger.kernel.org, Martynas Pumputis +Message-ID: <20221216125628.1622505-7-jolsa@kernel.org> + +From: Jiri Olsa + +commit fee356ede980b6c2c8db612e18b25738356d6744 upstream. + +Adding 3 bpf_testmod_fentry_* functions to have a way to test +kprobe multi link on kernel module. They follow bpf_fentry_test* +functions prototypes/code. + +Adding equivalent functions to all bpf_fentry_test* does not +seems necessary at the moment, could be added later. + +Acked-by: Song Liu +Signed-off-by: Jiri Olsa +Link: https://lore.kernel.org/r/20221025134148.3300700-7-jolsa@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c | 24 ++++++++++++++++++ + 1 file changed, 24 insertions(+) + +--- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c ++++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c +@@ -88,6 +88,23 @@ __weak noinline struct file *bpf_testmod + } + } + ++noinline int bpf_testmod_fentry_test1(int a) ++{ ++ return a + 1; ++} ++ ++noinline int bpf_testmod_fentry_test2(int a, u64 b) ++{ ++ return a + b; ++} ++ ++noinline int bpf_testmod_fentry_test3(char a, int b, u64 c) ++{ ++ return a + b + c; ++} ++ ++int bpf_testmod_fentry_ok; ++ + noinline ssize_t + bpf_testmod_test_read(struct file *file, struct kobject *kobj, + struct bin_attribute *bin_attr, +@@ -119,6 +136,13 @@ bpf_testmod_test_read(struct file *file, + return snprintf(buf, len, "%d\n", writable.val); + } + ++ if (bpf_testmod_fentry_test1(1) != 2 || ++ bpf_testmod_fentry_test2(2, 3) != 5 || ++ bpf_testmod_fentry_test3(4, 5, 6) != 15) ++ goto out; ++ ++ bpf_testmod_fentry_ok = 1; ++out: + return -EIO; /* always fail */ + } + EXPORT_SYMBOL(bpf_testmod_test_read); diff --git a/queue-6.0/selftests-bpf-add-kprobe_multi-check-to-module-attach-test.patch b/queue-6.0/selftests-bpf-add-kprobe_multi-check-to-module-attach-test.patch new file mode 100644 index 00000000000..ae0cabfa7d5 --- /dev/null +++ b/queue-6.0/selftests-bpf-add-kprobe_multi-check-to-module-attach-test.patch @@ -0,0 +1,54 @@ +From stable-owner@vger.kernel.org Fri Dec 16 13:57:41 2022 +From: Jiri Olsa +Date: Fri, 16 Dec 2022 13:56:27 +0100 +Subject: selftests/bpf: Add kprobe_multi check to module attach test +To: stable@vger.kernel.org +Cc: Song Liu , bpf@vger.kernel.org, Martynas Pumputis +Message-ID: <20221216125628.1622505-8-jolsa@kernel.org> + +From: Jiri Olsa + +commit e697d8dcebd2f557fa5e5ed57aaf0a9992ce9df8 upstream. + +Adding test that makes sure the kernel module won't be removed +if there's kprobe multi link defined on top of it. + +Acked-by: Song Liu +Signed-off-by: Jiri Olsa +Link: https://lore.kernel.org/r/20221025134148.3300700-8-jolsa@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/bpf/prog_tests/module_attach.c | 7 +++++++ + tools/testing/selftests/bpf/progs/test_module_attach.c | 6 ++++++ + 2 files changed, 13 insertions(+) + +--- a/tools/testing/selftests/bpf/prog_tests/module_attach.c ++++ b/tools/testing/selftests/bpf/prog_tests/module_attach.c +@@ -103,6 +103,13 @@ void test_module_attach(void) + ASSERT_ERR(delete_module("bpf_testmod", 0), "delete_module"); + bpf_link__destroy(link); + ++ link = bpf_program__attach(skel->progs.kprobe_multi); ++ if (!ASSERT_OK_PTR(link, "attach_kprobe_multi")) ++ goto cleanup; ++ ++ ASSERT_ERR(delete_module("bpf_testmod", 0), "delete_module"); ++ bpf_link__destroy(link); ++ + cleanup: + test_module_attach__destroy(skel); + } +--- a/tools/testing/selftests/bpf/progs/test_module_attach.c ++++ b/tools/testing/selftests/bpf/progs/test_module_attach.c +@@ -110,4 +110,10 @@ int BPF_PROG(handle_fmod_ret, + return 0; /* don't override the exit code */ + } + ++SEC("kprobe.multi/bpf_testmod_test_read") ++int BPF_PROG(kprobe_multi) ++{ ++ return 0; ++} ++ + char _license[] SEC("license") = "GPL"; diff --git a/queue-6.0/selftests-bpf-add-kprobe_multi-kmod-attach-api-tests.patch b/queue-6.0/selftests-bpf-add-kprobe_multi-kmod-attach-api-tests.patch new file mode 100644 index 00000000000..c3cd849b96e --- /dev/null +++ b/queue-6.0/selftests-bpf-add-kprobe_multi-kmod-attach-api-tests.patch @@ -0,0 +1,177 @@ +From stable-owner@vger.kernel.org Fri Dec 16 13:57:50 2022 +From: Jiri Olsa +Date: Fri, 16 Dec 2022 13:56:28 +0100 +Subject: selftests/bpf: Add kprobe_multi kmod attach api tests +To: stable@vger.kernel.org +Cc: Song Liu , bpf@vger.kernel.org, Martynas Pumputis +Message-ID: <20221216125628.1622505-9-jolsa@kernel.org> + +From: Jiri Olsa + +commit be884a22c1c835a146e97c6ab282a2b31b002e1f upstream. + +Adding kprobe_multi kmod attach api tests that attach bpf_testmod +functions via bpf_program__attach_kprobe_multi_opts. + +Running it as serial test, because we don't want other tests to +reload bpf_testmod while it's running. + +Acked-by: Song Liu +Signed-off-by: Jiri Olsa +Link: https://lore.kernel.org/r/20221025134148.3300700-9-jolsa@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/bpf/prog_tests/kprobe_multi_testmod_test.c | 89 ++++++++++ + tools/testing/selftests/bpf/progs/kprobe_multi.c | 50 +++++ + 2 files changed, 139 insertions(+) + create mode 100644 tools/testing/selftests/bpf/prog_tests/kprobe_multi_testmod_test.c + +--- /dev/null ++++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_testmod_test.c +@@ -0,0 +1,89 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include ++#include "kprobe_multi.skel.h" ++#include "trace_helpers.h" ++#include "bpf/libbpf_internal.h" ++ ++static void kprobe_multi_testmod_check(struct kprobe_multi *skel) ++{ ++ ASSERT_EQ(skel->bss->kprobe_testmod_test1_result, 1, "kprobe_test1_result"); ++ ASSERT_EQ(skel->bss->kprobe_testmod_test2_result, 1, "kprobe_test2_result"); ++ ASSERT_EQ(skel->bss->kprobe_testmod_test3_result, 1, "kprobe_test3_result"); ++ ++ ASSERT_EQ(skel->bss->kretprobe_testmod_test1_result, 1, "kretprobe_test1_result"); ++ ASSERT_EQ(skel->bss->kretprobe_testmod_test2_result, 1, "kretprobe_test2_result"); ++ ASSERT_EQ(skel->bss->kretprobe_testmod_test3_result, 1, "kretprobe_test3_result"); ++} ++ ++static void test_testmod_attach_api(struct bpf_kprobe_multi_opts *opts) ++{ ++ struct kprobe_multi *skel = NULL; ++ ++ skel = kprobe_multi__open_and_load(); ++ if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load")) ++ return; ++ ++ skel->bss->pid = getpid(); ++ ++ skel->links.test_kprobe_testmod = bpf_program__attach_kprobe_multi_opts( ++ skel->progs.test_kprobe_testmod, ++ NULL, opts); ++ if (!skel->links.test_kprobe_testmod) ++ goto cleanup; ++ ++ opts->retprobe = true; ++ skel->links.test_kretprobe_testmod = bpf_program__attach_kprobe_multi_opts( ++ skel->progs.test_kretprobe_testmod, ++ NULL, opts); ++ if (!skel->links.test_kretprobe_testmod) ++ goto cleanup; ++ ++ ASSERT_OK(trigger_module_test_read(1), "trigger_read"); ++ kprobe_multi_testmod_check(skel); ++ ++cleanup: ++ kprobe_multi__destroy(skel); ++} ++ ++static void test_testmod_attach_api_addrs(void) ++{ ++ LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); ++ unsigned long long addrs[3]; ++ ++ addrs[0] = ksym_get_addr("bpf_testmod_fentry_test1"); ++ ASSERT_NEQ(addrs[0], 0, "ksym_get_addr"); ++ addrs[1] = ksym_get_addr("bpf_testmod_fentry_test2"); ++ ASSERT_NEQ(addrs[1], 0, "ksym_get_addr"); ++ addrs[2] = ksym_get_addr("bpf_testmod_fentry_test3"); ++ ASSERT_NEQ(addrs[2], 0, "ksym_get_addr"); ++ ++ opts.addrs = (const unsigned long *) addrs; ++ opts.cnt = ARRAY_SIZE(addrs); ++ ++ test_testmod_attach_api(&opts); ++} ++ ++static void test_testmod_attach_api_syms(void) ++{ ++ LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); ++ const char *syms[3] = { ++ "bpf_testmod_fentry_test1", ++ "bpf_testmod_fentry_test2", ++ "bpf_testmod_fentry_test3", ++ }; ++ ++ opts.syms = syms; ++ opts.cnt = ARRAY_SIZE(syms); ++ test_testmod_attach_api(&opts); ++} ++ ++void serial_test_kprobe_multi_testmod_test(void) ++{ ++ if (!ASSERT_OK(load_kallsyms_refresh(), "load_kallsyms_refresh")) ++ return; ++ ++ if (test__start_subtest("testmod_attach_api_syms")) ++ test_testmod_attach_api_syms(); ++ if (test__start_subtest("testmod_attach_api_addrs")) ++ test_testmod_attach_api_addrs(); ++} +--- a/tools/testing/selftests/bpf/progs/kprobe_multi.c ++++ b/tools/testing/selftests/bpf/progs/kprobe_multi.c +@@ -110,3 +110,53 @@ int test_kretprobe_manual(struct pt_regs + kprobe_multi_check(ctx, true); + return 0; + } ++ ++extern const void bpf_testmod_fentry_test1 __ksym; ++extern const void bpf_testmod_fentry_test2 __ksym; ++extern const void bpf_testmod_fentry_test3 __ksym; ++ ++__u64 kprobe_testmod_test1_result = 0; ++__u64 kprobe_testmod_test2_result = 0; ++__u64 kprobe_testmod_test3_result = 0; ++ ++__u64 kretprobe_testmod_test1_result = 0; ++__u64 kretprobe_testmod_test2_result = 0; ++__u64 kretprobe_testmod_test3_result = 0; ++ ++static void kprobe_multi_testmod_check(void *ctx, bool is_return) ++{ ++ if (bpf_get_current_pid_tgid() >> 32 != pid) ++ return; ++ ++ __u64 addr = bpf_get_func_ip(ctx); ++ ++ if (is_return) { ++ if ((const void *) addr == &bpf_testmod_fentry_test1) ++ kretprobe_testmod_test1_result = 1; ++ if ((const void *) addr == &bpf_testmod_fentry_test2) ++ kretprobe_testmod_test2_result = 1; ++ if ((const void *) addr == &bpf_testmod_fentry_test3) ++ kretprobe_testmod_test3_result = 1; ++ } else { ++ if ((const void *) addr == &bpf_testmod_fentry_test1) ++ kprobe_testmod_test1_result = 1; ++ if ((const void *) addr == &bpf_testmod_fentry_test2) ++ kprobe_testmod_test2_result = 1; ++ if ((const void *) addr == &bpf_testmod_fentry_test3) ++ kprobe_testmod_test3_result = 1; ++ } ++} ++ ++SEC("kprobe.multi") ++int test_kprobe_testmod(struct pt_regs *ctx) ++{ ++ kprobe_multi_testmod_check(ctx, false); ++ return 0; ++} ++ ++SEC("kretprobe.multi") ++int test_kretprobe_testmod(struct pt_regs *ctx) ++{ ++ kprobe_multi_testmod_check(ctx, true); ++ return 0; ++} diff --git a/queue-6.0/selftests-bpf-add-load_kallsyms_refresh-function.patch b/queue-6.0/selftests-bpf-add-load_kallsyms_refresh-function.patch new file mode 100644 index 00000000000..da3a44d0762 --- /dev/null +++ b/queue-6.0/selftests-bpf-add-load_kallsyms_refresh-function.patch @@ -0,0 +1,84 @@ +From stable-owner@vger.kernel.org Fri Dec 16 13:57:23 2022 +From: Jiri Olsa +Date: Fri, 16 Dec 2022 13:56:25 +0100 +Subject: selftests/bpf: Add load_kallsyms_refresh function +To: stable@vger.kernel.org +Cc: Song Liu , bpf@vger.kernel.org, Martynas Pumputis +Message-ID: <20221216125628.1622505-6-jolsa@kernel.org> + +From: Jiri Olsa + +commit 10705b2b7a8e4eb46ab5bf1b9ee354cb9a929428 upstream. + +Adding load_kallsyms_refresh function to re-read symbols from +/proc/kallsyms file. + +This will be needed to get proper functions addresses from +bpf_testmod.ko module, which is loaded/unloaded several times +during the tests run, so symbols might be already old when +we need to use them. + +Acked-by: Song Liu +Signed-off-by: Jiri Olsa +Link: https://lore.kernel.org/r/20221025134148.3300700-6-jolsa@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/bpf/trace_helpers.c | 20 +++++++++++++------- + tools/testing/selftests/bpf/trace_helpers.h | 2 ++ + 2 files changed, 15 insertions(+), 7 deletions(-) + +--- a/tools/testing/selftests/bpf/trace_helpers.c ++++ b/tools/testing/selftests/bpf/trace_helpers.c +@@ -23,7 +23,7 @@ static int ksym_cmp(const void *p1, cons + return ((struct ksym *)p1)->addr - ((struct ksym *)p2)->addr; + } + +-int load_kallsyms(void) ++int load_kallsyms_refresh(void) + { + FILE *f; + char func[256], buf[256]; +@@ -31,12 +31,7 @@ int load_kallsyms(void) + void *addr; + int i = 0; + +- /* +- * This is called/used from multiplace places, +- * load symbols just once. +- */ +- if (sym_cnt) +- return 0; ++ sym_cnt = 0; + + f = fopen("/proc/kallsyms", "r"); + if (!f) +@@ -57,6 +52,17 @@ int load_kallsyms(void) + return 0; + } + ++int load_kallsyms(void) ++{ ++ /* ++ * This is called/used from multiplace places, ++ * load symbols just once. ++ */ ++ if (sym_cnt) ++ return 0; ++ return load_kallsyms_refresh(); ++} ++ + struct ksym *ksym_search(long key) + { + int start = 0, end = sym_cnt; +--- a/tools/testing/selftests/bpf/trace_helpers.h ++++ b/tools/testing/selftests/bpf/trace_helpers.h +@@ -10,6 +10,8 @@ struct ksym { + }; + + int load_kallsyms(void); ++int load_kallsyms_refresh(void); ++ + struct ksym *ksym_search(long key); + long ksym_get_addr(const char *name); + diff --git a/queue-6.0/series b/queue-6.0/series index 65112145bce..37f38ee7866 100644 --- a/queue-6.0/series +++ b/queue-6.0/series @@ -1 +1,9 @@ pci-mt7621-add-sentinel-to-quirks-table.patch +kallsyms-make-module_kallsyms_on_each_symbol-generally-available.patch +ftrace-add-support-to-resolve-module-symbols-in-ftrace_lookup_symbols.patch +bpf-rename-__bpf_kprobe_multi_cookie_cmp-to-bpf_kprobe_multi_addrs_cmp.patch +bpf-take-module-reference-on-kprobe_multi-link.patch +selftests-bpf-add-load_kallsyms_refresh-function.patch +selftests-bpf-add-bpf_testmod_fentry_-functions.patch +selftests-bpf-add-kprobe_multi-check-to-module-attach-test.patch +selftests-bpf-add-kprobe_multi-kmod-attach-api-tests.patch -- 2.47.3