Skip to content

Commit

Permalink
kernel: 6.6: prevent garbage-cleanup of BPF kfuncs
Browse files Browse the repository at this point in the history
Backport an upstream Linux fix to prevent BPF kfunc functions from being
removed during linker optimization when building BTF-enabled vmlinux.

The telltale sign of this occurring is build log warnings (e.g. mips64el):

      BTFIDS  vmlinux
    WARN: resolve_btfids: unresolved symbol bpf_verify_pkcs7_signature
    WARN: resolve_btfids: unresolved symbol bpf_lookup_user_key
    WARN: resolve_btfids: unresolved symbol bpf_lookup_system_key
    WARN: resolve_btfids: unresolved symbol bpf_key_put
    WARN: resolve_btfids: unresolved symbol bpf_iter_task_next
    WARN: resolve_btfids: unresolved symbol bpf_iter_css_task_new
    WARN: resolve_btfids: unresolved symbol bpf_get_file_xattr
    WARN: resolve_btfids: unresolved symbol bpf_ct_insert_entry
      NM      System.map
      SORTTAB vmlinux

Link: https://lore.kernel.org/bpf/ZlkoM6%2FPSxVcGM6X@kodidev-ubuntu/
Signed-off-by: Tony Ambardar <itugrok@yahoo.com>
  • Loading branch information
guidosarducci committed Jun 11, 2024
1 parent 721943a commit 145ce80
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
From 443df175be581618d6ff781dc3af3aa1a9ba789d Mon Sep 17 00:00:00 2001
From: Tony Ambardar <Tony.Ambardar@gmail.com>
Date: Fri, 31 May 2024 23:55:55 -0700
Subject: [PATCH 1/2] compiler_types.h: Define __retain for
__attribute__((__retain__))

Some code includes the __used macro to prevent functions and data from
being optimized out. This macro implements __attribute__((__used__)), which
operates at the compiler and IR-level, and so still allows a linker to
remove objects intended to be kept.

Compilers supporting __attribute__((__retain__)) can address this gap by
setting the flag SHF_GNU_RETAIN on the section of a function/variable,
indicating to the linker the object should be retained. This attribute is
available since gcc 11, clang 13, and binutils 2.36.

Provide a __retain macro implementing __attribute__((__retain__)), whose
first user will be the '__bpf_kfunc' tag.

Link: https://lore.kernel.org/bpf/ZlmGoT9KiYLZd91S@krava/T/
Cc: stable@vger.kernel.org # v6.6+
Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>
---
include/linux/compiler_types.h | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
index 0a182f088c89..3894774e01d9 100644
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -145,6 +145,29 @@ static inline void __chk_io_ptr(const volatile void __iomem *ptr) { }
#define __has_builtin(x) (0)
#endif

+/*
+ * Annotating a function/variable with __retain tells the compiler to place
+ * the object in its own section and set the flag SHF_GNU_RETAIN. This flag
+ * instructs the linker to retain the object during garbage-cleanup or LTO
+ * phases.
+ *
+ * Note that the __used macro is also used to prevent functions or data
+ * being optimized out, but operates at the compiler/IR-level and may still
+ * allow unintended removal of objects during linking.
+ *
+ * Optional: only supported since gcc >= 11, clang >= 13
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-retain-function-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#retain
+ */
+#if __has_attribute(__retain__) && \
+ (defined(CONFIG_LD_DEAD_CODE_DATA_ELIMINATION) || \
+ defined(CONFIG_LTO_CLANG))
+# define __retain __attribute__((__retain__))
+#else
+# define __retain
+#endif
+
/* Compiler specific macros. */
#ifdef __clang__
#include <linux/compiler-clang.h>
--
2.34.1

Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
From ac507ed9882fd91a94657d68fe9ceac04b957103 Mon Sep 17 00:00:00 2001
From: Tony Ambardar <Tony.Ambardar@gmail.com>
Date: Sat, 1 Jun 2024 00:00:21 -0700
Subject: [PATCH 2/2] bpf: Harden __bpf_kfunc tag against linker kfunc removal

BPF kfuncs are often not directly referenced and may be inadvertently
removed by optimization steps during kernel builds, thus the __bpf_kfunc
tag mitigates against this removal by including the __used macro. However,
this macro alone does not prevent removal during linking, and may still
yield build warnings (e.g. on mips64el):

LD vmlinux
BTFIDS vmlinux
WARN: resolve_btfids: unresolved symbol bpf_verify_pkcs7_signature
WARN: resolve_btfids: unresolved symbol bpf_lookup_user_key
WARN: resolve_btfids: unresolved symbol bpf_lookup_system_key
WARN: resolve_btfids: unresolved symbol bpf_key_put
WARN: resolve_btfids: unresolved symbol bpf_iter_task_next
WARN: resolve_btfids: unresolved symbol bpf_iter_css_task_new
WARN: resolve_btfids: unresolved symbol bpf_get_file_xattr
WARN: resolve_btfids: unresolved symbol bpf_ct_insert_entry
WARN: resolve_btfids: unresolved symbol bpf_cgroup_release
WARN: resolve_btfids: unresolved symbol bpf_cgroup_from_id
WARN: resolve_btfids: unresolved symbol bpf_cgroup_acquire
WARN: resolve_btfids: unresolved symbol bpf_arena_free_pages
NM System.map
SORTTAB vmlinux
OBJCOPY vmlinux.32

Update the __bpf_kfunc tag to better guard against linker optimization by
including the new __retain compiler macro, which fixes the warnings above.

Verify the __retain macro with readelf by checking object flags for 'R':

$ readelf -Wa kernel/trace/bpf_trace.o
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
...
[178] .text.bpf_key_put PROGBITS 00000000 6420 0050 00 AXR 0 0 8
...
Key to Flags:
...
R (retain), D (mbind), p (processor specific)

Link: https://lore.kernel.org/bpf/ZlmGoT9KiYLZd91S@krava/T/
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/r/202401211357.OCX9yllM-lkp@intel.com/
Fixes: 57e7c169cd6a ("bpf: Add __bpf_kfunc tag for marking kernel functions as kfuncs")
Cc: stable@vger.kernel.org # v6.6+
Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>
---
include/linux/btf.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/btf.h b/include/linux/btf.h
index 928113a80a95..2835ecad9eba 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -81,7 +81,7 @@
* as to avoid issues such as the compiler inlining or eliding either a static
* kfunc, or a global kfunc in an LTO build.
*/
-#define __bpf_kfunc __used noinline
+#define __bpf_kfunc __used __retain noinline

/*
* Return the name of the passed struct, if exists, or halt the build if for
--
2.34.1

0 comments on commit 145ce80

Please sign in to comment.