From patchwork Mon Dec 5 15:26:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viktor Malik X-Patchwork-Id: 13064683 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 53F2EC4332F for ; Mon, 5 Dec 2022 15:28:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232769AbiLEP2j (ORCPT ); Mon, 5 Dec 2022 10:28:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59614 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232776AbiLEP2T (ORCPT ); Mon, 5 Dec 2022 10:28:19 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E6F836147 for ; Mon, 5 Dec 2022 07:26:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1670253984; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=qEKiaerBTgxeA+iQRDpxjwc3UIUz5FP4iUyhE5eUv28=; b=ZpUHkmHgyrERIIIDDabAzLH9Qp9WuMeN/hDZwhYotIel3uYLXLlLShPCRQtzaJZS4xnEcd 0igF85ezWRmLIoQJ4u7fOyoNWM1F/G6J5Ud8ruVIdRebXe1vCo0fzDRqPi767t4cfnfC2r gsXIEbJJOYfGLdiJVFMr/7PhwfmvhmI= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-173-8uT96WGBMOqEa9FGmoZw5g-1; Mon, 05 Dec 2022 10:26:22 -0500 X-MC-Unique: 8uT96WGBMOqEa9FGmoZw5g-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id BC637383328E; Mon, 5 Dec 2022 15:26:21 +0000 (UTC) Received: from ovpn-193-115.brq.redhat.com (ovpn-193-115.brq.redhat.com [10.40.193.115]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 9555540C6EC3; Mon, 5 Dec 2022 15:26:18 +0000 (UTC) From: Viktor Malik To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Viktor Malik Subject: [PATCH bpf-next v3 1/3] kallsyms: add space-efficient lookup in one module Date: Mon, 5 Dec 2022 16:26:04 +0100 Message-Id: <8831f08b909c7c670e547240368276af73e552d2.1670249590.git.vmalik@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net Until now, the only way to look up a symbol in kallsyms of a particular module was using the "module_kallsyms_lookup_name" function with the "module:symbol" string passed as a parameter. This syntax often requires to build the parameter string on stack, needlessly wasting space. This commit introduces function "kallsyms_lookup_name_in_module" which takes the module and the symbol names as separate parameters and therefore allows more space-efficient lookup. Signed-off-by: Viktor Malik --- include/linux/module.h | 7 +++++++ kernel/module/kallsyms.c | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/linux/module.h b/include/linux/module.h index 35876e89eb93..a06fbcc4013c 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -605,6 +605,7 @@ struct module *find_module(const char *name); int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, char *name, char *module_name, int *exported); +unsigned long kallsyms_lookup_name_in_module(const char *module_name, const char *name); /* Look for this name: can be of form module:name. */ unsigned long module_kallsyms_lookup_name(const char *name); @@ -783,6 +784,12 @@ static inline int module_get_kallsym(unsigned int symnum, unsigned long *value, return -ERANGE; } +static inline unsigned long kallsyms_lookup_name_in_module(const char *module_name, + const char *name) +{ + return 0; +} + static inline unsigned long module_kallsyms_lookup_name(const char *name) { return 0; diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c index 4523f99b0358..c6c8227c7a45 100644 --- a/kernel/module/kallsyms.c +++ b/kernel/module/kallsyms.c @@ -482,6 +482,22 @@ static unsigned long __module_kallsyms_lookup_name(const char *name) return 0; } +unsigned long kallsyms_lookup_name_in_module(const char *module_name, const char *name) +{ + unsigned long ret; + struct module *mod; + + preempt_disable(); + mod = find_module_all(module_name, strlen(module_name), false); + if (mod) + ret = find_kallsyms_symbol_value(mod, name); + else + ret = 0; + preempt_enable(); + return ret; + +} + /* Look for this name: can be of form module:name. */ unsigned long module_kallsyms_lookup_name(const char *name) { From patchwork Mon Dec 5 15:26:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viktor Malik X-Patchwork-Id: 13064684 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8F9B4C4332F for ; Mon, 5 Dec 2022 15:29:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232713AbiLEP3J (ORCPT ); Mon, 5 Dec 2022 10:29:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59060 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232717AbiLEP2u (ORCPT ); Mon, 5 Dec 2022 10:28:50 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 52EEA1EADB for ; Mon, 5 Dec 2022 07:26:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1670253990; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8dqUbyDZlyGg8DVT9UBDOU6EHVP5CrdcsfuouIr9/4Q=; b=FcriGVIpIEqWbm81sk2ADwvlXYmAC36A1ZIgJBXQN2ZGjhYwMqyIhBsSKOkTwZYS/jgxCw BOvZJ+tzLtMEU2GhokkvQsY/+uK+mOxTyjmtYV89iKkJ48YkcK0G3eMlwPFU55jLoDFwDQ NI76kv346uCAJPFyfQAKr+AhFYYV1gs= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-206-qNVVoELHPzWfB2lHhX6QDg-1; Mon, 05 Dec 2022 10:26:25 -0500 X-MC-Unique: qNVVoELHPzWfB2lHhX6QDg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id C100C3C0F22E; Mon, 5 Dec 2022 15:26:24 +0000 (UTC) Received: from ovpn-193-115.brq.redhat.com (ovpn-193-115.brq.redhat.com [10.40.193.115]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 1657C40C6EC3; Mon, 5 Dec 2022 15:26:21 +0000 (UTC) From: Viktor Malik To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Viktor Malik Subject: [PATCH bpf-next v3 2/3] bpf: Fix attaching fentry/fexit/fmod_ret/lsm to modules Date: Mon, 5 Dec 2022 16:26:05 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net When attaching fentry/fexit/fmod_ret/lsm to a function located in a module without specifying the target program, the verifier tries to find the address to attach to in kallsyms. This is always done by searching the entire kallsyms, not respecting the module in which the function is located. This approach causes an incorrect attachment address to be computed if the function to attach to is shadowed by a function of the same name located earlier in kallsyms. Since the attachment must contain the BTF of the program to attach to, we may extract the module name from it (if the attach target is a module) and search for the function address in the correct module. Signed-off-by: Viktor Malik Acked-by: Hao Luo --- include/linux/btf.h | 1 + kernel/bpf/btf.c | 5 +++++ kernel/bpf/verifier.c | 5 ++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/linux/btf.h b/include/linux/btf.h index cbd6e4096f8c..b7b791d1f3d6 100644 --- a/include/linux/btf.h +++ b/include/linux/btf.h @@ -188,6 +188,7 @@ u32 btf_obj_id(const struct btf *btf); bool btf_is_kernel(const struct btf *btf); bool btf_is_module(const struct btf *btf); struct module *btf_try_get_module(const struct btf *btf); +const char *btf_module_name(const struct btf *btf); u32 btf_nr_types(const struct btf *btf); bool btf_member_is_reg_int(const struct btf *btf, const struct btf_type *s, const struct btf_member *m, diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index c80bd8709e69..f78e8060efa6 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -7208,6 +7208,11 @@ bool btf_is_module(const struct btf *btf) return btf->kernel_btf && strcmp(btf->name, "vmlinux") != 0; } +const char *btf_module_name(const struct btf *btf) +{ + return btf->name; +} + enum { BTF_MODULE_F_LIVE = (1 << 0), }; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 1d51bd9596da..0c533db51f92 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -16483,7 +16483,10 @@ int bpf_check_attach_target(struct bpf_verifier_log *log, else addr = (long) tgt_prog->aux->func[subprog]->bpf_func; } else { - addr = kallsyms_lookup_name(tname); + if (btf_is_module(btf)) + addr = kallsyms_lookup_name_in_module(btf_module_name(btf), tname); + else + addr = kallsyms_lookup_name(tname); if (!addr) { bpf_log(log, "The address of function %s cannot be found\n", From patchwork Mon Dec 5 15:26:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viktor Malik X-Patchwork-Id: 13064685 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E4041C4332F for ; Mon, 5 Dec 2022 15:29:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232781AbiLEP3Y (ORCPT ); Mon, 5 Dec 2022 10:29:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59490 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232691AbiLEP3F (ORCPT ); Mon, 5 Dec 2022 10:29:05 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CD2031EAFC for ; Mon, 5 Dec 2022 07:26:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1670253993; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uKvjKCdmkZB6NQ/bdjjalHt9P1pJFFM/EqdFh8BTkbY=; b=Yf8bEIReKVn6O/sTik0nSjhRZytoRXVgT917y3swtcmn0uZTF/mLVrngvPhvHkf2kqVNm2 yBvpqV4se9sIuqDeeJhFDBlQybuMF6wYi9bceJ1UcVBWLmer4Jm6Gnqrqo394p+iqLlF/K DV4I84RQwLK4qqSo+zyZPL0W3N8FABE= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-221-Kwxs43jeO1SsU25OnBblNw-1; Mon, 05 Dec 2022 10:26:29 -0500 X-MC-Unique: Kwxs43jeO1SsU25OnBblNw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 4C4231C05149; Mon, 5 Dec 2022 15:26:27 +0000 (UTC) Received: from ovpn-193-115.brq.redhat.com (ovpn-193-115.brq.redhat.com [10.40.193.115]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 275E040C6EC3; Mon, 5 Dec 2022 15:26:24 +0000 (UTC) From: Viktor Malik To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Viktor Malik Subject: [PATCH bpf-next v3 3/3] bpf/selftests: Test fentry attachment to shadowed functions Date: Mon, 5 Dec 2022 16:26:06 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net Adds a new test that tries to attach a program to fentry of two functions of the same name, one located in vmlinux and the other in bpf_testmod. To avoid conflicts with existing tests, a new function "bpf_fentry_shadow_test" was created both in vmlinux and in bpf_testmod. The previous commit fixed a bug which caused this test to fail. The verifier would always use the vmlinux function's address as the target trampoline address, hence trying to attach two programs to the same trampoline. Signed-off-by: Viktor Malik --- net/bpf/test_run.c | 5 + .../selftests/bpf/bpf_testmod/bpf_testmod.c | 7 + .../bpf/prog_tests/module_attach_shadow.c | 124 ++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/module_attach_shadow.c diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index 6094ef7cffcd..71e36a85573b 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c @@ -536,6 +536,11 @@ int noinline bpf_modify_return_test(int a, int *b) return a + *b; } +int noinline bpf_fentry_shadow_test(int a) +{ + return a + 1; +} + u64 noinline bpf_kfunc_call_test1(struct sock *sk, u32 a, u64 b, u32 c, u64 d) { return a + b + c + d; diff --git a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c index 5085fea3cac5..d23127a5ec68 100644 --- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c +++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c @@ -229,6 +229,13 @@ static const struct btf_kfunc_id_set bpf_testmod_kfunc_set = { .set = &bpf_testmod_check_kfunc_ids, }; +noinline int bpf_fentry_shadow_test(int a) +{ + return a + 2; +} +EXPORT_SYMBOL_GPL(bpf_fentry_shadow_test); +ALLOW_ERROR_INJECTION(bpf_fentry_shadow_test, ERRNO); + extern int bpf_fentry_test1(int a); static int bpf_testmod_init(void) diff --git a/tools/testing/selftests/bpf/prog_tests/module_attach_shadow.c b/tools/testing/selftests/bpf/prog_tests/module_attach_shadow.c new file mode 100644 index 000000000000..bf511e61ec1f --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/module_attach_shadow.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2022 Red Hat */ +#include +#include +#include "bpf/libbpf_internal.h" +#include "cgroup_helpers.h" + +static const char *module_name = "bpf_testmod"; +static const char *symbol_name = "bpf_fentry_shadow_test"; + +int get_bpf_testmod_btf_fd(void) +{ + struct bpf_btf_info info; + char name[64]; + __u32 id = 0, len; + int err, fd; + + while (true) { + err = bpf_btf_get_next_id(id, &id); + if (err) { + log_err("failed to iterate BTF objects"); + return err; + } + + fd = bpf_btf_get_fd_by_id(id); + if (fd < 0) { + err = -errno; + log_err("failed to get FD for BTF object #%d", id); + return err; + } + + len = sizeof(info); + memset(&info, 0, sizeof(info)); + info.name = ptr_to_u64(name); + info.name_len = sizeof(name); + + err = bpf_obj_get_info_by_fd(fd, &info, &len); + if (err) { + err = -errno; + log_err("failed to get info for BTF object #%d", id); + close(fd); + return err; + } + + if (strcmp(name, module_name) == 0) + return fd; + + close(fd); + } + return -ENOENT; +} + +void test_module_fentry_shadow(void) +{ + struct btf *vmlinux_btf = NULL, *mod_btf = NULL; + int err, i; + int btf_fd[2] = {}; + int prog_fd[2] = {}; + int link_fd[2] = {}; + __s32 btf_id[2] = {}; + + const struct bpf_insn trace_program[] = { + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }; + + LIBBPF_OPTS(bpf_prog_load_opts, load_opts, + .expected_attach_type = BPF_TRACE_FENTRY, + ); + + LIBBPF_OPTS(bpf_test_run_opts, test_opts); + + vmlinux_btf = btf__load_vmlinux_btf(); + if (!ASSERT_OK_PTR(vmlinux_btf, "load_vmlinux_btf")) + return; + + btf_fd[1] = get_bpf_testmod_btf_fd(); + if (!ASSERT_GT(btf_fd[1], 0, "get_bpf_testmod_btf_fd")) + goto out; + + mod_btf = btf_get_from_fd(btf_fd[1], vmlinux_btf); + if (!ASSERT_OK_PTR(mod_btf, "btf_get_from_fd")) + goto out; + + btf_id[0] = btf__find_by_name_kind(vmlinux_btf, symbol_name, BTF_KIND_FUNC); + if (!ASSERT_GT(btf_id[0], 0, "btf_find_by_name")) + goto out; + + btf_id[1] = btf__find_by_name_kind(mod_btf, symbol_name, BTF_KIND_FUNC); + if (!ASSERT_GT(btf_id[1], 0, "btf_find_by_name")) + goto out; + + for (i = 0; i < 2; i++) { + load_opts.attach_btf_id = btf_id[i]; + load_opts.attach_btf_obj_fd = btf_fd[i]; + prog_fd[i] = bpf_prog_load(BPF_PROG_TYPE_TRACING, NULL, "GPL", + trace_program, + sizeof(trace_program) / sizeof(struct bpf_insn), + &load_opts); + if (!ASSERT_GE(prog_fd[i], 0, "bpf_prog_load")) + goto out; + + link_fd[i] = bpf_link_create(prog_fd[i], 0, BPF_TRACE_FENTRY, NULL); + if (!ASSERT_GE(link_fd[i], 0, "bpf_link_create")) + goto out; + } + + err = bpf_prog_test_run_opts(prog_fd[0], &test_opts); + ASSERT_OK(err, "running test"); + +out: + if (vmlinux_btf) + btf__free(vmlinux_btf); + if (mod_btf) + btf__free(mod_btf); + for (i = 0; i < 2; i++) { + if (btf_fd[i]) + close(btf_fd[i]); + if (prog_fd[i]) + close(prog_fd[i]); + if (link_fd[i]) + close(link_fd[i]); + } +}