From 1feb7d247dde05ca466a419c7b3a41979398f5b5 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 30 Jan 2026 17:32:55 -0600 Subject: [PATCH 1/7] .github/workflows/linuxkm.yml: in first scenario, remove --disable-opensslextra (i.e. retain opensslextra implicit to --enable-all), remove -DWOLFSSL_LINUXKM_VERBOSE_DEBUG, and use --enable-all-asm rather than --enable-intelasm --disable-sp-asm; in second secnario, add -DDEBUG_LINUXKM_PIE_SUPPORT. --- .github/workflows/linuxkm.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linuxkm.yml b/.github/workflows/linuxkm.yml index ad593a177c1..db2798dab80 100644 --- a/.github/workflows/linuxkm.yml +++ b/.github/workflows/linuxkm.yml @@ -17,8 +17,8 @@ jobs: strategy: matrix: config: [ - 'EXTRA_CPPFLAGS=-Werror --enable-option-checking=fatal --enable-linuxkm --enable-linuxkm-lkcapi-register=all --enable-all --enable-kyber=yes,original --enable-lms --enable-xmss --enable-dilithium --enable-experimental --enable-dual-alg-certs --disable-qt --disable-quic --with-sys-crypto-policy=no --disable-opensslextra --disable-testcert --enable-intelasm --disable-sp-asm --enable-crypttests --enable-linuxkm-benchmarks CFLAGS="-DWOLFSSL_LINUXKM_VERBOSE_DEBUG -Wframe-larger-than=2048 -Wstack-usage=4096 -DBENCH_EMBEDDED -DBENCH_MIN_RUNTIME_SEC=0.01 -DBENCH_NTIMES=1 -DBENCH_AGREETIMES=1" --with-max-rsa-bits=16384', - 'EXTRA_CPPFLAGS=-Werror --enable-option-checking=fatal --enable-linuxkm --enable-linuxkm-pie --enable-reproducible-build --enable-linuxkm-lkcapi-register=all --enable-all-crypto --enable-cryptonly --enable-kyber=yes,original --enable-lms --enable-xmss --enable-dilithium --enable-experimental --disable-qt --disable-quic --with-sys-crypto-policy=no --disable-opensslextra --disable-testcert --enable-intelasm --disable-sp-asm --enable-crypttests --enable-linuxkm-benchmarks CFLAGS="-DWOLFSSL_LINUXKM_VERBOSE_DEBUG -Wframe-larger-than=2048 -Wstack-usage=4096 -DBENCH_EMBEDDED -DBENCH_MIN_RUNTIME_SEC=0.01 -DBENCH_NTIMES=1 -DBENCH_AGREETIMES=1" --with-max-rsa-bits=16384' + 'EXTRA_CPPFLAGS=-Werror --enable-option-checking=fatal --enable-linuxkm --enable-linuxkm-lkcapi-register=all --enable-all --enable-kyber=yes,original --enable-lms --enable-xmss --enable-dilithium --enable-experimental --enable-dual-alg-certs --disable-qt --disable-quic --with-sys-crypto-policy=no --disable-testcert --enable-all-asm --enable-crypttests --enable-linuxkm-benchmarks CFLAGS="-Wframe-larger-than=2048 -Wstack-usage=4096 -DBENCH_EMBEDDED -DBENCH_MIN_RUNTIME_SEC=0.01 -DBENCH_NTIMES=1 -DBENCH_AGREETIMES=1" --with-max-rsa-bits=16384', + 'EXTRA_CPPFLAGS=-Werror --enable-option-checking=fatal --enable-linuxkm --enable-linuxkm-pie --enable-reproducible-build --enable-linuxkm-lkcapi-register=all --enable-all-crypto --enable-cryptonly --enable-kyber=yes,original --enable-lms --enable-xmss --enable-dilithium --enable-experimental --disable-qt --disable-quic --with-sys-crypto-policy=no --disable-opensslextra --disable-testcert --enable-intelasm --disable-sp-asm --enable-crypttests --enable-linuxkm-benchmarks CFLAGS="-DWOLFSSL_LINUXKM_VERBOSE_DEBUG -DDEBUG_LINUXKM_PIE_SUPPORT -Wframe-larger-than=2048 -Wstack-usage=4096 -DBENCH_EMBEDDED -DBENCH_MIN_RUNTIME_SEC=0.01 -DBENCH_NTIMES=1 -DBENCH_AGREETIMES=1" --with-max-rsa-bits=16384' ] name: build module if: github.repository_owner == 'wolfssl' From e48663248c22d17436b93f8f7069dad87a196ce1 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 30 Jan 2026 17:33:13 -0600 Subject: [PATCH 2/7] wolfssl/wolfcrypt/types.h: in setup for wc_static_assert, include assert.h if __STDC_VERSION__ or __cplusplus denotes presence, even if WOLFSSL_HAVE_ASSERT_H is unset. --- wolfssl/wolfcrypt/types.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index df1f82d2a86..6ba7f8466c3 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -2105,7 +2105,9 @@ WOLFSSL_API word32 CheckRunTimeSettings(void); #define wc_static_assert(expr) struct wc_static_assert_dummy_struct #define wc_static_assert2(expr, msg) wc_static_assert(expr) #elif !defined(wc_static_assert) - #if defined(WOLFSSL_HAVE_ASSERT_H) && !defined(WOLFSSL_NO_ASSERT_H) + #if !defined(WOLFSSL_NO_ASSERT_H) && (defined(WOLFSSL_HAVE_ASSERT_H) || \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (defined(__cplusplus) && (__cplusplus >= 201103L))) #include #endif #if (defined(__cplusplus) && (__cplusplus >= 201703L)) || \ From 8719df2666a3845d4ed6acd2a75e4e6b45d54a93 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 30 Jan 2026 17:33:30 -0600 Subject: [PATCH 3/7] wolfcrypt/src/aes.c: in wc_AesGcmSetKey(), don't VECTOR_REGISTERS_POP() until after GCM_generate_m0_*(). --- wolfcrypt/src/aes.c | 51 ++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 8dbbefb64dd..8abec2905fc 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -7460,37 +7460,40 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) * assure pure-C fallback is always usable. */ ret = wc_AesEncrypt(aes, iv, aes->gcm.H); - VECTOR_REGISTERS_POP; - } - if (ret == 0) { -#if defined(GCM_TABLE) || defined(GCM_TABLE_4BIT) -#if defined(WOLFSSL_AESNI) && defined(GCM_TABLE_4BIT) - if (aes->use_aesni) { - #if defined(WC_C_DYNAMIC_FALLBACK) - #ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_AVX2(intel_flags)) { - GCM_generate_m0_avx2(aes->gcm.H, (byte*)aes->gcm.M0); - } - else + + if (ret == 0) { + #if defined(GCM_TABLE) || defined(GCM_TABLE_4BIT) + #if defined(WOLFSSL_AESNI) && defined(GCM_TABLE_4BIT) + if (aes->use_aesni) { + #if defined(WC_C_DYNAMIC_FALLBACK) + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + GCM_generate_m0_avx2(aes->gcm.H, (byte*)aes->gcm.M0); + } + else + #endif + #if defined(HAVE_INTEL_AVX1) + if (IS_INTEL_AVX1(intel_flags)) { + GCM_generate_m0_avx1(aes->gcm.H, (byte*)aes->gcm.M0); + } + else + #endif + { + GCM_generate_m0_aesni(aes->gcm.H, (byte*)aes->gcm.M0); + } #endif - #if defined(HAVE_INTEL_AVX1) - if (IS_INTEL_AVX1(intel_flags)) { - GCM_generate_m0_avx1(aes->gcm.H, (byte*)aes->gcm.M0); } else - #endif + #endif { - GCM_generate_m0_aesni(aes->gcm.H, (byte*)aes->gcm.M0); + GenerateM0(&aes->gcm); } - #endif + #endif /* GCM_TABLE || GCM_TABLE_4BIT */ } - else -#endif - { - GenerateM0(&aes->gcm); - } -#endif /* GCM_TABLE || GCM_TABLE_4BIT */ + + VECTOR_REGISTERS_POP; } + #endif /* !FREESCALE_LTC_AES_GCM && !WOLFSSL_PSOC6_CRYPTO */ #endif From 0b91a0e91326c6e3ce8c323955b54a46809bc215 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 30 Jan 2026 17:34:02 -0600 Subject: [PATCH 4/7] linuxkm/linuxkm_wc_port.h, linuxkm/module_hooks.c, linuxkm/Makefile: refactor wc_linuxkm_normalize_relocations() and associated types and objects: * change wc_linuxkm_pie_reloc_tab from unsigned int[] to struct wc_linuxkm_pie_reloc_tab_ent[], with dest_segment and reloc_type members; * add enum wc_reloc_dest_segment and enum wc_reloc_type; * update GENERATE_RELOC_TAB recipe in Makefile to render the dest segment and reloc type; * add struct reloc_layout_ent, and reloc_layouts[] fully populated for x86 and ARM relocations; * refactor find_reloc_tab_offset() and wc_linuxkm_normalize_relocations() to reflect the above; linuxkm/module_hooks.c: tweak various printf format characters and arguments for compatibility with ARM32; linuxkm/linuxkm_wc_port.h: include linux/inet.h and define wc_linuxkm_inet_pton() and XINET_PTON(), unless WOLFCRYPT_ONLY. --- linuxkm/Makefile | 25 +- linuxkm/linuxkm_wc_port.h | 74 +++++- linuxkm/module_hooks.c | 511 +++++++++++++++++++++++++++----------- 3 files changed, 452 insertions(+), 158 deletions(-) diff --git a/linuxkm/Makefile b/linuxkm/Makefile index f8be02bdef8..6ce75e6e5e2 100644 --- a/linuxkm/Makefile +++ b/linuxkm/Makefile @@ -148,7 +148,7 @@ GENERATE_RELOC_TAB := $(AWK) ' \ bad_relocs=0; \ print "\#include "; \ printf("%s\n ", \ - "WOLFSSL_LOCAL const unsigned int wc_linuxkm_pie_reloc_tab[] = { "); \ + "WOLFSSL_LOCAL const struct wc_linuxkm_pie_reloc_tab_ent wc_linuxkm_pie_reloc_tab[] = { "); \ if ("SECTION_MAP" in ENVIRON) { \ while (getline 0) \ section_map[$$1] = $$2; \ @@ -177,36 +177,36 @@ GENERATE_RELOC_TAB := $(AWK) ' \ if (section) { \ switch (section) { \ case ".text_wolfcrypt": \ - section_tag = 0; \ + section_tag = "WC_R_SEG_TEXT"; \ break; \ case ".rodata_wolfcrypt": \ - section_tag = 1; \ + section_tag = "WC_R_SEG_RODATA"; \ break; \ case ".data_wolfcrypt": \ - section_tag = 2; \ + section_tag = "WC_R_SEG_RWDATA"; \ break; \ case ".bss_wolfcrypt": \ - section_tag = 3; \ + section_tag = "WC_R_SEG_BSS"; \ break; \ default: \ print "Unexpected section:\n" $$0 >"/dev/stderr"; \ ++bad_relocs; \ - section_tag = 4; \ + section_tag = "WC_R_SEG_OTHER"; \ } \ } else { \ print "Unresolvable symbol reference for relocation:\n" $$0 >"/dev/stderr";\ ++bad_relocs; \ - section_tag = 4; \ + section_tag = "WC_R_SEG_OTHER"; \ } \ + reloc_type = $$3; \ if (strtonum("0x" gensub("^0*","",1,$$1)) >= lshift(1, 29)) { \ print "Relocation offset overflow:" >"/dev/stderr"; \ print >"/dev/stderr"; \ exit(1); \ } \ - printf("0x%xU%s", \ - or(strtonum("0x" gensub("^0*","",1,$$1)), \ - lshift(section_tag, 29)), \ - ((++n%8) ? ", " : ",\n ")); \ + printf(" { .offset = 0x%xU, .dest_segment = %s, .reloc_type = WC_%s },\n", \ + strtonum("0x" gensub("^0*","",1,$$1)), \ + section_tag, reloc_type); \ } \ } \ END { \ @@ -214,7 +214,8 @@ GENERATE_RELOC_TAB := $(AWK) ' \ print "Found " bad_relocs " unresolvable relocations." >"/dev/stderr"; \ exit(1); \ } \ - print "~0U };\nWOLFSSL_LOCAL const unsigned long wc_linuxkm_pie_reloc_tab_length = sizeof wc_linuxkm_pie_reloc_tab / sizeof wc_linuxkm_pie_reloc_tab[0];";\ + print " { .offset = ~0U, .dest_segment = WC_R_SEG_NONE, .reloc_type = WC_R_NONE } };"; \ + print "WOLFSSL_LOCAL const unsigned long wc_linuxkm_pie_reloc_tab_length = sizeof wc_linuxkm_pie_reloc_tab / sizeof wc_linuxkm_pie_reloc_tab[0];"; \ }' ifeq "$(V)" "1" diff --git a/linuxkm/linuxkm_wc_port.h b/linuxkm/linuxkm_wc_port.h index bb9dd03a769..138c69d550a 100644 --- a/linuxkm/linuxkm_wc_port.h +++ b/linuxkm/linuxkm_wc_port.h @@ -483,6 +483,9 @@ #ifndef WC_CONTAINERIZE_THIS #include #include + #ifndef WOLFCRYPT_ONLY + #include + #endif #endif #include @@ -815,7 +818,52 @@ __wc_bss_start[], __wc_bss_end[]; - extern const unsigned int wc_linuxkm_pie_reloc_tab[]; + struct wc_linuxkm_pie_reloc_tab_ent { + unsigned int offset; + #define WC_RELOC_DEST_SEGMENT_BITS 3 + unsigned int dest_segment:WC_RELOC_DEST_SEGMENT_BITS; + #define WC_RELOC_TYPE_BITS 5 + unsigned int reloc_type:WC_RELOC_TYPE_BITS; + }; + + enum wc_reloc_dest_segment { + WC_R_SEG_NONE = 0, + WC_R_SEG_TEXT, + WC_R_SEG_RODATA, + WC_R_SEG_RWDATA, + WC_R_SEG_BSS, + WC_R_SEG_OTHER + }; + + enum wc_reloc_type { + WC_R_NONE = 0, + WC_R_X86_64_32, + WC_R_X86_64_32S, + WC_R_X86_64_64, + WC_R_X86_64_PC32, + WC_R_X86_64_PLT32, + WC_R_AARCH64_ABS32, + WC_R_AARCH64_ABS64, + WC_R_AARCH64_ADD_ABS_LO12_NC, + WC_R_AARCH64_ADR_PREL_PG_HI21, + WC_R_AARCH64_CALL26, + WC_R_AARCH64_JUMP26, + WC_R_AARCH64_LDST8_ABS_LO12_NC, + WC_R_AARCH64_LDST16_ABS_LO12_NC, + WC_R_AARCH64_LDST32_ABS_LO12_NC, + WC_R_AARCH64_LDST64_ABS_LO12_NC, + WC_R_AARCH64_PREL32, + WC_R_ARM_ABS32, + WC_R_ARM_PREL31, + WC_R_ARM_REL32, + WC_R_ARM_THM_CALL, + WC_R_ARM_THM_JUMP11, + WC_R_ARM_THM_JUMP24, + WC_R_ARM_THM_MOVT_ABS, + WC_R_ARM_THM_MOVW_ABS_NC + }; + + extern const struct wc_linuxkm_pie_reloc_tab_ent wc_linuxkm_pie_reloc_tab[]; extern const unsigned long wc_linuxkm_pie_reloc_tab_length; extern ssize_t wc_linuxkm_normalize_relocations( const u8 *text_in, @@ -1738,4 +1786,28 @@ #define WC_DUMP_BACKTRACE_NONDEBUG dump_stack() #endif +#if !defined(WOLFCRYPT_ONLY) && !defined(WC_CONTAINERIZE_THIS) +static inline int wc_linuxkm_inet_pton(int af, const char *src, void *dst) +{ + int ret; + + if (!src || !dst) + return -EFAULT; + + switch (af) { + case AF_INET: + ret = in4_pton(src, -1, (u8 *)dst, '\0', NULL); + return ret == 1 ? 1 : 0; + + case AF_INET6: + ret = in6_pton(src, -1, (u8 *)dst, '\0', NULL); + return ret == 1 ? 1 : 0; + + default: + return -EAFNOSUPPORT; + } +} +#define XINET_PTON(af, src, dst) wc_linuxkm_inet_pton(af, src, dst) +#endif /* !WOLFCRYPT_ONLY && !WC_CONTAINERIZE_THIS */ + #endif /* LINUXKM_WC_PORT_H */ diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index df7dad3201a..9a86835623f 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -459,6 +459,20 @@ static int wolfssl_init(void) { int ret; +#ifdef WC_LINUXKM_TEST_INET_PTON + { + const char *src; + byte dst[16] = { }; + int pton_ret; + src = "1.2.3.4"; + pton_ret = wc_linuxkm_inet_pton(AF_INET, src, dst); + printf("pton_ret=%d src=%s dst=%d.%d.%d.%d\n", pton_ret, src, (int)dst[0], (int)dst[1], (int)dst[2], (int)dst[3]); + src = "89ab::cdef"; + pton_ret = wc_linuxkm_inet_pton(AF_INET6, src, dst); + printf("pton_ret=%d src=%s dst=%02x%02x::%02x%02x\n", pton_ret, src, (int)dst[0], (int)dst[1], (int)dst[14], (int)dst[15]); + } +#endif /* WC_LINUXKM_TEST_INET_PTON */ + #ifdef HAVE_FIPS /* The compiled-in verifycore must be the right length, else the module * geometry will change when the correct value is passed in, destabilizing @@ -570,7 +584,7 @@ static int wolfssl_init(void) canon_buf, &cur_reloc_index); if (progress <= 0) { pr_err("ERROR: progress=%ld from WOLFSSL_TEXT_SEGMENT_CANONICALIZER() at offset %x (text=%x-%x).\n", - progress, + (long)progress, (unsigned)(uintptr_t)text_p, (unsigned)(uintptr_t)__wc_text_start, (unsigned)(uintptr_t)__wc_text_end); @@ -588,23 +602,23 @@ static int wolfssl_init(void) * the true module start address, which is potentially useful to an * attacker. */ - pr_info("wolfCrypt segment hashes (spans): text 0x%x (%lu), rodata 0x%x (%lu), offset %c0x%lx, canon text 0x%x\n", - text_hash, (uintptr_t)__wc_text_end - (uintptr_t)__wc_text_start, - rodata_hash, __wc_rodata_end - __wc_rodata_start, + pr_info("wolfCrypt segment hashes (spans): text 0x%x (%llu), rodata 0x%x (%llu), offset %c0x%llx, canon text 0x%x\n", + text_hash, (unsigned long long)((uintptr_t)__wc_text_end - (uintptr_t)__wc_text_start), + rodata_hash, (unsigned long long)((uintptr_t)__wc_rodata_end - (uintptr_t)__wc_rodata_start), (uintptr_t)__wc_text_start < (uintptr_t)&__wc_rodata_start[0] ? '+' : '-', - (uintptr_t)__wc_text_start < (uintptr_t)&__wc_rodata_start[0] ? (uintptr_t)&__wc_rodata_start[0] - (uintptr_t)__wc_text_start : (uintptr_t)__wc_text_start - (uintptr_t)&__wc_rodata_start[0], + (uintptr_t)__wc_text_start < (uintptr_t)&__wc_rodata_start[0] ? (unsigned long long)((uintptr_t)&__wc_rodata_start[0] - (uintptr_t)__wc_text_start) : (unsigned long long)((uintptr_t)__wc_text_start - (uintptr_t)&__wc_rodata_start[0]), stabilized_text_hash); - pr_info("wolfCrypt segments: text=%x-%x, rodata=%x-%x, " - "rwdata=%x-%x, bss=%x-%x\n", - (unsigned)(uintptr_t)__wc_text_start, - (unsigned)(uintptr_t)__wc_text_end, - (unsigned)(uintptr_t)__wc_rodata_start, - (unsigned)(uintptr_t)__wc_rodata_end, - (unsigned)(uintptr_t)__wc_rwdata_start, - (unsigned)(uintptr_t)__wc_rwdata_end, - (unsigned)(uintptr_t)__wc_bss_start, - (unsigned)(uintptr_t)__wc_bss_end); + pr_info("wolfCrypt segments: text=%llx-%llx, rodata=%llx-%llx, " + "rwdata=%llx-%llx, bss=%llx-%llx\n", + (unsigned long long)(uintptr_t)__wc_text_start, + (unsigned long long)(uintptr_t)__wc_text_end, + (unsigned long long)(uintptr_t)__wc_rodata_start, + (unsigned long long)(uintptr_t)__wc_rodata_end, + (unsigned long long)(uintptr_t)__wc_rwdata_start, + (unsigned long long)(uintptr_t)__wc_rwdata_end, + (unsigned long long)(uintptr_t)__wc_bss_start, + (unsigned long long)(uintptr_t)__wc_bss_end); pr_info("whole-segment relocation normalizations: text=%d, rodata=%d, rwdata=%d, bss=%d, other=%d\n", total_text_r, total_rodata_r, total_rwdata_r, total_bss_r, total_other_r); @@ -878,14 +892,41 @@ MODULE_VERSION(LIBWOLFSSL_VERSION_STRING); #ifdef WC_SYM_RELOC_TABLES -#define WC_TEXT_TAG (0x0 << 29) -#define WC_RODATA_TAG (0x1U << 29) -#define WC_RWDATA_TAG (0x2U << 29) -#define WC_BSS_TAG (0x3U << 29) -#define WC_OTHER_TAG (0x4U << 29) - -#define WC_RELOC_TAG_MASK (0x7U << 29) -#define WC_RELOC_OFFSET_MASK (~WC_RELOC_TAG_MASK) +static const struct reloc_layout_ent { + const char *name; + word64 mask; + word64 width; + word64 is_signed:1; + word64 is_relative:1; + word64 is_pages:1; + word64 is_pair_lo:1; + word64 is_pair_hi:1; +} reloc_layouts[] = { + [WC_R_X86_64_32] = { "R_X86_64_32", ~0UL, 32, .is_signed = 0, .is_relative = 0 }, + [WC_R_X86_64_32S] = { "R_X86_64_32S", ~0UL, 32, .is_signed = 1, .is_relative = 0 }, + [WC_R_X86_64_64] = { "R_X86_64_64", ~0UL, 64, .is_signed = 0, .is_relative = 0 }, + [WC_R_X86_64_PC32] = { "R_X86_64_PC32", ~0UL, 32, .is_signed = 1, .is_relative = 1 }, + [WC_R_X86_64_PLT32] = { "R_X86_64_PLT32", ~0UL, 32, .is_signed = 1, .is_relative = 1 }, + [WC_R_AARCH64_ABS32] = { "R_AARCH64_ABS32", ~0UL, 32, .is_signed = 1, .is_relative = 0, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 }, + [WC_R_AARCH64_ABS64] = { "R_AARCH64_ABS64", ~0UL, 64, .is_signed = 1, .is_relative = 0, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 }, + [WC_R_AARCH64_ADD_ABS_LO12_NC] = { "R_AARCH64_ADD_ABS_LO12_NC", 0b00000000001111111111110000000000, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 1, .is_pair_hi = 0 }, + [WC_R_AARCH64_ADR_PREL_PG_HI21] = { "R_AARCH64_ADR_PREL_PG_HI21", 0b01100000111111111111111111100000, 32, .is_signed = 1, .is_relative = 1, .is_pages = 1, .is_pair_lo = 0, .is_pair_hi = 1 }, + [WC_R_AARCH64_CALL26] = { "R_AARCH64_CALL26", 0b00000011111111111111111111111111, 32, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 }, + [WC_R_AARCH64_JUMP26] = { "R_AARCH64_JUMP26", 0b00000011111111111111111111111111, 32, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 }, + [WC_R_AARCH64_LDST8_ABS_LO12_NC] = { "R_AARCH64_LDST8_ABS_LO12_NC", 0b00000000001111111111110000000000, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 1, .is_pair_hi = 0 }, + [WC_R_AARCH64_LDST16_ABS_LO12_NC] = { "R_AARCH64_LDST16_ABS_LO12_NC", 0b00000000001111111111110000000000, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 1, .is_pair_hi = 0 }, + [WC_R_AARCH64_LDST32_ABS_LO12_NC] = { "R_AARCH64_LDST32_ABS_LO12_NC", 0b00000000001111111111110000000000, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 1, .is_pair_hi = 0 }, + [WC_R_AARCH64_LDST64_ABS_LO12_NC] = { "R_AARCH64_LDST64_ABS_LO12_NC", 0b00000000001111111111110000000000, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 1, .is_pair_hi = 0 }, + [WC_R_AARCH64_PREL32] = { "R_AARCH64_PREL32", ~0UL, 32, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 }, + [WC_R_ARM_ABS32] = { "R_ARM_ABS32", ~0UL, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 }, + [WC_R_ARM_PREL31] = { "R_ARM_PREL31", 0b01111111111111111111111111111111, 32, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 }, + [WC_R_ARM_REL32] = { "R_ARM_REL32", ~0UL, 32, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 }, + [WC_R_ARM_THM_CALL] = { "R_ARM_THM_CALL", 0b00000111111111110010111111111111, 32, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 }, + [WC_R_ARM_THM_JUMP24] = { "R_ARM_THM_JUMP24", 0b00000111111111110010111111111111, 32, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 }, + [WC_R_ARM_THM_JUMP11] = { "R_ARM_THM_JUMP11", 0b00000000000000000000011111111111, 16, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 }, + [WC_R_ARM_THM_MOVT_ABS] = { "R_ARM_THM_MOVT_ABS", 0b00000100000011110111000011111111, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 1 }, + [WC_R_ARM_THM_MOVW_ABS_NC] = { "R_ARM_THM_MOVW_ABS_NC", 0b00000100000011110111000011111111, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 1, .is_pair_hi = 0 } + }; static inline long find_reloc_tab_offset(size_t text_in_offset) { long ret; @@ -902,7 +943,7 @@ static inline long find_reloc_tab_offset(size_t text_in_offset) { #endif return -1; } - if (text_in_offset >= (size_t)(wc_linuxkm_pie_reloc_tab[wc_linuxkm_pie_reloc_tab_length - 1] & WC_RELOC_OFFSET_MASK)) { + if (text_in_offset >= (size_t)wc_linuxkm_pie_reloc_tab[wc_linuxkm_pie_reloc_tab_length - 1].offset) { #ifdef DEBUG_LINUXKM_PIE_SUPPORT pr_err("ERROR: %s failed at L %d.\n", __FUNCTION__, __LINE__); #endif @@ -913,20 +954,20 @@ static inline long find_reloc_tab_offset(size_t text_in_offset) { hop; hop >>= 1) { - if (text_in_offset == (size_t)(wc_linuxkm_pie_reloc_tab[ret] & WC_RELOC_OFFSET_MASK)) + if (text_in_offset == (size_t)wc_linuxkm_pie_reloc_tab[ret].offset) break; - else if (text_in_offset > (size_t)(wc_linuxkm_pie_reloc_tab[ret] & WC_RELOC_OFFSET_MASK)) + else if (text_in_offset > (size_t)wc_linuxkm_pie_reloc_tab[ret].offset) ret += hop; else if (ret) ret -= hop; } while ((ret < (long)wc_linuxkm_pie_reloc_tab_length - 1) && - ((size_t)(wc_linuxkm_pie_reloc_tab[ret] & WC_RELOC_OFFSET_MASK) < text_in_offset)) + ((size_t)wc_linuxkm_pie_reloc_tab[ret].offset < text_in_offset)) ++ret; while ((ret > 0) && - ((size_t)(wc_linuxkm_pie_reloc_tab[ret - 1] & WC_RELOC_OFFSET_MASK) >= text_in_offset)) + ((size_t)wc_linuxkm_pie_reloc_tab[ret - 1].offset >= text_in_offset)) --ret; #ifdef DEBUG_LINUXKM_PIE_SUPPORT @@ -950,9 +991,9 @@ ssize_t wc_linuxkm_normalize_relocations( { ssize_t i; size_t text_in_offset; - size_t last_reloc; /* for error-checking order in wc_linuxkm_pie_reloc_tab[] */ + const struct wc_linuxkm_pie_reloc_tab_ent *last_reloc; /* for error-checking order in wc_linuxkm_pie_reloc_tab[] */ #ifdef DEBUG_LINUXKM_PIE_SUPPORT - int n_text_r = 0, n_rodata_r = 0, n_rwdata_r = 0, n_bss_r = 0, n_other_r = 0; + int n_text_r = 0, n_rodata_r = 0, n_rwdata_r = 0, n_bss_r = 0, n_other_r = 0, n_oob_r = 0; #endif if ((text_in_len == 0) || @@ -960,12 +1001,12 @@ ssize_t wc_linuxkm_normalize_relocations( ((uintptr_t)(text_in + text_in_len) > (uintptr_t)__wc_text_end)) { #ifdef DEBUG_LINUXKM_PIE_SUPPORT - pr_err("ERROR: %s returning -1 at L %d with span %x-%x versus segment %x-%x.\n", + pr_err("ERROR: %s returning -1 at L %d with span %llx-%llx versus segment %llx-%llx.\n", __FUNCTION__, __LINE__, - (unsigned)(uintptr_t)text_in, - (unsigned)(uintptr_t)(text_in + text_in_len), - (unsigned)(uintptr_t)__wc_text_start, - (unsigned)(uintptr_t)__wc_text_end); + (unsigned long long)(uintptr_t)text_in, + (unsigned long long)(uintptr_t)(text_in + text_in_len), + (unsigned long long)(uintptr_t)__wc_text_start, + (unsigned long long)(uintptr_t)__wc_text_end); #endif return -1; } @@ -980,157 +1021,337 @@ ssize_t wc_linuxkm_normalize_relocations( if (i == -1) i = find_reloc_tab_offset(text_in_offset); - if (i < 0) { + if (i < 0) return i; - } WC_SANITIZE_DISABLE(); memcpy(text_out, text_in, text_in_len); WC_SANITIZE_ENABLE(); - for (last_reloc = wc_linuxkm_pie_reloc_tab[i > 0 ? i-1 : 0]; + for (last_reloc = &wc_linuxkm_pie_reloc_tab[i > 0 ? i-1 : 0]; (size_t)i < wc_linuxkm_pie_reloc_tab_length - 1; ++i) { - size_t next_reloc = wc_linuxkm_pie_reloc_tab[i]; - unsigned int reloc_tag; - int reloc_buf; + const struct wc_linuxkm_pie_reloc_tab_ent *next_reloc = &wc_linuxkm_pie_reloc_tab[i]; + enum wc_reloc_dest_segment dest_seg; + uintptr_t seg_beg; #ifdef DEBUG_LINUXKM_PIE_SUPPORT - uintptr_t abs_ptr; + uintptr_t seg_end; + const char *seg_name; #endif + word64 reloc_buf = 0; + const struct reloc_layout_ent *layout; + unsigned int next_reloc_rel; + + if (next_reloc->dest_segment == WC_R_SEG_NONE) { + pr_err("BUG: missing dest segment for relocation at wc_linuxkm_pie_reloc_tab[%zd]\n", i); + continue; + } - if ((last_reloc & WC_RELOC_OFFSET_MASK) > (next_reloc & WC_RELOC_OFFSET_MASK)) { - pr_err("BUG: out-of-order offset found at wc_linuxkm_pie_reloc_tab[%zd]: %zu > %zu\n", - i, last_reloc & WC_RELOC_OFFSET_MASK, next_reloc & WC_RELOC_OFFSET_MASK); + if (last_reloc->offset > next_reloc->offset) { + pr_err("BUG: out-of-order offset found at wc_linuxkm_pie_reloc_tab[%zd]: %u > %u\n", + i, last_reloc->offset, next_reloc->offset); return -1; } + last_reloc = next_reloc; - reloc_tag = next_reloc & WC_RELOC_TAG_MASK; - next_reloc &= WC_RELOC_OFFSET_MASK; - next_reloc -= text_in_offset; + if (next_reloc->reloc_type >= (sizeof reloc_layouts / sizeof reloc_layouts[0])) { + pr_err("BUG: unknown relocation type %u found at wc_linuxkm_pie_reloc_tab[%zd]\n", + next_reloc->reloc_type, i); + return -1; + } + + layout = &reloc_layouts[next_reloc->reloc_type]; - if (next_reloc >= text_in_len) { + switch (layout->width) { + case 32: + case 64: + case 16: + break; + default: + pr_err("BUG: unexpected relocation width %llu found at wc_linuxkm_pie_reloc_tab[%lld], reloc type %u\n", + (unsigned long long)layout->width, (long long)i, next_reloc->reloc_type); + return -1; + } + + /* provisionally assign the destination segment from the reloc record -- + * it may wind up getting overridden later if things don't go as + * expected. + */ + dest_seg = next_reloc->dest_segment; + + /* next_reloc_rel is the offset of the relocation relative to the start + * of the current text chunk (text_in). i.e., text_in + next_reloc_rel + * is the start of the relocation. + */ + next_reloc_rel = next_reloc->offset - text_in_offset; + + if (next_reloc_rel >= text_in_len) { /* no more relocations in this buffer. */ break; } - if (next_reloc > text_in_len - sizeof reloc_buf) { + + if (next_reloc_rel > text_in_len - layout->width) { /* relocation straddles buffer at end -- caller will try again with * that relocation at the start. */ - text_in_len = next_reloc; + text_in_len = next_reloc_rel; break; } - /* set reloc_buf to the relative address from the live text segment. */ - reloc_buf = (int)get_unaligned((int32_t *)&text_out[next_reloc]); - -#ifdef DEBUG_LINUXKM_PIE_SUPPORT - /* when debugging runtime segment consistency, for the various data - * segments, recognize dest addrs a few bytes outside the segment -- the - * compiler occasionally generates these, e.g. __wc_rwdata_start - 1 in - * DoInCoreCheck() in kernel 6.1 build of FIPS v5, __wc_bss_start - 4 in - * kernel 4.4, and __wc_rodata_end + 26 in kernel 6.18. - * - * abs_ptr is the absolute address referred to by the relocation. we - * need this in order to identify the target segment of the relocation, - * thereby allowing us to use the correct normalization tag and - * corrective offset for the relocation. - * - * start with the absolute address of the start of the current text - * segment span, add to that the offset of the relocation at issue, - * yielding the absolute address of the relocation, then add the - * contents of the relocation that we loaded above. - * - * the +4 accounts for the disp32 field size, as RIP points to the next - * instruction byte per the x86_64 ABI. + /* set reloc_buf to the address bits from the live text segment. on + * ARM, this will often also pull in some opcode bits, which we mask out. */ - #ifndef LINUXKM_PIE_DATA_SLOP_MARGIN - #define LINUXKM_PIE_DATA_SLOP_MARGIN 0x20 - #endif + if (layout->is_signed) { + /* Note, the intermediate cast to sword64 is necessary to + * sign-extend the value to 64 bits before unsigned + * reinterpretation. Normalization later relies on this. + */ + switch (layout->width) { + case 32: + reloc_buf = (word64)(sword64)(get_unaligned((sword32 *)&text_out[next_reloc_rel]) & (sword32)layout->mask); + break; + case 64: + reloc_buf = (word64)(sword64)(get_unaligned((sword64 *)&text_out[next_reloc_rel]) & (sword64)layout->mask); + break; + case 16: + reloc_buf = (word64)(sword64)(get_unaligned((sword16 *)&text_out[next_reloc_rel]) & (sword16)layout->mask); + break; + } + } + else { + switch (layout->width) { + case 32: + reloc_buf = (word64)(get_unaligned((word32 *)&text_out[next_reloc_rel]) & (word32)layout->mask); + break; + case 64: + reloc_buf = (word64)(get_unaligned((word64 *)&text_out[next_reloc_rel]) & layout->mask); + break; + case 16: + reloc_buf = (word64)(get_unaligned((word16 *)&text_out[next_reloc_rel]) & (word16)layout->mask); + break; + } + } - abs_ptr = (uintptr_t)text_in + next_reloc + 4 + reloc_buf; -#endif /* DEBUG_LINUXKM_PIE_SUPPORT */ + switch (dest_seg) { + case WC_R_SEG_TEXT: + seg_beg = (uintptr_t)__wc_text_start; + #ifdef DEBUG_LINUXKM_PIE_SUPPORT + seg_end = (uintptr_t)__wc_text_end; + seg_name = "text"; + ++n_text_r; + #endif + break; + case WC_R_SEG_RODATA: + seg_beg = (uintptr_t)__wc_rodata_start; + #ifdef DEBUG_LINUXKM_PIE_SUPPORT + seg_end = (uintptr_t)__wc_rodata_end; + seg_name = "rodata"; + ++n_rodata_r; + #endif + break; + case WC_R_SEG_RWDATA: + seg_beg = (uintptr_t)__wc_rwdata_start; + #ifdef DEBUG_LINUXKM_PIE_SUPPORT + seg_end = (uintptr_t)__wc_rwdata_end; + seg_name = "data"; + ++n_rwdata_r; + #endif + break; + case WC_R_SEG_BSS: + seg_beg = (uintptr_t)__wc_bss_start; + #ifdef DEBUG_LINUXKM_PIE_SUPPORT + seg_end = (uintptr_t)__wc_bss_end; + seg_name = "bss"; + ++n_bss_r; + #endif + break; + default: + case WC_R_SEG_NONE: + dest_seg = WC_R_SEG_OTHER; + FALL_THROUGH; + case WC_R_SEG_OTHER: + seg_beg = 0; + #ifdef DEBUG_LINUXKM_PIE_SUPPORT + seg_end = 0; + seg_name = "other"; + #endif + break; + } - switch (reloc_tag) { - case WC_TEXT_TAG: -#ifdef DEBUG_LINUXKM_PIE_SUPPORT - if ((abs_ptr >= (uintptr_t)__wc_text_start) && - (abs_ptr <= (uintptr_t)__wc_text_end)) - ++n_text_r; - else { - reloc_tag = WC_OTHER_TAG; +#ifdef CONFIG_X86 + { + switch (next_reloc->reloc_type) { + case WC_R_X86_64_PC32: + case WC_R_X86_64_PLT32: + case WC_R_X86_64_32: + case WC_R_X86_64_32S: + case WC_R_X86_64_64: break; + default: +#ifdef DEBUG_LINUXKM_PIE_SUPPORT + pr_notice("BUG: unexpected non-x86 relocation type %u in reloc record %zu, text offset 0x%x\n", + (unsigned)next_reloc->reloc_type, i, wc_linuxkm_pie_reloc_tab[i].offset); + ++n_oob_r; +#endif + dest_seg = WC_R_SEG_OTHER; } + + if (dest_seg != WC_R_SEG_OTHER) { +#ifdef DEBUG_LINUXKM_PIE_SUPPORT + word64 raw_dest_addr = reloc_buf; #endif - /* internal references in the .wolfcrypt.text segment don't need - * normalization. - */ - continue; - case WC_RODATA_TAG: + + if (layout->is_relative) { + /* the +(layout->width / 8) (i.e. 4) accounts for the disp32 + * field size, as RIP points to the next instruction byte + * per the x86_64 ABI. + */ + reloc_buf = reloc_buf + (uintptr_t)next_reloc->offset + ((uintptr_t)layout->width / 8UL) - (seg_beg - (uintptr_t)__wc_text_start); + } + else + reloc_buf -= seg_beg; + #ifdef DEBUG_LINUXKM_PIE_SUPPORT - if ((abs_ptr >= (uintptr_t)__wc_rodata_start - LINUXKM_PIE_DATA_SLOP_MARGIN) && - (abs_ptr <= (uintptr_t)__wc_rodata_end + LINUXKM_PIE_DATA_SLOP_MARGIN)) - ++n_rodata_r; - else - reloc_tag = WC_OTHER_TAG; -#endif - reloc_buf -= (int)((uintptr_t)__wc_rodata_start - 1 - - (uintptr_t)__wc_text_start); - reloc_buf ^= WC_RODATA_TAG; - break; - case WC_RWDATA_TAG: + /* For the various data segments, recognize dest addrs a few bytes + * outside the segment -- the compiler occasionally generates these, + * e.g. __wc_rwdata_start - 1 in DoInCoreCheck() in kernel 6.1 build + * of FIPS v5, __wc_bss_start - 4 in kernel 4.4, and __wc_rodata_end + * + 26 in kernel 6.18. + */ + #ifndef LINUXKM_PIE_DATA_SLOP_MARGIN + #define LINUXKM_PIE_DATA_SLOP_MARGIN 0x20 + #endif + + if ((dest_seg == WC_R_SEG_TEXT) ? + (reloc_buf > seg_end - seg_beg) : + (reloc_buf + LINUXKM_PIE_DATA_SLOP_MARGIN > (seg_end - seg_beg) + (LINUXKM_PIE_DATA_SLOP_MARGIN * 2))) + { + ++n_oob_r; + pr_notice("WARNING: normalized value is out of bounds (%s0x%lx) at index %ld, text offset 0x%x, reloc type %s, " + "dest seg .%s_wolfcrypt, offset from text to dest segment %s0x%lx, raw dest addr %s0x%lx, " + "seg span 0x%lx - 0x%lx, seg size 0x%lx, text base 0x%lx\n", + (sword64)reloc_buf < 0 ? "-" : "", + (sword64)reloc_buf < 0 ? -reloc_buf : reloc_buf, + i, + next_reloc->offset, + layout->name, + seg_name, + seg_beg < (uintptr_t)__wc_text_start ? "-" : "+", + seg_beg < (uintptr_t)__wc_text_start ? (word64)(uintptr_t)__wc_text_start - seg_beg : seg_beg - (word64)(uintptr_t)__wc_text_start, + (layout->is_signed && ((sword64)raw_dest_addr < 0)) ? "-" : "", + (layout->is_signed && ((sword64)raw_dest_addr < 0)) ? (word64)-(sword64)raw_dest_addr : raw_dest_addr, + (word64)seg_beg, + (word64)seg_end, + (word64)(seg_end - seg_beg), + (word64)(uintptr_t)__wc_text_start); + } +#endif + } + } /* end CONFIG_X86 */ + +#elif defined(CONFIG_ARM) + { + switch (next_reloc->reloc_type) { + case WC_R_ARM_ABS32: + case WC_R_ARM_PREL31: + case WC_R_ARM_REL32: + case WC_R_ARM_THM_CALL: + case WC_R_ARM_THM_JUMP11: + case WC_R_ARM_THM_JUMP24: + case WC_R_ARM_THM_MOVT_ABS: + case WC_R_ARM_THM_MOVW_ABS_NC: + break; + default: #ifdef DEBUG_LINUXKM_PIE_SUPPORT - if ((abs_ptr >= (uintptr_t)__wc_rwdata_start - LINUXKM_PIE_DATA_SLOP_MARGIN) && - (abs_ptr <= (uintptr_t)__wc_rwdata_end + LINUXKM_PIE_DATA_SLOP_MARGIN)) - ++n_rwdata_r; - else - reloc_tag = WC_OTHER_TAG; -#endif - reloc_buf -= (int)((uintptr_t)__wc_rwdata_start - 1 - - (uintptr_t)__wc_text_start); - reloc_buf ^= WC_RWDATA_TAG; - break; - case WC_BSS_TAG: + pr_notice("BUG: unexpected non-ARM32 relocation type %u in reloc record %u, text offset 0x%x\n", + (unsigned)next_reloc->reloc_type, i, wc_linuxkm_pie_reloc_tab[i].offset); + ++n_oob_r; +#endif + dest_seg = WC_R_SEG_OTHER; + } + + /* Don't attempt to reconstruct ARM destination addresses -- just + * normalize to zero. They can be reconstructed using the + * parameters in reloc_layouts[] but it's very fidgety. + */ + reloc_buf = 0; + } /* end CONFIG_ARM */ + +#elif defined(CONFIG_ARM64) + { + switch (next_reloc->reloc_type) { + case WC_R_AARCH64_ABS32: + case WC_R_AARCH64_ABS64: + case WC_R_AARCH64_ADD_ABS_LO12_NC: + case WC_R_AARCH64_ADR_PREL_PG_HI21: + case WC_R_AARCH64_CALL26: + case WC_R_AARCH64_JUMP26: + case WC_R_AARCH64_LDST16_ABS_LO12_NC: + case WC_R_AARCH64_LDST32_ABS_LO12_NC: + case WC_R_AARCH64_LDST64_ABS_LO12_NC: + case WC_R_AARCH64_LDST8_ABS_LO12_NC: + case WC_R_AARCH64_PREL32: + break; + default: #ifdef DEBUG_LINUXKM_PIE_SUPPORT - if ((abs_ptr >= (uintptr_t)__wc_bss_start - LINUXKM_PIE_DATA_SLOP_MARGIN) && - (abs_ptr <= (uintptr_t)__wc_bss_end + LINUXKM_PIE_DATA_SLOP_MARGIN)) - ++n_bss_r; - else - reloc_tag = WC_OTHER_TAG; -#endif - reloc_buf -= (int)((uintptr_t)__wc_bss_start - 1 - - (uintptr_t)__wc_text_start); - reloc_buf ^= WC_BSS_TAG; - break; - } - if (reloc_tag == WC_OTHER_TAG) { + pr_notice("BUG: unexpected non-ARM64 relocation type %u in reloc record %ld, text offset 0x%x\n", + (unsigned)next_reloc->reloc_type, i, wc_linuxkm_pie_reloc_tab[i].offset); + ++n_oob_r; +#endif + dest_seg = WC_R_SEG_OTHER; + } + + /* Don't attempt to reconstruct ARM destination addresses -- just + * normalize to zero. They can be reconstructed using the + * parameters in reloc_layouts[] but it's very fidgety. + */ + reloc_buf = 0; + } /* end CONFIG_ARM64 */ + +#else + + #warning Building WC_SYM_RELOC_TABLES without arch-specific handling. + + dest_seg = WC_R_SEG_OTHER; + reloc_buf = 0; + +#endif + + if (dest_seg == WC_R_SEG_OTHER) { /* relocation referring to non-wolfcrypt segment -- these can only * be stabilized by zeroing them. */ - reloc_buf = WC_OTHER_TAG; + reloc_buf = 0; + #ifdef DEBUG_LINUXKM_PIE_SUPPORT ++n_other_r; /* we're currently only handling 32 bit relocations (R_X86_64_PLT32 * and R_X86_64_PC32) so the top half of the word64 is padding we * can lop off for rendering. */ - pr_notice("found non-wolfcrypt relocation at text offset 0x%x to " - "addr 0x%x, text=%x-%x, rodata=%x-%x, " - "rwdata=%x-%x, bss=%x-%x\n", - wc_linuxkm_pie_reloc_tab[i] & WC_RELOC_OFFSET_MASK, - (unsigned)(uintptr_t)abs_ptr, - (unsigned)(uintptr_t)__wc_text_start, - (unsigned)(uintptr_t)__wc_text_end, - (unsigned)(uintptr_t)__wc_rodata_start, - (unsigned)(uintptr_t)__wc_rodata_end, - (unsigned)(uintptr_t)__wc_rwdata_start, - (unsigned)(uintptr_t)__wc_rwdata_end, - (unsigned)(uintptr_t)__wc_bss_start, - (unsigned)(uintptr_t)__wc_bss_end); + pr_notice("found non-wolfcrypt relocation at index %lld, text offset 0x%x.\n", + (long long)i, wc_linuxkm_pie_reloc_tab[i].offset); #endif } - put_unaligned((u32)reloc_buf, (int32_t *)&text_out[next_reloc]); + + /* xor in a label identifying the dest segment and reloc type. */ + reloc_buf ^= dest_seg << (layout->width - WC_RELOC_DEST_SEGMENT_BITS); + reloc_buf ^= next_reloc->reloc_type << (layout->width - (WC_RELOC_DEST_SEGMENT_BITS + WC_RELOC_TYPE_BITS)); + + /* write the modified reloc_buf to the destination buffer. */ + switch (layout->width) { + case 32: + put_unaligned((u32)reloc_buf, (u32 *)&text_out[next_reloc_rel]); + break; + case 64: + put_unaligned(reloc_buf, (u64 *)&text_out[next_reloc_rel]); + break; + case 16: + put_unaligned((u16)reloc_buf, (u16 *)&text_out[next_reloc_rel]); + break; + } } #ifdef DEBUG_LINUXKM_PIE_SUPPORT @@ -1140,11 +1361,11 @@ ssize_t wc_linuxkm_normalize_relocations( total_bss_r += n_bss_r; total_other_r += n_other_r; - if (n_other_r > 0) - pr_notice("text_in=%x relocs=%d/%d/%d/%d/%d ret = %zu\n", - (unsigned)(uintptr_t)text_in, n_text_r, n_rodata_r, - n_rwdata_r, n_bss_r, n_other_r, - text_in_len); + if ((n_other_r > 0) || (n_oob_r > 0)) + pr_notice("text_in=%llx relocs=%d/%d/%d/%d/%d/%d ret = %llu\n", + (unsigned long long)(uintptr_t)text_in, n_text_r, n_rodata_r, + n_rwdata_r, n_bss_r, n_other_r, n_oob_r, + (unsigned long long)text_in_len); #endif if (cur_index_p) From 6123febd3fe8ca2051d4a895360cc420cf909af0 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 30 Jan 2026 17:34:37 -0600 Subject: [PATCH 5/7] src/ssl_sk.c, src/x509.c, wolfssl/ssl.h: tweaks and fixes to from #9705: remove !WOLFSSL_LINUXKM gates, and fix nullPointerArithmeticRedundantCheck in ExtractHostFromUri(). --- src/ssl_sk.c | 3 +-- src/x509.c | 18 +++++++++--------- wolfssl/ssl.h | 4 ++-- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/ssl_sk.c b/src/ssl_sk.c index 2d1d374c28a..9696a820aa9 100644 --- a/src/ssl_sk.c +++ b/src/ssl_sk.c @@ -811,8 +811,7 @@ static wolfSSL_sk_freefunc wolfssl_sk_get_free_func(WOLF_STACK_TYPE type) func = (wolfSSL_sk_freefunc)wolfSSL_GENERAL_NAME_free; break; case STACK_TYPE_GENERAL_SUBTREE: - #if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) && \ - !defined(WOLFSSL_LINUXKM) + #if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) func = (wolfSSL_sk_freefunc)wolfSSL_GENERAL_SUBTREE_free; #endif break; diff --git a/src/x509.c b/src/x509.c index cec26ca24d9..291cd37ba2c 100644 --- a/src/x509.c +++ b/src/x509.c @@ -2218,8 +2218,7 @@ int wolfSSL_X509_get_ext_by_NID(const WOLFSSL_X509* x509, int nid, int lastPos) #endif /* OPENSSL_ALL || OPENSSL_EXTRA */ -#if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) && \ - !defined(WOLFSSL_LINUXKM) +#if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) /* * Convert a Base_entry linked list to a STACK of GENERAL_SUBTREE. * @@ -2370,7 +2369,7 @@ static int ConvertBaseEntryToSubtreeStack(Base_entry* list, WOLFSSL_STACK* sk, return 0; } -#endif /* OPENSSL_EXTRA && !IGNORE_NAME_CONSTRAINTS && !WOLFSSL_LINUXKM */ +#endif /* OPENSSL_EXTRA && !IGNORE_NAME_CONSTRAINTS */ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) /* Looks for the extension matching the passed in nid @@ -2874,8 +2873,7 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c, } break; - #if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) && \ - !defined(WOLFSSL_LINUXKM) + #if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) case NAME_CONS_OID: { WOLFSSL_NAME_CONSTRAINTS* nc = NULL; @@ -2937,7 +2935,7 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c, return nc; } - #endif /* OPENSSL_EXTRA && !IGNORE_NAME_CONSTRAINTS && !WOLFSSL_LINUXKM */ + #endif /* OPENSSL_EXTRA && !IGNORE_NAME_CONSTRAINTS */ case PRIV_KEY_USAGE_PERIOD_OID: WOLFSSL_MSG("Private Key Usage Period extension not supported"); @@ -5327,7 +5325,7 @@ void wolfSSL_EXTENDED_KEY_USAGE_free(WOLFSSL_STACK * sk) wolfSSL_sk_X509_pop_free(sk, NULL); } -#if !defined(IGNORE_NAME_CONSTRAINTS) && !defined(WOLFSSL_LINUXKM) +#if !defined(IGNORE_NAME_CONSTRAINTS) /* * Allocate and initialize an empty GENERAL_SUBTREE structure. * Returns NULL on allocation failure. @@ -5480,12 +5478,14 @@ static const char* ExtractHostFromUri(const char* uri, int uriLen, int* hostLen) const char* hostStart; const char* hostEnd; const char* p; - const char* uriEnd = uri + uriLen; + const char* uriEnd; if (uri == NULL || uriLen <= 0 || hostLen == NULL) { return NULL; } + uriEnd = uri + uriLen; + /* Find "://" to skip scheme */ hostStart = NULL; for (p = uri; p < uriEnd - 2; p++) { @@ -5692,7 +5692,7 @@ int wolfSSL_NAME_CONSTRAINTS_check_name(WOLFSSL_NAME_CONSTRAINTS* nc, return 1; } -#endif /* !IGNORE_NAME_CONSTRAINTS && !WOLFSSL_LINUXKM */ +#endif /* !IGNORE_NAME_CONSTRAINTS */ #if defined(OPENSSL_ALL) && !defined(NO_BIO) /* Outputs name string of the given WOLFSSL_GENERAL_NAME_OBJECT to WOLFSSL_BIO. diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index cf38c9e9d25..08989907c32 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1984,7 +1984,7 @@ WOLFSSL_API int wolfSSL_GENERAL_NAME_print(WOLFSSL_BIO* out, WOLFSSL_GENERAL_NAME* name); WOLFSSL_API void wolfSSL_EXTENDED_KEY_USAGE_free(WOLFSSL_STACK * sk); -#if !defined(IGNORE_NAME_CONSTRAINTS) && !defined(WOLFSSL_LINUXKM) +#if !defined(IGNORE_NAME_CONSTRAINTS) WOLFSSL_API WOLFSSL_NAME_CONSTRAINTS* wolfSSL_NAME_CONSTRAINTS_new(void); WOLFSSL_API void wolfSSL_NAME_CONSTRAINTS_free(WOLFSSL_NAME_CONSTRAINTS* nc); WOLFSSL_API int wolfSSL_NAME_CONSTRAINTS_check_name( @@ -1994,7 +1994,7 @@ WOLFSSL_API void wolfSSL_GENERAL_SUBTREE_free(WOLFSSL_GENERAL_SUBTREE* subtree); WOLFSSL_API int wolfSSL_sk_GENERAL_SUBTREE_num(const WOLFSSL_STACK* sk); WOLFSSL_API WOLFSSL_GENERAL_SUBTREE* wolfSSL_sk_GENERAL_SUBTREE_value( const WOLFSSL_STACK* sk, int idx); -#endif /* !IGNORE_NAME_CONSTRAINTS && !WOLFSSL_LINUXKM */ +#endif /* !IGNORE_NAME_CONSTRAINTS */ WOLFSSL_API WOLFSSL_DIST_POINT* wolfSSL_DIST_POINT_new(void); WOLFSSL_API void wolfSSL_DIST_POINT_free(WOLFSSL_DIST_POINT* dp); From 64bdcce08d0538f1259773ba4a94daa702cf2872 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 30 Jan 2026 22:35:31 -0600 Subject: [PATCH 6/7] linuxkm/linuxkm_wc_port.h: move implementation of wc_linuxkm_inet_pton() and definition of XINET_PTON() inside BUILDING_WOLFSSL guard. --- linuxkm/linuxkm_wc_port.h | 49 ++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/linuxkm/linuxkm_wc_port.h b/linuxkm/linuxkm_wc_port.h index 138c69d550a..00e7e45d3ef 100644 --- a/linuxkm/linuxkm_wc_port.h +++ b/linuxkm/linuxkm_wc_port.h @@ -485,8 +485,29 @@ #include #ifndef WOLFCRYPT_ONLY #include - #endif -#endif + static inline int wc_linuxkm_inet_pton(int af, const char *src, void *dst) + { + int ret; + + if (!src || !dst) + return -EFAULT; + + switch (af) { + case AF_INET: + ret = in4_pton(src, -1, (u8 *)dst, '\0', NULL); + return ret == 1 ? 1 : 0; + + case AF_INET6: + ret = in6_pton(src, -1, (u8 *)dst, '\0', NULL); + return ret == 1 ? 1 : 0; + + default: + return -EAFNOSUPPORT; + } + } + #define XINET_PTON(af, src, dst) wc_linuxkm_inet_pton(af, src, dst) + #endif /* !WOLFCRYPT_ONLY */ +#endif /* !WC_CONTAINERIZE_THIS */ #include #include @@ -1786,28 +1807,4 @@ #define WC_DUMP_BACKTRACE_NONDEBUG dump_stack() #endif -#if !defined(WOLFCRYPT_ONLY) && !defined(WC_CONTAINERIZE_THIS) -static inline int wc_linuxkm_inet_pton(int af, const char *src, void *dst) -{ - int ret; - - if (!src || !dst) - return -EFAULT; - - switch (af) { - case AF_INET: - ret = in4_pton(src, -1, (u8 *)dst, '\0', NULL); - return ret == 1 ? 1 : 0; - - case AF_INET6: - ret = in6_pton(src, -1, (u8 *)dst, '\0', NULL); - return ret == 1 ? 1 : 0; - - default: - return -EAFNOSUPPORT; - } -} -#define XINET_PTON(af, src, dst) wc_linuxkm_inet_pton(af, src, dst) -#endif /* !WOLFCRYPT_ONLY && !WC_CONTAINERIZE_THIS */ - #endif /* LINUXKM_WC_PORT_H */ From f2f9d5bbe7a1f2fae7fe189c8f78cd1636bac991 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 30 Jan 2026 22:38:44 -0600 Subject: [PATCH 7/7] src/internal.c: in SanityCheckMsgReceived(), gate "TLS 1.2 message order check: certificate before CKE" from 5b6f86bc8e on !WOLFSSL_NO_CLIENT_AUTH. --- src/internal.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/internal.c b/src/internal.c index ea3b3f5370a..74f59faff90 100644 --- a/src/internal.c +++ b/src/internal.c @@ -18083,12 +18083,14 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); return OUT_OF_ORDER_E; } +#ifndef WOLFSSL_NO_CLIENT_AUTH if (!ssl->options.resuming && ssl->options.verifyPeer && !ssl->options.usingPSK_cipher && !ssl->options.usingAnon_cipher && !ssl->msgsReceived.got_certificate) { return OUT_OF_ORDER_E; } +#endif if (ssl->msgsReceived.got_certificate_verify|| ssl->msgsReceived.got_change_cipher || ssl->msgsReceived.got_finished) {