lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <8BFF520DF61C1BB6+096017ae9362c21b090c1f3c97bbd0fdf305bd27.1760463245.git.tanyuan@tinylab.org>
Date: Wed, 15 Oct 2025 14:22:15 +0800
From: Yuan Tan <tanyuan@...ylab.org>
To: arnd@...db.de,
	masahiroy@...nel.org,
	nathan@...nel.org,
	palmer@...belt.com,
	linux-kbuild@...r.kernel.org,
	linux-riscv@...ts.infradead.org
Cc: linux-arch@...r.kernel.org,
	linux-kernel@...r.kernel.org,
	i@...kray.me,
	tanyuan@...ylab.org,
	falcon@...ylab.org,
	ronbogo@...look.com,
	z1652074432@...il.com,
	lx24@....ynu.edu.cn
Subject: [PATCH v2 7/8] vmlinux.lds.h: support conditional KEEP() in linker script

Introduce a conditional KEEP() helper, COND_KEEP(), that allows a
section to be kept only if a corresponding NOKEEP_<sec> macro is not
defined. This provides a finer-grained mechanism to control which
sections are protected from garbage collection.

Traditionally, many sections — for example, the exception table and jump
table — are created by .pushsection and wrapped with KEEP() in
vmlinux.lds.h to prevent them from being discarded by the linker, even when
they are not actually referenced. This can block dead code and data
elimination (DCE) when the section is known to be safe to drop.

With COND_KEEP(), architectures or subsystems can safely remove the KEEP()
in cases where the section can be safely garbage-collected.

The implementation adds:
  - __KEEP_ACT_0() / __KEEP_ACT_1() helpers for macro expansion
  - BSEC_MAIN() to handle possible sub-section patterns, such as
    __ex_table.18
  - COND_KEEP() macro, which wraps KEEP() conditionally based on
    __is_defined(NOKEEP_<sec>)

Example usage:

COND_KEEP(alternative, *(.alternative*))

Additionally, move the ___PASTE()/__PASTE() definitions in
include/linux/compiler_types.h out from under the '#ifndef __ASSEMBLY__'
guard so that they are visible to assembly.

No functional change unless NOKEEP_<sec> is defined.

Signed-off-by: Yuan Tan <tanyuan@...ylab.org>
Signed-off-by: Zhangjin Wu <falcon@...ylab.org>
Signed-off-by: Peihan Liu <ronbogo@...look.com>
---
 include/asm-generic/vmlinux.lds.h | 12 ++++++++++--
 include/linux/compiler_types.h    |  8 ++++----
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8a9a2e732a65..8bb411ace863 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -51,6 +51,7 @@
  */
 
 #include <asm-generic/codetag.lds.h>
+#include <linux/compiler_types.h>
 
 #ifndef LOAD_OFFSET
 #define LOAD_OFFSET 0
@@ -113,14 +114,21 @@ defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPELLER_CLANG)
 #define RODATA_MAIN .rodata .rodata.[0-9a-zA-Z_]* .rodata..L*
 #define BSS_MAIN .bss .bss.[0-9a-zA-Z_]* .bss..L* .bss..compoundliteral*
 #define SBSS_MAIN .sbss .sbss.[0-9a-zA-Z_]*
+#define BSEC_MAIN(sec) sec sec##.[0-9a-zA-Z_]*
 #else
 #define DATA_MAIN .data .data.rel .data.rel.local
 #define SDATA_MAIN .sdata
 #define RODATA_MAIN .rodata
 #define BSS_MAIN .bss
 #define SBSS_MAIN .sbss
+#define BSEC_MAIN(sec) sec
 #endif
 
+#define __KEEP_ACT_0(sec) KEEP(sec)
+#define __KEEP_ACT_1(sec) sec
+
+#define COND_KEEP(sec, list) __PASTE(__KEEP_ACT_, __is_defined(NOKEEP_##sec))(list)
+
 /*
  * GCC 4.5 and later have a 32 bytes section alignment for structures.
  * Except GCC 4.9, that feels the need to align on 64 bytes.
@@ -196,12 +204,12 @@ defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPELLER_CLANG)
 
 #define BOUNDED_SECTION_PRE_LABEL(_sec_, _label_, _BEGIN_, _END_)	\
 	_BEGIN_##_label_ = .;						\
-	KEEP(*(_sec_))							\
+	COND_KEEP(_sec_, *(BSEC_MAIN(_sec_)))				\
 	_END_##_label_ = .;
 
 #define BOUNDED_SECTION_POST_LABEL(_sec_, _label_, _BEGIN_, _END_)	\
 	_label_##_BEGIN_ = .;						\
-	KEEP(*(_sec_))							\
+	COND_KEEP(_sec_, *(BSEC_MAIN(_sec_)))				\
 	_label_##_END_ = .;
 
 #define BOUNDED_SECTION_BY(_sec_, _label_)				\
diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
index 59288a2c1ad2..680ba4afbe7d 100644
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -79,10 +79,6 @@ static inline void __chk_io_ptr(const volatile void __iomem *ptr) { }
 # define __builtin_warning(x, y...) (1)
 #endif /* __CHECKER__ */
 
-/* Indirect macros required for expanded argument pasting, eg. __LINE__. */
-#define ___PASTE(a,b) a##b
-#define __PASTE(a,b) ___PASTE(a,b)
-
 #ifdef __KERNEL__
 
 /* Attributes */
@@ -425,6 +421,10 @@ struct ftrace_likely_data {
 
 #endif /* __ASSEMBLY__ */
 
+/* Indirect macros required for expanded argument pasting, eg. __LINE__. */
+#define ___PASTE(a, b) a##b
+#define __PASTE(a, b) ___PASTE(a, b)
+
 /*
  * The below symbols may be defined for one or more, but not ALL, of the above
  * compilers. We don't consider that to be an error, so set them to nothing.
-- 
2.43.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ