linuxkm: fix Tegra Yocto FIPS build issues (ARM64, RT, PIE)

Fix multiple build and runtime issues when building wolfSSL LinuxKM FIPS
on NVIDIA Tegra (ARM64) kernels under Yocto.

- Disable ARM64 LSE atomics for out-of-tree modules to avoid jump_table
  asm constraints
- Handle PREEMPT_RT mutex and spinlock differences correctly
- Avoid alt_cb_patch_nops / queued_spin_lock_slowpath on Tegra
- Remove conflicting compiler auto-var-init flags for PIE objects
- Align PIE symbol redirection with RT and Tegra kernels

This restores successful LinuxKM FIPS builds on Tegra-based Yocto systems.

Signed-off-by: Sameeh Jubran <sameeh.j@gmail.com>
This commit is contained in:
Sameeh Jubran
2025-12-05 18:32:21 +02:00
parent 19cba1c462
commit a5f1fde955
5 changed files with 82 additions and 5 deletions

View File

@@ -145,7 +145,8 @@ ifeq "$(ENABLED_LINUXKM_PIE)" "yes"
endif
ccflags-y += $(PIE_SUPPORT_FLAGS)
$(WOLFCRYPT_PIE_FILES): ccflags-y += $(PIE_FLAGS)
$(WOLFCRYPT_PIE_FILES): ccflags-remove-y += -pg
$(WOLFCRYPT_PIE_FILES): ccflags-remove-y += -pg \
$(call cc-option,-ftrivial-auto-var-init=zero)
ifdef FORCE_GLOBAL_OBJTOOL_OFF
undefine CONFIG_OBJTOOL
endif

View File

@@ -24,6 +24,27 @@
#ifndef LINUXKM_WC_PORT_H
#define LINUXKM_WC_PORT_H
/*
* CRITICAL: Disable ARM64 LSE atomics for out-of-tree modules.
*
* When CONFIG_ARM64_LSE_ATOMICS is enabled, the kernel uses static keys
* (jump labels) in system_uses_lse_atomics() to choose between LSE and
* LL/SC atomic implementations at runtime. These static keys generate
* asm goto statements that reference .jump_table section symbols which
* cannot be resolved in out-of-tree modules, causing:
* "error: impossible constraint in 'asm'"
*
* By undefining CONFIG_ARM64_LSE_ATOMICS here (before any kernel headers
* that use atomics are included), we force use of the LL/SC fallback path
* which works correctly in out-of-tree modules.
*
* This must appear BEFORE #include <linux/version.h> because that header
* may transitively include headers that use atomics.
*/
#ifdef CONFIG_ARM64_LSE_ATOMICS
#undef CONFIG_ARM64_LSE_ATOMICS
#endif
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)
@@ -941,7 +962,15 @@
#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS */
typeof(__mutex_init) *__mutex_init;
#ifndef CONFIG_PREEMPT_RT
typeof(__mutex_init) *__mutex_init;
#else
typeof(__rt_mutex_init) *__rt_mutex_init;
typeof(rt_mutex_base_init) *rt_mutex_base_init;
typeof(rt_spin_lock) *rt_spin_lock;
typeof(rt_spin_unlock) *rt_spin_unlock;
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
typeof(mutex_lock_nested) *mutex_lock_nested;
#else
@@ -1048,6 +1077,7 @@
#endif
#ifdef CONFIG_ARM64
#ifndef CONFIG_ARCH_TEGRA
#ifdef WC_CONTAINERIZE_THIS
/* alt_cb_patch_nops and queued_spin_lock_slowpath are defined early
* to allow shimming in system headers, but now we need the native
@@ -1062,6 +1092,7 @@
typeof(queued_spin_lock_slowpath) *queued_spin_lock_slowpath;
#endif
#endif
#endif
typeof(preempt_count) *preempt_count;
#ifndef _raw_spin_lock_irqsave
@@ -1260,7 +1291,17 @@
#error WOLFSSL_USE_SAVE_VECTOR_REGISTERS is set for an unimplemented architecture.
#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS */
#define __mutex_init WC_PIE_INDIRECT_SYM(__mutex_init)
#ifndef CONFIG_PREEMPT_RT
#define __mutex_init WC_PIE_INDIRECT_SYM(__mutex_init)
#else
/* On RT kernels, __mutex_init is a macro pointing to __rt_mutex_init */
#undef __mutex_init
#define __rt_mutex_init WC_PIE_INDIRECT_SYM(__rt_mutex_init)
#define __mutex_init(mutex, name, key) __rt_mutex_init(mutex, name, key)
#define rt_mutex_base_init WC_PIE_INDIRECT_SYM(rt_mutex_base_init)
#define rt_spin_lock WC_PIE_INDIRECT_SYM(rt_spin_lock)
#define rt_spin_unlock WC_PIE_INDIRECT_SYM(rt_spin_unlock)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
#define mutex_lock_nested WC_PIE_INDIRECT_SYM(mutex_lock_nested)
#else
@@ -1327,8 +1368,31 @@
/* this is defined in linux/spinlock.h as an inline that calls the unshimmed
* raw_spin_unlock_irqrestore(). use a macro here to supersede it.
* Note: On PREEMPT_RT kernels, spinlock_t doesn't have rlock member,
* so we skip this redefinition and use the kernel's native implementation.
*/
#define spin_unlock_irqrestore(lock, flags) raw_spin_unlock_irqrestore(&((lock)->rlock), flags)
#ifndef CONFIG_PREEMPT_RT
#define spin_unlock_irqrestore(lock, flags) raw_spin_unlock_irqrestore(&((lock)->rlock), flags)
#else
/* Undo internal wolfSSL PIE macro rewriting */
#ifdef rt_spin_unlock
#undef rt_spin_unlock
#endif
#ifdef rt_spin_lock
#undef rt_spin_lock
#endif
static inline int wolfssl_spin_unlock_irqrestore_rt(spinlock_t *lock,
unsigned long flags)
{
(void)flags; /* rt_spin_unlock ignores flags */
WC_PIE_INDIRECT_SYM(rt_spin_unlock)(lock);
return 0;
}
#undef spin_unlock_irqrestore
#define spin_unlock_irqrestore(lock, flags) \
wolfssl_spin_unlock_irqrestore_rt((lock), (flags))
#endif
#define wc_linuxkm_sig_ignore_begin WC_PIE_INDIRECT_SYM(wc_linuxkm_sig_ignore_begin);
#define wc_linuxkm_sig_ignore_end WC_PIE_INDIRECT_SYM(wc_linuxkm_sig_ignore_end);

View File

@@ -1310,7 +1310,14 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) {
#error WOLFSSL_USE_SAVE_VECTOR_REGISTERS is set for an unsupported architecture.
#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS */
wolfssl_linuxkm_pie_redirect_table.__mutex_init = __mutex_init;
#ifndef CONFIG_PREEMPT_RT
wolfssl_linuxkm_pie_redirect_table.__mutex_init = __mutex_init;
#else
wolfssl_linuxkm_pie_redirect_table.__rt_mutex_init = __rt_mutex_init;
wolfssl_linuxkm_pie_redirect_table.rt_mutex_base_init = rt_mutex_base_init;
wolfssl_linuxkm_pie_redirect_table.rt_spin_lock = rt_spin_lock;
wolfssl_linuxkm_pie_redirect_table.rt_spin_unlock = rt_spin_unlock;
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
wolfssl_linuxkm_pie_redirect_table.mutex_lock_nested = mutex_lock_nested;
#else
@@ -1489,8 +1496,10 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) {
#endif
#ifdef CONFIG_ARM64
#ifndef CONFIG_ARCH_TEGRA
wolfssl_linuxkm_pie_redirect_table.alt_cb_patch_nops = alt_cb_patch_nops;
wolfssl_linuxkm_pie_redirect_table.queued_spin_lock_slowpath = queued_spin_lock_slowpath;
#endif
#endif
wolfssl_linuxkm_pie_redirect_table.wc_linuxkm_sig_ignore_begin = wc_linuxkm_sig_ignore_begin;