mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2] x86/kcfi: Don't emit KCFI_REFERENCE() in modules
@ 2026-10-27 22:29 Ridge Lomont via B4 Relay
  2026-10-28 12:33 ` Peter Zijlstra
  0 siblings, 1 reply; 2+ messages in thread
From: Ridge Lomont via B4 Relay @ 2026-10-27 22:29 UTC (permalink / raw)
  To: x86, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
	Chris Li, Nick Desaulniers, Bill Wendling, Justin Stitt
  Cc: H. Peter Anvin, Peter Zijlstra, Nathan Chancellor, Sami Tolvanen,
	Kees Cook, llvm, linux-kernel, linux-sparse, Ridge Lomont

From: Ridge Lomont <cyridge@proton.me>

KCFI_REFERENCE() takes the address of a symbol so that the compiler
emits its __kcfi_typeid_ symbol, which the SYM_TYPED_FUNC_START()
assembly implementing it needs. It is used from arch/x86 headers for
__clear_pages_unrolled(), copy_page(), __memset() and __memmove(), and
all of that assembly is built into vmlinux.

Modules include the same headers, so with CONFIG_CFI=y every module
also gets an __ADDRESSABLE() reference to each of these symbols in
.discard.addressable. This serves no purpose there, and since
__clear_pages_unrolled() is EXPORT_SYMBOL_GPL, modpost now rejects any
GPL-incompatible module that includes <linux/mm.h>:

  ERROR: modpost: GPL-incompatible module repro.ko uses GPL-only
  symbol '__clear_pages_unrolled'

even though the module never uses the symbol. This makes OpenZFS
impossible to build against CFI kernels; its configure checks fail
in the same way and are misreported as CONFIG_DEBUG_LOCK_ALLOC.

scripts/module.lds.S does not help here: modpost checks <module>.o
before the final link, and even after it the discarded section only
loses its relocations, the undefined symbols stay in .symtab, where
the module loader resolves them with the same license check.

Only emit the reference when building vmlinux.

Tested on x86_64 with clang 23.1.3 and CONFIG_CFI=y, with both
CONFIG_LTO_CLANG_FULL=y (the configuration from the Fixes: commit) and
CONFIG_LTO_CLANG_THIN=y: vmlinux links without warnings and still contains
__kcfi_typeid___clear_pages_unrolled, __kcfi_typeid_copy_page,
__kcfi_typeid___memset and __kcfi_typeid___memmove. It boots in QEMU
with no CFI failures. A minimal module with MODULE_LICENSE("Proprietary")
including <linux/mm.h> fails modpost before this change and builds and
loads after it. OpenZFS builds against a CFI kernel with this change,
and its pool, encryption, checksum and send/recv operations run
without CFI failures, in QEMU and on a desktop with CFI enforcing.

Fixes: 9b041a4b66b3 ("x86/mm: Ensure clear_page() variants always have __kcfi_typeid_ symbols")
Link: https://github.com/openzfs/zfs/issues/18092
Assisted-by: LLM
Signed-off-by: Ridge Lomont <cyridge@proton.me>
Acked-by: Nathan Chancellor <nathan@kernel.org>
---
Notes for reviewers:

- The fix was found and written with an AI coding assistant (Claude
  Opus 5.5, Claude Code). It started from "CONFIG_CFI breaks
  OpenZFS"; the assistant traced that to the modpost failure,
  wrote this change, and ran the tests described in the changelog.
  I have reviewed it and take responsibility for it.
- An alternative would be wrapping the KCFI_REFERENCE() lines in
  arch/x86/include/asm/page_64.h in #ifndef MODULE, as suggested in
  the OpenZFS report; doing it in the macro covers all users.
- Only x86_64 was tested; it is the only architecture using
  KCFI_REFERENCE(). Tested with CONFIG_LTO_CLANG_FULL=y and
  CONFIG_LTO_CLANG_THIN=y on this tree and with LTO disabled on v7.3.
  In-tree modules were built but not loaded.
- checkpatch reports "Non-standard signature: Assisted-by:", which
  conflicts with Documentation/process/coding-assistants.rst.
---
Changes in v2:
- Sign off with my real name (Peter, Borislav).
- Explain in the changelog why module.lds.S discarding
  .discard.addressable does not help (Nathan).
- Also tested with CONFIG_LTO_CLANG_THIN=y.
- Add Nathan's Acked-by.
- Link to v1: https://patch.msgid.link/20261024-kcfi-reference-modules-v1-1-43c2a4a9e657@proton.me
---
 include/linux/compiler.h | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 0ea7150db..ea161a72d 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -258,10 +258,13 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
 
 #endif /* __KERNEL__ */
 
-#if defined(CONFIG_CFI) && !defined(__DISABLE_EXPORTS) && !defined(BUILD_VDSO)
+#if defined(CONFIG_CFI) && !defined(__DISABLE_EXPORTS) && !defined(BUILD_VDSO) && \
+	!defined(MODULE)
 /*
  * Force a reference to the external symbol so the compiler generates
- * __kcfi_typid.
+ * __kcfi_typid. Only vmlinux needs it, as that is where the assembly
+ * using the typeid lives; in a module it would only add a reference to
+ * the symbol, which fails modpost if the symbol is GPL-only.
  */
 #define KCFI_REFERENCE(sym) __ADDRESSABLE(sym)
 #else

---
base-commit: 6fba331225f5040e93d0947d1027e9712238291f
change-id: 20261024-kcfi-reference-modules-04c32004af41

Best regards,
--  
Ridge



^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] x86/kcfi: Don't emit KCFI_REFERENCE() in modules
  2026-10-27 22:29 [PATCH v2] x86/kcfi: Don't emit KCFI_REFERENCE() in modules Ridge Lomont via B4 Relay
@ 2026-10-28 12:33 ` Peter Zijlstra
  0 siblings, 0 replies; 2+ messages in thread
From: Peter Zijlstra @ 2026-10-28 12:33 UTC (permalink / raw)
  To: cyridge
  Cc: x86, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
	Chris Li, Nick Desaulniers, Bill Wendling, Justin Stitt,
	H. Peter Anvin, Nathan Chancellor, Sami Tolvanen, Kees Cook,
	llvm, linux-kernel, linux-sparse

On Tue, Oct 27, 2026 at 03:29:21PM -0700, Ridge Lomont via B4 Relay wrote:
> From: Ridge Lomont <cyridge@proton.me>
> 
> KCFI_REFERENCE() takes the address of a symbol so that the compiler
> emits its __kcfi_typeid_ symbol, which the SYM_TYPED_FUNC_START()
> assembly implementing it needs. It is used from arch/x86 headers for
> __clear_pages_unrolled(), copy_page(), __memset() and __memmove(), and
> all of that assembly is built into vmlinux.
> 
> Modules include the same headers, so with CONFIG_CFI=y every module
> also gets an __ADDRESSABLE() reference to each of these symbols in
> .discard.addressable. This serves no purpose there, and since
> __clear_pages_unrolled() is EXPORT_SYMBOL_GPL, modpost now rejects any
> GPL-incompatible module that includes <linux/mm.h>:
> 
>   ERROR: modpost: GPL-incompatible module repro.ko uses GPL-only
>   symbol '__clear_pages_unrolled'
> 
> even though the module never uses the symbol. This makes OpenZFS
> impossible to build against CFI kernels; its configure checks fail
> in the same way and are misreported as CONFIG_DEBUG_LOCK_ALLOC.
> 
> scripts/module.lds.S does not help here: modpost checks <module>.o
> before the final link, and even after it the discarded section only
> loses its relocations, the undefined symbols stay in .symtab, where
> the module loader resolves them with the same license check.
> 
> Only emit the reference when building vmlinux.
> 
> Tested on x86_64 with clang 23.1.3 and CONFIG_CFI=y, with both
> CONFIG_LTO_CLANG_FULL=y (the configuration from the Fixes: commit) and
> CONFIG_LTO_CLANG_THIN=y: vmlinux links without warnings and still contains
> __kcfi_typeid___clear_pages_unrolled, __kcfi_typeid_copy_page,
> __kcfi_typeid___memset and __kcfi_typeid___memmove. It boots in QEMU
> with no CFI failures. A minimal module with MODULE_LICENSE("Proprietary")
> including <linux/mm.h> fails modpost before this change and builds and
> loads after it. OpenZFS builds against a CFI kernel with this change,
> and its pool, encryption, checksum and send/recv operations run
> without CFI failures, in QEMU and on a desktop with CFI enforcing.
> 
> Fixes: 9b041a4b66b3 ("x86/mm: Ensure clear_page() variants always have __kcfi_typeid_ symbols")
> Link: https://github.com/openzfs/zfs/issues/18092
> Assisted-by: LLM
> Signed-off-by: Ridge Lomont <cyridge@proton.me>
> Acked-by: Nathan Chancellor <nathan@kernel.org>

Thanks!

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-28 12:33 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-27 22:29 [PATCH v2] x86/kcfi: Don't emit KCFI_REFERENCE() in modules Ridge Lomont via B4 Relay
2026-10-28 12:33 ` Peter Zijlstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®