From 00b65a9e0072a9be62590dfea82c887be5e936f2 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Thu, 16 Apr 2026 18:00:45 -0500 Subject: [PATCH 1/8] linuxkm/Kbuild: define NO_PIE_FLAG to 1, not empty, to satisfy gnu make criteria for ifdef. --- linuxkm/Kbuild | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linuxkm/Kbuild b/linuxkm/Kbuild index 17c9d4f1378..fe3f823942f 100644 --- a/linuxkm/Kbuild +++ b/linuxkm/Kbuild @@ -118,11 +118,11 @@ ifeq "$(ENABLED_LINUXKM_PIE)" "yes" ifndef NO_PIE_FLAG ifeq ($(KERNEL_ARCH),arm) ifeq ($(intcmp $(VERSION),5,1,0,0),1) - NO_PIE_FLAG := + NO_PIE_FLAG := 1 $(info Note: disabling -fPIE to avoid R_ARM_REL32 on pre-5.11 target kernel.) else ifeq ($(intcmp $(VERSION),5,0,1,0)-$(intcmp $(PATCHLEVEL),11,1,0,0),1-1) - NO_PIE_FLAG := + NO_PIE_FLAG := 1 $(info Note: disabling -fPIE to avoid R_ARM_REL32 on pre-5.11 target kernel.) endif endif From d218d3fbdd0169b209aae9aa74659c724c57acf8 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Thu, 16 Apr 2026 18:01:07 -0500 Subject: [PATCH 2/8] wolfcrypt/src/ge_operations.c and wolfssl/wolfcrypt/ge_operations.h: when ge_tobytes_nct and ge_tobytes have identical definitions, map the former to the latter using a macro and omit the latter definition, to avoid problematic R_ARM_THM_JUMP11 tail call. --- wolfcrypt/src/ge_operations.c | 10 +++------- wolfssl/wolfcrypt/ge_operations.h | 4 +++- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/wolfcrypt/src/ge_operations.c b/wolfcrypt/src/ge_operations.c index 3758552c155..7556594f4b8 100644 --- a/wolfcrypt/src/ge_operations.c +++ b/wolfcrypt/src/ge_operations.c @@ -10176,12 +10176,8 @@ void ge_tobytes(unsigned char *s,const ge_p2 *h) s[31] ^= (unsigned char)((unsigned char)fe_isnegative(x) << 7); } -#ifdef HAVE_ED25519_VERIFY -#ifndef CURVED25519_ASM_64BIT - #define fe_invert_nct fe_invert -#endif - -/* ge tobytes */ +#if defined(HAVE_ED25519_VERIFY) && defined(CURVED25519_ASM_64BIT) +/* ge tobytes_nct */ void ge_tobytes_nct(unsigned char *s,const ge_p2 *h) { ge recip; @@ -10194,7 +10190,7 @@ void ge_tobytes_nct(unsigned char *s,const ge_p2 *h) fe_tobytes(s,y); s[31] ^= (unsigned char)((unsigned char)fe_isnegative(x) << 7); } -#endif +#endif /* HAVE_ED25519_VERIFY && CURVED25519_ASM_64BIT */ #endif /* !ED25519_SMALL */ diff --git a/wolfssl/wolfcrypt/ge_operations.h b/wolfssl/wolfcrypt/ge_operations.h index 8496b959b1f..0a18a7ebbae 100644 --- a/wolfssl/wolfcrypt/ge_operations.h +++ b/wolfssl/wolfcrypt/ge_operations.h @@ -85,11 +85,13 @@ WOLFSSL_LOCAL void sc_reduce(byte* s); WOLFSSL_LOCAL void sc_muladd(byte* s, const byte* a, const byte* b, const byte* c); WOLFSSL_LOCAL void ge_tobytes(unsigned char *s,const ge_p2 *h); -#ifndef ED25519_SMALL +#ifdef HAVE_ED25519_VERIFY +#if !defined(ED25519_SMALL) && defined(CURVED25519_ASM_64BIT) WOLFSSL_LOCAL void ge_tobytes_nct(unsigned char *s,const ge_p2 *h); #else #define ge_tobytes_nct ge_tobytes #endif +#endif /* HAVE_ED25519_VERIFY */ #ifndef GE_P3_TOBYTES_IMPL #define ge_p3_tobytes(s, h) ge_tobytes((s), (const ge_p2 *)(h)) #else From 8b98f7f8eab20eb5ae001e55a3e4b26ff51740c4 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Thu, 16 Apr 2026 18:10:00 -0500 Subject: [PATCH 3/8] linuxkm/: refactor wc_reloc_table_segments.reloc_tab_* as wc_reloc_table_segments.text_reloc_tab.* (using the new struct wc_reloc_table_fenceposts and WC_RELOC_TABLE_FENCEPOSTS_INITIALIZER), and add wc_reloc_table_segments.rodata_reloc_tab (allocated but not yet implemented). --- linuxkm/Makefile | 4 +-- linuxkm/linuxkm-fips-hash-wrapper.sh | 8 ++--- linuxkm/linuxkm-fips-hash.c | 34 +++++++++--------- linuxkm/linuxkm_memory.c | 52 ++++++++++++++-------------- linuxkm/linuxkm_memory.h | 46 +++++++++++++++++------- linuxkm/module_hooks.c | 14 ++++---- 6 files changed, 89 insertions(+), 69 deletions(-) diff --git a/linuxkm/Makefile b/linuxkm/Makefile index b91d4c0b1bf..f28f0587387 100644 --- a/linuxkm/Makefile +++ b/linuxkm/Makefile @@ -163,7 +163,7 @@ GENERATE_RELOC_TAB := $(AWK) ' \ print "\#include "; \ print "\#include "; \ printf("%s\n ", \ - "WOLFSSL_LOCAL const struct wc_reloc_table_ent wc_linuxkm_pie_reloc_tab[] = { "); \ + "WOLFSSL_LOCAL const struct wc_reloc_table_ent wc_linuxkm_pie_text_reloc_tab[] = { "); \ if ("SECTION_MAP" in ENVIRON) { \ while (getline 0) \ section_map[$$1] = $$2; \ @@ -232,7 +232,7 @@ GENERATE_RELOC_TAB := $(AWK) ' \ exit(1); \ } \ print " { .offset = ~0U, .dest_offset = ~0U, .dest_addend = 0, .dest_segment = WC_R_SEG_NONE, .reloc_type = WC_R_NONE } };"; \ - print "WOLFSSL_LOCAL const unsigned int wc_linuxkm_pie_reloc_tab_length = (unsigned int)(sizeof wc_linuxkm_pie_reloc_tab / sizeof wc_linuxkm_pie_reloc_tab[0]);"; \ + print "WOLFSSL_LOCAL const unsigned int wc_linuxkm_pie_text_reloc_tab_length = (unsigned int)(sizeof wc_linuxkm_pie_text_reloc_tab / sizeof wc_linuxkm_pie_text_reloc_tab[0]);"; \ }' ifeq "$(V)" "1" diff --git a/linuxkm/linuxkm-fips-hash-wrapper.sh b/linuxkm/linuxkm-fips-hash-wrapper.sh index 57a2f02be04..9f68b82f615 100755 --- a/linuxkm/linuxkm-fips-hash-wrapper.sh +++ b/linuxkm/linuxkm-fips-hash-wrapper.sh @@ -48,15 +48,15 @@ fi # shellcheck disable=SC2016 # using $AWK instead of awk confuses shellcheck. readarray -t fenceposts < <(readelf --wide --sections --symbols "$mod_path" | "$AWK" ' BEGIN { - fips_fenceposts["wc_linuxkm_pie_reloc_tab"] = "reloc_tab_start"; - fips_fenceposts["wc_linuxkm_pie_reloc_tab_length"] = "reloc_tab_len_start"; + fips_fenceposts["wc_linuxkm_pie_text_reloc_tab"] = "text_reloc_tab.start"; + fips_fenceposts["wc_linuxkm_pie_text_reloc_tab_length"] = "text_reloc_tab.len_start"; fips_fenceposts["verifyCore"] = "verifyCore_start"; fips_fenceposts["wolfCrypt_FIPS_first"] = "fips_text_start"; fips_fenceposts["wolfCrypt_FIPS_last"] = "fips_text_end"; fips_fenceposts["wolfCrypt_FIPS_ro_start"] = "fips_rodata_start"; fips_fenceposts["wolfCrypt_FIPS_ro_end"] = "fips_rodata_end"; - singleton_ends["wc_linuxkm_pie_reloc_tab"] = "reloc_tab_end"; - singleton_ends["wc_linuxkm_pie_reloc_tab_length"] = "reloc_tab_len_end"; + singleton_ends["wc_linuxkm_pie_text_reloc_tab"] = "text_reloc_tab.end"; + singleton_ends["wc_linuxkm_pie_text_reloc_tab_length"] = "text_reloc_tab.len_end"; singleton_ends["verifyCore"] = "verifyCore_end"; } diff --git a/linuxkm/linuxkm-fips-hash.c b/linuxkm/linuxkm-fips-hash.c index fc53a1619fd..59719f51ace 100644 --- a/linuxkm/linuxkm-fips-hash.c +++ b/linuxkm/linuxkm-fips-hash.c @@ -104,10 +104,10 @@ int main(int argc, char **argv) .val = FENCEPOST_OPT_FLAG | offsetof(typeof(seg_map), x) } FENCEPOST_OPT(text_start), FENCEPOST_OPT(text_end), - FENCEPOST_OPT(reloc_tab_start), - FENCEPOST_OPT(reloc_tab_end), - FENCEPOST_OPT(reloc_tab_len_start), - FENCEPOST_OPT(reloc_tab_len_end), + FENCEPOST_OPT(text_reloc_tab.start), + FENCEPOST_OPT(text_reloc_tab.end), + FENCEPOST_OPT(text_reloc_tab.len_start), + FENCEPOST_OPT(text_reloc_tab.len_end), FENCEPOST_OPT(fips_text_start), FENCEPOST_OPT(fips_text_end), FENCEPOST_OPT(rodata_start), @@ -228,10 +228,10 @@ int main(int argc, char **argv) if ((seg_map.text_start == ~0UL) || (seg_map.text_end == ~0UL) || - (seg_map.reloc_tab_start == ~0UL) || - (seg_map.reloc_tab_end == ~0UL) || - (seg_map.reloc_tab_len_start == ~0UL) || - (seg_map.reloc_tab_len_end == ~0UL) || + (seg_map.text_reloc_tab.start == ~0UL) || + (seg_map.text_reloc_tab.end == ~0UL) || + (seg_map.text_reloc_tab.len_start == ~0UL) || + (seg_map.text_reloc_tab.len_end == ~0UL) || (seg_map.fips_text_start == ~0UL) || (seg_map.fips_text_end == ~0UL) || (seg_map.rodata_start == ~0UL) || @@ -267,12 +267,12 @@ int main(int argc, char **argv) exit(1); } - if ((seg_map.reloc_tab_start >= seg_map.reloc_tab_end) || - (seg_map.reloc_tab_end >= (unsigned long)st.st_size) || - (seg_map.reloc_tab_len_start >= seg_map.reloc_tab_len_end) || - (seg_map.reloc_tab_len_end >= (unsigned long)st.st_size)) + if ((seg_map.text_reloc_tab.start >= seg_map.text_reloc_tab.end) || + (seg_map.text_reloc_tab.end >= (unsigned long)st.st_size) || + (seg_map.text_reloc_tab.len_start >= seg_map.text_reloc_tab.len_end) || + (seg_map.text_reloc_tab.len_end >= (unsigned long)st.st_size)) { - fprintf(stderr, "%s: supplied reloc_tab fencepost(s) are out of bounds " + fprintf(stderr, "%s: supplied text_reloc_tab fencepost(s) are out of bounds " "for supplied module %s with length %lu.\n", progname, mod_path, (unsigned long)st.st_size); exit(1); @@ -291,10 +291,10 @@ int main(int argc, char **argv) seg_map.start = (unsigned long)mod_map; seg_map.end = (unsigned long)mod_map + st.st_size; - seg_map.reloc_tab_start += (unsigned long)mod_map; - seg_map.reloc_tab_end += (unsigned long)mod_map; - seg_map.reloc_tab_len_start += (unsigned long)mod_map; - seg_map.reloc_tab_len_end += (unsigned long)mod_map; + seg_map.text_reloc_tab.start += (unsigned long)mod_map; + seg_map.text_reloc_tab.end += (unsigned long)mod_map; + seg_map.text_reloc_tab.len_start += (unsigned long)mod_map; + seg_map.text_reloc_tab.len_end += (unsigned long)mod_map; seg_map.verifyCore_start += (unsigned long)mod_map; seg_map.verifyCore_end += (unsigned long)mod_map; diff --git a/linuxkm/linuxkm_memory.c b/linuxkm/linuxkm_memory.c index 3448cc6de8f..01f816a73b0 100644 --- a/linuxkm/linuxkm_memory.c +++ b/linuxkm/linuxkm_memory.c @@ -140,8 +140,8 @@ ssize_t wc_reloc_normalize_text( size_t text_in_offset; const struct wc_reloc_table_ent *last_reloc; /* for error-checking order in reloc_tab[] */ 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; - const struct wc_reloc_table_ent *reloc_tab = (const struct wc_reloc_table_ent *)seg_map->reloc_tab_start; - const word32 reloc_tab_len = *(const word32 *)seg_map->reloc_tab_len_start; + const struct wc_reloc_table_ent *reloc_tab = (const struct wc_reloc_table_ent *)seg_map->text_reloc_tab.start; + const word32 reloc_tab_len = *(const word32 *)seg_map->text_reloc_tab.len_start; if ((text_in_len == 0) || ((uintptr_t)text_in < seg_map->text_start) || @@ -553,16 +553,16 @@ int wc_fips_generate_hash( #if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT) if (seg_map->text_is_live) { - if ((seg_map->reloc_tab_start == 0) || - (seg_map->reloc_tab_len_start == 0)) + if ((seg_map->text_reloc_tab.start == 0) || + (seg_map->text_reloc_tab.len_start == 0)) { RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_FUNC_ARG; } } else { - if ((seg_map->reloc_tab_end == 0) || - (seg_map->reloc_tab_len_end == 0)) + if ((seg_map->text_reloc_tab.end == 0) || + (seg_map->text_reloc_tab.len_end == 0)) { RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_FUNC_ARG; @@ -575,8 +575,8 @@ int wc_fips_generate_hash( (seg_map->fips_rodata_start >= seg_map->fips_rodata_end) #if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT) || - ((seg_map->reloc_tab_end != 0) && (seg_map->reloc_tab_start >= seg_map->reloc_tab_end)) || - ((seg_map->reloc_tab_len_end != 0) && (seg_map->reloc_tab_len_start >= seg_map->reloc_tab_len_end)) || + ((seg_map->text_reloc_tab.end != 0) && (seg_map->text_reloc_tab.start >= seg_map->text_reloc_tab.end)) || + ((seg_map->text_reloc_tab.len_end != 0) && (seg_map->text_reloc_tab.len_start >= seg_map->text_reloc_tab.len_end)) || (seg_map->text_start >= seg_map->text_end) || (seg_map->rodata_start >= seg_map->rodata_end) || (seg_map->data_start >= seg_map->data_end) || @@ -594,8 +594,8 @@ int wc_fips_generate_hash( (seg_map->verifyCore_start < seg_map->start) #if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT) || - (seg_map->reloc_tab_start < seg_map->start) || - (seg_map->reloc_tab_len_start < seg_map->start) || + (seg_map->text_reloc_tab.start < seg_map->start) || + (seg_map->text_reloc_tab.len_start < seg_map->start) || (seg_map->text_start < seg_map->start) || (seg_map->rodata_start < seg_map->start) || (seg_map->data_start < seg_map->start) || @@ -614,10 +614,10 @@ int wc_fips_generate_hash( (seg_map->verifyCore_end > seg_map->end) #if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT) || - ((seg_map->reloc_tab_end != 0) && - (seg_map->reloc_tab_end > seg_map->end)) || - ((seg_map->reloc_tab_len_end != 0) && - (seg_map->reloc_tab_len_end > seg_map->end)) || + ((seg_map->text_reloc_tab.end != 0) && + (seg_map->text_reloc_tab.end > seg_map->end)) || + ((seg_map->text_reloc_tab.len_end != 0) && + (seg_map->text_reloc_tab.len_end > seg_map->end)) || (seg_map->text_end > seg_map->end) || (seg_map->rodata_end > seg_map->end) || (seg_map->data_end > seg_map->end) || @@ -631,15 +631,15 @@ int wc_fips_generate_hash( } #if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT) - if ((seg_map->reloc_tab_len_end != 0) && - (seg_map->reloc_tab_len_end - seg_map->reloc_tab_len_start != sizeof(word32))) + if ((seg_map->text_reloc_tab.len_end != 0) && + (seg_map->text_reloc_tab.len_end - seg_map->text_reloc_tab.len_start != sizeof(word32))) { RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_FUNC_ARG; } - else if (seg_map->reloc_tab_len_start & (sizeof(word32) - 1)) { - /* fprintf(stderr, "%s: seg_map->reloc_tab_len_start isn't properly aligned: 0x%llx.\n", progname, ( - unsigned long long)seg_map->reloc_tab_len_start); */ + else if (seg_map->text_reloc_tab.len_start & (sizeof(word32) - 1)) { + /* fprintf(stderr, "%s: seg_map->text_reloc_tab.len_start isn't properly aligned: 0x%llx.\n", progname, ( + unsigned long long)seg_map->text_reloc_tab.len_start); */ RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_ALIGN_E; } @@ -649,8 +649,8 @@ int wc_fips_generate_hash( * a nonsense byte-swapped value, or the final reloc_tab ent has * nonsense flags. */ - word32 reloc_tab_len = *(const word32 *)seg_map->reloc_tab_len_start; - const struct wc_reloc_table_ent *reloc_tab = (const struct wc_reloc_table_ent *)seg_map->reloc_tab_start; + word32 reloc_tab_len = *(const word32 *)seg_map->text_reloc_tab.len_start; + const struct wc_reloc_table_ent *reloc_tab = (const struct wc_reloc_table_ent *)seg_map->text_reloc_tab.start; if (reloc_tab_len == 0) { RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_FUNC_ARG; @@ -667,14 +667,14 @@ int wc_fips_generate_hash( RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_FUNC_ARG; } - else if ((seg_map->reloc_tab_end != 0) && - (seg_map->reloc_tab_end - seg_map->reloc_tab_start != sizeof(struct wc_reloc_table_ent) * *(const word32 *)seg_map->reloc_tab_len_start)) + else if ((seg_map->text_reloc_tab.end != 0) && + (seg_map->text_reloc_tab.end - seg_map->text_reloc_tab.start != sizeof(struct wc_reloc_table_ent) * *(const word32 *)seg_map->text_reloc_tab.len_start)) { /* - fprintf(stderr, "%s: wc_linuxkm_pie_reloc_tab_length from module (%u) is inconsistent with actual reloc_tab size %llu.\n", + fprintf(stderr, "%s: wc_linuxkm_pie_text_reloc_tab_length from module (%u) is inconsistent with actual text_reloc_tab size %llu.\n", progname, - *(const word32 *)seg_map->reloc_tab_len_start, - (unsigned long long)(seg_map->reloc_tab_end - seg_map->reloc_tab_start)); + *(const word32 *)seg_map->text_reloc_tab.len_start, + (unsigned long long)(seg_map->text_reloc_tab.end - seg_map->text_reloc_tab.start)); */ RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_FUNC_ARG; diff --git a/linuxkm/linuxkm_memory.h b/linuxkm/linuxkm_memory.h index 695a82aafae..c60a734b8e5 100644 --- a/linuxkm/linuxkm_memory.h +++ b/linuxkm/linuxkm_memory.h @@ -80,13 +80,25 @@ struct __attribute__((packed)) wc_reloc_table_ent { /* full ELF fencepost representation, to allow wc_reloc_normalize_text() */ +struct wc_reloc_table_fenceposts { + unsigned long start; + unsigned long end; + unsigned long len_start; + unsigned long len_end; +}; + +#define WC_RELOC_TABLE_FENCEPOSTS_INITIALIZER { \ + .start = ~0UL, \ + .end = ~0UL, \ + .len_start = ~0UL, \ + .len_end = ~0UL \ +} + struct wc_reloc_table_segments { unsigned long start; unsigned long end; - unsigned long reloc_tab_start; - unsigned long reloc_tab_end; - unsigned long reloc_tab_len_start; - unsigned long reloc_tab_len_end; + struct wc_reloc_table_fenceposts text_reloc_tab; + struct wc_reloc_table_fenceposts rodata_reloc_tab; unsigned long text_start; unsigned long text_end; #ifdef HAVE_FIPS @@ -113,10 +125,8 @@ struct wc_reloc_table_segments { #define WC_RELOC_TABLE_SEGMENTS_INITIALIZER { \ .start = ~0UL, \ .end = ~0UL, \ - .reloc_tab_start = ~0UL, \ - .reloc_tab_end = ~0UL, \ - .reloc_tab_len_start = ~0UL, \ - .reloc_tab_len_end = ~0UL, \ + .text_reloc_tab = WC_RELOC_TABLE_FENCEPOSTS_INITIALIZER, \ + .rodata_reloc_tab = WC_RELOC_TABLE_FENCEPOSTS_INITIALIZER, \ .text_start = ~0UL, \ .text_end = ~0UL, \ .fips_text_start = ~0UL, \ @@ -139,10 +149,8 @@ struct wc_reloc_table_segments { #define WC_RELOC_TABLE_SEGMENTS_INITIALIZER { \ .start = ~0UL, \ .end = ~0UL, \ - .reloc_tab_start = ~0UL, \ - .reloc_tab_end = ~0UL, \ - .reloc_tab_len_start = ~0UL, \ - .reloc_tab_len_end = ~0UL, \ + .text_reloc_tab = WC_RELOC_TABLE_FENCEPOSTS_INITIALIZER, \ + .rodata_reloc_tab = WC_RELOC_TABLE_FENCEPOSTS_INITIALIZER, \ .text_start = ~0UL, \ .text_end = ~0UL, \ .rodata_start = ~0UL, \ @@ -200,8 +208,12 @@ struct wc_reloc_counts { #if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT) +#ifndef WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ + #define WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ 8192 +#endif + #ifndef WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ - #define WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ 8192 + #define WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ #endif WOLFSSL_API ssize_t wc_reloc_normalize_text( @@ -212,6 +224,14 @@ WOLFSSL_API ssize_t wc_reloc_normalize_text( const struct wc_reloc_table_segments *seg_map, struct wc_reloc_counts *reloc_counts); +WOLFSSL_API ssize_t wc_reloc_normalize_rodata( + const byte *rodata_in, + size_t rodata_in_len, + byte *rodata_out, + ssize_t *cur_index_p, + const struct wc_reloc_table_segments *seg_map, + struct wc_reloc_counts *reloc_counts); + #endif /* WC_SYM_RELOC_TABLES || WC_SYM_RELOC_TABLES_SUPPORT */ #ifdef HAVE_FIPS diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index 90fc3123b22..90a695aa453 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -621,7 +621,7 @@ static int wolfssl_init(void) #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 - * wc_linuxkm_pie_reloc_tab. It also must be the right length for the + * wc_linuxkm_pie_text_reloc_tab. It also must be the right length for the * module-update-fips-hash recipe (in-place overwrite) to work, and for * updateFipsHash() (WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE) to be safe from * overruns. @@ -1118,17 +1118,17 @@ MODULE_VERSION(LIBWOLFSSL_VERSION_STRING); #ifdef WC_SYM_RELOC_TABLES -extern const struct wc_reloc_table_ent wc_linuxkm_pie_reloc_tab[]; -extern const unsigned int wc_linuxkm_pie_reloc_tab_length; +extern const struct wc_reloc_table_ent wc_linuxkm_pie_text_reloc_tab[]; +extern const unsigned int wc_linuxkm_pie_text_reloc_tab_length; static const struct wc_reloc_table_segments seg_map = { .start = 0, .end = 0, .text_start = (size_t)(uintptr_t)__wc_text_start, .text_end = (size_t)(uintptr_t)__wc_text_end, - .reloc_tab_start = (size_t)(uintptr_t)wc_linuxkm_pie_reloc_tab, - .reloc_tab_end = 0, - .reloc_tab_len_start = (size_t)(uintptr_t)&wc_linuxkm_pie_reloc_tab_length, - .reloc_tab_len_end = 0, + .text_reloc_tab.start = (size_t)(uintptr_t)wc_linuxkm_pie_text_reloc_tab, + .text_reloc_tab.end = 0, + .text_reloc_tab.len_start = (size_t)(uintptr_t)&wc_linuxkm_pie_text_reloc_tab_length, + .text_reloc_tab.len_end = 0, #ifdef HAVE_FIPS #ifdef WC_USE_PIE_FENCEPOSTS_FOR_FIPS .fips_text_start = (size_t)(uintptr_t)__wc_text_start, From 29c5b02046fcd6f1489e4a6448dd80a4bde414ce Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Tue, 28 Apr 2026 12:57:27 -0500 Subject: [PATCH 4/8] linuxkm/: finish support for stabilization of .rodata_wolfcrypt segment in WC_SYM_RELOC_TABLES (FIPS) kernel module builds: linuxkm/Makefile: update the GENERATE_RELOC_TAB recipe to generate both wc_linuxkm_pie_text_reloc_tab[] and wc_linuxkm_pie_rodata_reloc_tab. linuxkm/linuxkm-fips-hash-wrapper.sh: add handling for wc_linuxkm_pie_rodata_reloc_tab. linuxkm/linuxkm-fips-hash.c: add handling for rodata_reloc_tab.*. linuxkm/linuxkm_memory.c: * refactor find_reloc_tab_offset() to be segment-agnostic and tolerate empty reloc tabs. * refactor wc_reloc_normalize_segment(): * to be segment-agnostic, * identify the src segment dynamically, * return BAD_FUNC_ARG where previously returning literal -1, * use seg_in_out_len arg to accommodate size skew between input and output (not currently used), and * rename working vars for better mnemonicitude. * update wc_fips_generate_hash() to * handle seg_map->rodata_reloc_tab, * use new calling convention for wc_reloc_normalize_segment(), and * add wc_reloc_normalize_segment() loop for .rodata_wolfcrypt. linuxkm/linuxkm_memory.h and linuxkm/linuxkm_wc_port.h: rename WOLFSSL_TEXT_SEGMENT_CANONICALIZER* to WOLFSSL_SEGMENT_CANONICALIZER*, with backward-compat provisions. linuxkm/module_hooks.c: * add wc_linuxkm_normalize_relocations_noresize() backward-compat wrapper. * wolfssl_init(): add .rodata_wolfcrypt relocation handling alongside existing .text_wolfcrypt handling, and update for new wc_reloc_normalize_segment() calling convention. * add seg_map.rodata_reloc_tab initialization. * update wc_linuxkm_normalize_relocations() to be segment-agnostic and use new wc_reloc_normalize_segment() calling convention. --- linuxkm/Makefile | 57 +++-- linuxkm/linuxkm-fips-hash-wrapper.sh | 4 + linuxkm/linuxkm-fips-hash.c | 24 ++ linuxkm/linuxkm_memory.c | 349 +++++++++++++++++++-------- linuxkm/linuxkm_memory.h | 18 +- linuxkm/linuxkm_wc_port.h | 31 ++- linuxkm/module_hooks.c | 77 +++++- 7 files changed, 412 insertions(+), 148 deletions(-) diff --git a/linuxkm/Makefile b/linuxkm/Makefile index f28f0587387..0c1cdfaa110 100644 --- a/linuxkm/Makefile +++ b/linuxkm/Makefile @@ -157,30 +157,48 @@ GENERATE_SECTION_MAP := $(AWK) 'BEGIN { printf("") >ENVIRON["SECTION_MAP"]; } \ }' GENERATE_RELOC_TAB := $(AWK) ' \ - BEGIN { \ - n=0; \ + function open_seg(seg) { \ + seen_seg[seg] = 1; \ + printf("%s\n ", \ + "WOLFSSL_LOCAL const struct wc_reloc_table_ent wc_linuxkm_pie_" seg "_reloc_tab[] = { "); \ + cur_seg = seg; \ + } \ + function close_cur_seg() { \ + print " { .offset = ~0U, .dest_offset = ~0U, .dest_addend = 0, .dest_segment = WC_R_SEG_NONE, .reloc_type = WC_R_NONE } };"; \ + print "WOLFSSL_LOCAL const unsigned int wc_linuxkm_pie_" cur_seg "_reloc_tab_length = (unsigned int)(sizeof wc_linuxkm_pie_" cur_seg "_reloc_tab / sizeof wc_linuxkm_pie_" cur_seg "_reloc_tab[0]);"; \ + cur_seg = ""; \ + } \ + BEGIN { \ bad_relocs=0; \ print "\#include "; \ print "\#include "; \ - printf("%s\n ", \ - "WOLFSSL_LOCAL const struct wc_reloc_table_ent wc_linuxkm_pie_text_reloc_tab[] = { "); \ + print ""; \ if ("SECTION_MAP" in ENVIRON) { \ while (getline 0) \ section_map[$$1] = $$2; \ close(ENVIRON["SECTION_MAP"]); \ } \ } \ - /^Relocation section '\''\.rela?\.text_wolfcrypt'\''/ { \ - p=1; \ - next; \ - } \ + \ /^Relocation section/ { \ - p=0; \ + if (cur_seg) { \ + close_cur_seg(); \ + } \ + { \ + if (match($$0, "^Relocation section '\''\\.rela?\\.(text|rodata)_wolfcrypt'\''", a)) {\ + open_seg(a[1]); \ + next; \ + } \ + } \ + } \ + \ + { \ + if (! cur_seg) \ + next; \ } \ /^0/ { \ - if (p) { \ - if ($$3 !~ "^(R_X86_64_PLT32|R_X86_64_PC32|R_AARCH64_.*|R_ARM.*)$$") { \ - print "Unexpected relocation type:\n" $$0 >"/dev/stderr"; \ + if ($$3 !~ "^(R_X86_.*|R_AARCH64_.*|R_ARM.*)$$") { \ + print "Unexpected relocation type in " cur_seg ":\n" $$0 >"/dev/stderr"; \ ++bad_relocs; \ } \ if ($$5 in section_map) \ @@ -224,15 +242,22 @@ GENERATE_RELOC_TAB := $(AWK) ' \ strtonum("0x" $$4), \ $$6 strtonum("0x" $$7), \ section_tag, reloc_type); \ - } \ } \ END { \ + if (cur_seg) { \ + close_cur_seg(); \ + } \ + n = split("text rodata", segs, " "); \ + for (i = 1; i <= n; ++i) { \ + if (! (segs[i] in seen_seg)) { \ + open_seg(segs[i]); \ + close_cur_seg(); \ + } \ + } \ if (bad_relocs) { \ print "Found " bad_relocs " unresolvable relocations." >"/dev/stderr"; \ exit(1); \ } \ - print " { .offset = ~0U, .dest_offset = ~0U, .dest_addend = 0, .dest_segment = WC_R_SEG_NONE, .reloc_type = WC_R_NONE } };"; \ - print "WOLFSSL_LOCAL const unsigned int wc_linuxkm_pie_text_reloc_tab_length = (unsigned int)(sizeof wc_linuxkm_pie_text_reloc_tab / sizeof wc_linuxkm_pie_text_reloc_tab[0]);"; \ }' ifeq "$(V)" "1" @@ -384,7 +409,7 @@ $(MODULE_TOP)/libwolfssl-user-build/src/.libs/libwolfssl.so: $(LIBWOLFSSL_NAME). @ echo 'Using existing Makefile for libwolfssl.so.' @else @ echo -n 'Configuring user libwolfssl.so...' - @ $(FRESH_ENV) ./configure $(QFLAG) $(VFLAG) --disable-jobserver --enable-cryptonly --enable-fips="$$FIPS_FLAVOR" CFLAGS='-DWC_SYM_RELOC_TABLES_SUPPORT -DWOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE -DWOLFSSL_USER_SETTINGS -DWOLFSSL_USER_SETTINGS_ASM' $(if $(HOSTCC),CC='$(HOSTCC)') + @ $(FRESH_ENV) ./configure $(QFLAG) $(VFLAG) --disable-jobserver --enable-cryptonly --enable-fips="$$FIPS_FLAVOR" CFLAGS='-DWC_SYM_RELOC_TABLES_SUPPORT -DWOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE -DWOLFSSL_USER_SETTINGS -DWOLFSSL_USER_SETTINGS_ASM -DDEBUG_LINUXKM_PIE_SUPPORT' $(if $(HOSTCC),CC='$(HOSTCC)') @ echo ' done.' @fi @echo -n 'Building user libwolfssl.so...' diff --git a/linuxkm/linuxkm-fips-hash-wrapper.sh b/linuxkm/linuxkm-fips-hash-wrapper.sh index 9f68b82f615..1018d30c154 100755 --- a/linuxkm/linuxkm-fips-hash-wrapper.sh +++ b/linuxkm/linuxkm-fips-hash-wrapper.sh @@ -50,6 +50,8 @@ readarray -t fenceposts < <(readelf --wide --sections --symbols "$mod_path" | "$ BEGIN { fips_fenceposts["wc_linuxkm_pie_text_reloc_tab"] = "text_reloc_tab.start"; fips_fenceposts["wc_linuxkm_pie_text_reloc_tab_length"] = "text_reloc_tab.len_start"; + fips_fenceposts["wc_linuxkm_pie_rodata_reloc_tab"] = "rodata_reloc_tab.start"; + fips_fenceposts["wc_linuxkm_pie_rodata_reloc_tab_length"] = "rodata_reloc_tab.len_start"; fips_fenceposts["verifyCore"] = "verifyCore_start"; fips_fenceposts["wolfCrypt_FIPS_first"] = "fips_text_start"; fips_fenceposts["wolfCrypt_FIPS_last"] = "fips_text_end"; @@ -57,6 +59,8 @@ BEGIN { fips_fenceposts["wolfCrypt_FIPS_ro_end"] = "fips_rodata_end"; singleton_ends["wc_linuxkm_pie_text_reloc_tab"] = "text_reloc_tab.end"; singleton_ends["wc_linuxkm_pie_text_reloc_tab_length"] = "text_reloc_tab.len_end"; + singleton_ends["wc_linuxkm_pie_rodata_reloc_tab"] = "rodata_reloc_tab.end"; + singleton_ends["wc_linuxkm_pie_rodata_reloc_tab_length"] = "rodata_reloc_tab.len_end"; singleton_ends["verifyCore"] = "verifyCore_end"; } diff --git a/linuxkm/linuxkm-fips-hash.c b/linuxkm/linuxkm-fips-hash.c index 59719f51ace..ff327f0ceb7 100644 --- a/linuxkm/linuxkm-fips-hash.c +++ b/linuxkm/linuxkm-fips-hash.c @@ -108,6 +108,10 @@ int main(int argc, char **argv) FENCEPOST_OPT(text_reloc_tab.end), FENCEPOST_OPT(text_reloc_tab.len_start), FENCEPOST_OPT(text_reloc_tab.len_end), + FENCEPOST_OPT(rodata_reloc_tab.start), + FENCEPOST_OPT(rodata_reloc_tab.end), + FENCEPOST_OPT(rodata_reloc_tab.len_start), + FENCEPOST_OPT(rodata_reloc_tab.len_end), FENCEPOST_OPT(fips_text_start), FENCEPOST_OPT(fips_text_end), FENCEPOST_OPT(rodata_start), @@ -232,6 +236,10 @@ int main(int argc, char **argv) (seg_map.text_reloc_tab.end == ~0UL) || (seg_map.text_reloc_tab.len_start == ~0UL) || (seg_map.text_reloc_tab.len_end == ~0UL) || + (seg_map.rodata_reloc_tab.start == ~0UL) || + (seg_map.rodata_reloc_tab.end == ~0UL) || + (seg_map.rodata_reloc_tab.len_start == ~0UL) || + (seg_map.rodata_reloc_tab.len_end == ~0UL) || (seg_map.fips_text_start == ~0UL) || (seg_map.fips_text_end == ~0UL) || (seg_map.rodata_start == ~0UL) || @@ -278,6 +286,17 @@ int main(int argc, char **argv) exit(1); } + if ((seg_map.rodata_reloc_tab.start >= seg_map.rodata_reloc_tab.end) || + (seg_map.rodata_reloc_tab.end >= (unsigned long)st.st_size) || + (seg_map.rodata_reloc_tab.len_start >= seg_map.rodata_reloc_tab.len_end) || + (seg_map.rodata_reloc_tab.len_end >= (unsigned long)st.st_size)) + { + fprintf(stderr, "%s: supplied rodata_reloc_tab fencepost(s) are out of bounds " + "for supplied module %s with length %lu.\n", + progname, mod_path, (unsigned long)st.st_size); + exit(1); + } + mod_map = (byte *)mmap(NULL, st.st_size, inplace ? PROT_READ | PROT_WRITE : PROT_READ, (inplace ? MAP_SHARED : MAP_PRIVATE) | MAP_POPULATE, @@ -296,6 +315,11 @@ int main(int argc, char **argv) seg_map.text_reloc_tab.len_start += (unsigned long)mod_map; seg_map.text_reloc_tab.len_end += (unsigned long)mod_map; + seg_map.rodata_reloc_tab.start += (unsigned long)mod_map; + seg_map.rodata_reloc_tab.end += (unsigned long)mod_map; + seg_map.rodata_reloc_tab.len_start += (unsigned long)mod_map; + seg_map.rodata_reloc_tab.len_end += (unsigned long)mod_map; + seg_map.verifyCore_start += (unsigned long)mod_map; seg_map.verifyCore_end += (unsigned long)mod_map; seg_map.fips_text_start += (unsigned long)mod_map; diff --git a/linuxkm/linuxkm_memory.c b/linuxkm/linuxkm_memory.c index 01f816a73b0..9969a7fc732 100644 --- a/linuxkm/linuxkm_memory.c +++ b/linuxkm/linuxkm_memory.c @@ -74,44 +74,41 @@ static const struct reloc_layout_ent { }; static inline long find_reloc_tab_offset( - const struct wc_reloc_table_segments *seg_map, const struct wc_reloc_table_ent reloc_tab[], word32 reloc_tab_len, - size_t text_in_offset) + size_t seg_in_offset) { long ret; unsigned long hop; - if (reloc_tab_len <= 1) { - RELOC_DEBUG_PRINTF("ERROR: %s failed.\n", __FUNCTION__); - return -1; - } - if (text_in_offset >= (size_t)(seg_map->text_end - seg_map->text_start)) { + + if (seg_in_offset >= (size_t)reloc_tab[reloc_tab_len - 1].offset) { RELOC_DEBUG_PRINTF("ERROR: %s failed.\n", __FUNCTION__); - return -1; + return BAD_FUNC_ARG; } - if (text_in_offset >= (size_t)reloc_tab[reloc_tab_len - 1].offset) { - RELOC_DEBUG_PRINTF("ERROR: %s failed.\n", __FUNCTION__); - return -1; + + if (reloc_tab_len <= 1) { + /* empty relocation table. */ + return 0; } for (ret = 0, hop = reloc_tab_len >> 1; hop; hop >>= 1) { - if (text_in_offset == (size_t)reloc_tab[ret].offset) + if (seg_in_offset == (size_t)reloc_tab[ret].offset) break; - else if (text_in_offset > (size_t)reloc_tab[ret].offset) + else if (seg_in_offset > (size_t)reloc_tab[ret].offset) ret += hop; else if (ret) ret -= hop; } while ((ret < (long)reloc_tab_len - 1) && - ((size_t)reloc_tab[ret].offset < text_in_offset)) + ((size_t)reloc_tab[ret].offset < seg_in_offset)) ++ret; while ((ret > 0) && - ((size_t)reloc_tab[ret - 1].offset >= text_in_offset)) + ((size_t)reloc_tab[ret - 1].offset >= seg_in_offset)) --ret; #ifdef DEBUG_LINUXKM_PIE_SUPPORT @@ -128,35 +125,65 @@ static inline long find_reloc_tab_offset( #define wc_get_unaligned(v) ({ typeof(*(v)) _v_aligned; XMEMCPY((void *)&_v_aligned, (void *)(v), sizeof _v_aligned); _v_aligned; }) #define wc_put_unaligned(v, v_out) do { typeof(v) _v = (v); XMEMCPY((void *)(v_out), (void *)&_v, sizeof(typeof(*(v_out)))); } while (0) -ssize_t wc_reloc_normalize_text( - const byte *text_in, - size_t text_in_len, - byte *text_out, +ssize_t wc_reloc_normalize_segment( + const byte *seg_in, + size_t *seg_in_out_len, + byte *seg_out, ssize_t *cur_index_p, const struct wc_reloc_table_segments *seg_map, struct wc_reloc_counts *reloc_counts) { ssize_t i; - size_t text_in_offset; + size_t seg_in_offset; const struct wc_reloc_table_ent *last_reloc; /* for error-checking order in reloc_tab[] */ 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; - const struct wc_reloc_table_ent *reloc_tab = (const struct wc_reloc_table_ent *)seg_map->text_reloc_tab.start; - const word32 reloc_tab_len = *(const word32 *)seg_map->text_reloc_tab.len_start; + const struct wc_reloc_table_ent *reloc_tab; + word32 reloc_tab_len; + uintptr_t src_seg_start; +#ifdef DEBUG_LINUXKM_PIE_SUPPORT + uintptr_t src_seg_end; + const char *src_seg_name; +#endif + + if (*seg_in_out_len == 0) + return BAD_FUNC_ARG; - if ((text_in_len == 0) || - ((uintptr_t)text_in < seg_map->text_start) || - ((uintptr_t)(text_in + text_in_len) > seg_map->text_end)) + if (((uintptr_t)seg_in >= seg_map->text_start) && + ((uintptr_t)(seg_in + *seg_in_out_len) <= seg_map->text_end)) + { + reloc_tab = (const struct wc_reloc_table_ent *)seg_map->text_reloc_tab.start; + reloc_tab_len = *(const word32 *)seg_map->text_reloc_tab.len_start; + src_seg_start = seg_map->text_start; +#ifdef DEBUG_LINUXKM_PIE_SUPPORT + src_seg_end = seg_map->text_end; + src_seg_name = "text"; +#endif + } + else if (((uintptr_t)seg_in >= seg_map->rodata_start) && + ((uintptr_t)(seg_in + *seg_in_out_len) <= seg_map->rodata_end)) + { + reloc_tab = (const struct wc_reloc_table_ent *)seg_map->rodata_reloc_tab.start; + reloc_tab_len = *(const word32 *)seg_map->rodata_reloc_tab.len_start; + src_seg_start = seg_map->rodata_start; +#ifdef DEBUG_LINUXKM_PIE_SUPPORT + src_seg_end = seg_map->rodata_end; + src_seg_name = "rodata"; +#endif + } + else { - RELOC_DEBUG_PRINTF("ERROR: %s returning -1 with span %llx-%llx versus segment %llx-%llx.\n", + RELOC_DEBUG_PRINTF("ERROR: %s returning BAD_FUNC_ARG with span %llx-%llx versus text %llx-%llx and rodata %llx-%llx.\n", __FUNCTION__, - (unsigned long long)(uintptr_t)text_in, - (unsigned long long)(uintptr_t)(text_in + text_in_len), + (unsigned long long)(uintptr_t)seg_in, + (unsigned long long)(uintptr_t)(seg_in + *seg_in_out_len), (unsigned long long)seg_map->text_start, - (unsigned long long)seg_map->text_end); - return -1; + (unsigned long long)seg_map->text_end, + (unsigned long long)seg_map->rodata_start, + (unsigned long long)seg_map->rodata_end); + return BAD_FUNC_ARG; } - text_in_offset = (uintptr_t)text_in - seg_map->text_start; + seg_in_offset = (uintptr_t)seg_in - src_seg_start; if (cur_index_p) i = *cur_index_p; @@ -164,25 +191,28 @@ ssize_t wc_reloc_normalize_text( i = -1; if (i == -1) - i = find_reloc_tab_offset(seg_map, reloc_tab, reloc_tab_len, text_in_offset); + i = find_reloc_tab_offset(reloc_tab, reloc_tab_len, seg_in_offset); if (i < 0) return i; WC_SANITIZE_DISABLE(); - memcpy(text_out, text_in, text_in_len); + memcpy(seg_out, seg_in, *seg_in_out_len); WC_SANITIZE_ENABLE(); + /* note, if there are no relocations in the src seg, the loop isn't entered + * at all, and we return without further ado. + */ for (last_reloc = &reloc_tab[i > 0 ? i-1 : 0]; (size_t)i < reloc_tab_len - 1; ++i) { const struct wc_reloc_table_ent *next_reloc = &reloc_tab[i]; enum wc_reloc_dest_segment dest_seg; - uintptr_t seg_beg; + uintptr_t dest_seg_start; #ifdef DEBUG_LINUXKM_PIE_SUPPORT - uintptr_t seg_end; - const char *seg_name; + uintptr_t dest_seg_end; + const char *dest_seg_name; #endif word64 reloc_buf = 0; const struct reloc_layout_ent *layout; @@ -196,7 +226,7 @@ ssize_t wc_reloc_normalize_text( if (last_reloc->offset > next_reloc->offset) { RELOC_DEBUG_PRINTF("BUG: out-of-order offset found at reloc_tab[%zd]: %u > %u\n", i, last_reloc->offset, next_reloc->offset); - return -1; + return BAD_FUNC_ARG; } last_reloc = next_reloc; @@ -204,7 +234,7 @@ ssize_t wc_reloc_normalize_text( if (next_reloc->reloc_type >= (sizeof reloc_layouts / sizeof reloc_layouts[0])) { RELOC_DEBUG_PRINTF("BUG: unknown relocation type %u found at reloc_tab[%zd]\n", next_reloc->reloc_type, i); - return -1; + return BAD_FUNC_ARG; } layout = &reloc_layouts[next_reloc->reloc_type]; @@ -217,7 +247,7 @@ ssize_t wc_reloc_normalize_text( default: RELOC_DEBUG_PRINTF("BUG: unexpected relocation width %llu found at reloc_tab[%lld], reloc type %u\n", (unsigned long long)layout->width, (long long)i, next_reloc->reloc_type); - return -1; + return BAD_FUNC_ARG; } /* provisionally assign the destination segment from the reloc record -- @@ -227,23 +257,23 @@ ssize_t wc_reloc_normalize_text( 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 + * of the current text chunk (seg_in). i.e., seg_in + next_reloc_rel * is the start of the relocation. */ - next_reloc_rel = next_reloc->offset - text_in_offset; + next_reloc_rel = next_reloc->offset - seg_in_offset; - if (next_reloc_rel >= text_in_len) { + if (next_reloc_rel >= *seg_in_out_len) { /* no more relocations in this buffer. */ break; } - if ((text_in_len < WC_BITS_TO_BYTES(layout->width)) || - (next_reloc_rel > text_in_len - WC_BITS_TO_BYTES(layout->width))) + if ((*seg_in_out_len < WC_BITS_TO_BYTES(layout->width)) || + (next_reloc_rel > *seg_in_out_len - WC_BITS_TO_BYTES(layout->width))) { /* relocation straddles buffer at end -- caller will try again with * that relocation at the start. */ - text_in_len = next_reloc_rel; + *seg_in_out_len = next_reloc_rel; break; } @@ -257,61 +287,61 @@ ssize_t wc_reloc_normalize_text( */ switch (layout->width) { case 32: - reloc_buf = (word64)(sword64)(wc_get_unaligned((sword32 *)&text_out[next_reloc_rel]) & (sword32)layout->mask); + reloc_buf = (word64)(sword64)(wc_get_unaligned((sword32 *)&seg_out[next_reloc_rel]) & (sword32)layout->mask); break; case 64: - reloc_buf = (word64)(sword64)(wc_get_unaligned((sword64 *)&text_out[next_reloc_rel]) & (sword64)layout->mask); + reloc_buf = (word64)(sword64)(wc_get_unaligned((sword64 *)&seg_out[next_reloc_rel]) & (sword64)layout->mask); break; case 16: - reloc_buf = (word64)(sword64)(wc_get_unaligned((sword16 *)&text_out[next_reloc_rel]) & (sword16)layout->mask); + reloc_buf = (word64)(sword64)(wc_get_unaligned((sword16 *)&seg_out[next_reloc_rel]) & (sword16)layout->mask); break; } } else { switch (layout->width) { case 32: - reloc_buf = (word64)(wc_get_unaligned((word32 *)&text_out[next_reloc_rel]) & (word32)layout->mask); + reloc_buf = (word64)(wc_get_unaligned((word32 *)&seg_out[next_reloc_rel]) & (word32)layout->mask); break; case 64: - reloc_buf = (word64)(wc_get_unaligned((word64 *)&text_out[next_reloc_rel]) & layout->mask); + reloc_buf = (word64)(wc_get_unaligned((word64 *)&seg_out[next_reloc_rel]) & layout->mask); break; case 16: - reloc_buf = (word64)(wc_get_unaligned((word16 *)&text_out[next_reloc_rel]) & (word16)layout->mask); + reloc_buf = (word64)(wc_get_unaligned((word16 *)&seg_out[next_reloc_rel]) & (word16)layout->mask); break; } } switch (dest_seg) { case WC_R_SEG_TEXT: - seg_beg = seg_map->text_start; + dest_seg_start = seg_map->text_start; ++n_text_r; #ifdef DEBUG_LINUXKM_PIE_SUPPORT - seg_end = seg_map->text_end; - seg_name = "text"; + dest_seg_end = seg_map->text_end; + dest_seg_name = "text"; #endif break; case WC_R_SEG_RODATA: - seg_beg = seg_map->rodata_start; + dest_seg_start = seg_map->rodata_start; ++n_rodata_r; #ifdef DEBUG_LINUXKM_PIE_SUPPORT - seg_end = seg_map->rodata_end; - seg_name = "rodata"; + dest_seg_end = seg_map->rodata_end; + dest_seg_name = "rodata"; #endif break; case WC_R_SEG_RWDATA: - seg_beg = seg_map->data_start; + dest_seg_start = seg_map->data_start; ++n_rwdata_r; #ifdef DEBUG_LINUXKM_PIE_SUPPORT - seg_end = seg_map->data_end; - seg_name = "data"; + dest_seg_end = seg_map->data_end; + dest_seg_name = "data"; #endif break; case WC_R_SEG_BSS: - seg_beg = seg_map->bss_start; + dest_seg_start = seg_map->bss_start; ++n_bss_r; #ifdef DEBUG_LINUXKM_PIE_SUPPORT - seg_end = seg_map->bss_end; - seg_name = "bss"; + dest_seg_end = seg_map->bss_end; + dest_seg_name = "bss"; #endif break; default: @@ -319,10 +349,10 @@ ssize_t wc_reloc_normalize_text( dest_seg = WC_R_SEG_OTHER; FALL_THROUGH; case WC_R_SEG_OTHER: - seg_beg = 0; + dest_seg_start = 0; #ifdef DEBUG_LINUXKM_PIE_SUPPORT - seg_end = 0; - seg_name = "other"; + dest_seg_end = 0; + dest_seg_name = "other"; #endif break; } @@ -344,33 +374,35 @@ ssize_t wc_reloc_normalize_text( * baked into the reloc_tab for each relocation. */ if (layout->is_relative) - reloc_buf = reloc_buf + (uintptr_t)next_reloc->offset - (uintptr_t)next_reloc->dest_addend - (seg_beg - seg_map->text_start); + reloc_buf = reloc_buf + (uintptr_t)next_reloc->offset - (uintptr_t)next_reloc->dest_addend - (dest_seg_start - src_seg_start); else - reloc_buf = reloc_buf - seg_beg - (uintptr_t)next_reloc->dest_addend; + reloc_buf = reloc_buf - dest_seg_start - (uintptr_t)next_reloc->dest_addend; } else { reloc_buf = (word64)next_reloc->dest_offset; } #ifdef DEBUG_LINUXKM_PIE_SUPPORT - if (reloc_buf >= seg_end - seg_beg) { + if (reloc_buf >= dest_seg_end - dest_seg_start) { ++n_oob_r; - RELOC_DEBUG_PRINTF("WARNING: normalized value is out of bounds (%s0x%llx) at index %lld, text offset 0x%x, reloc type %s, " - "dest seg .%s_wolfcrypt, offset from text to dest segment %s0x%llx, raw dest addr %s0x%llx, " - "seg span 0x%llx - 0x%llx, seg size 0x%llx, text base 0x%llx\n", + RELOC_DEBUG_PRINTF("WARNING: normalized value is out of bounds (%s0x%llx) at index %lld, %s offset 0x%x, reloc type %s, " + "src seg .%s_wolfcrypt, dest seg .%s_wolfcrypt, offset from src to dest segment %s0x%llx, raw dest addr %s0x%llx, " + "seg span 0x%llx - 0x%llx, seg size 0x%llx, src seg 0x%llx-0x%llx\n", (long long)reloc_buf < 0 ? "-" : "", (long long)reloc_buf < 0 ? -(long long)reloc_buf : (long long)reloc_buf, (long long)i, + src_seg_name, next_reloc->offset, layout->name, - seg_name, - seg_beg < seg_map->text_start ? "-" : "+", - seg_beg < seg_map->text_start ? (unsigned long long)seg_map->text_start - seg_beg : seg_beg - (unsigned long long)seg_map->text_start, + src_seg_name, + dest_seg_name, + dest_seg_start < src_seg_start ? "-" : "+", + dest_seg_start < src_seg_start ? (unsigned long long)src_seg_start - dest_seg_start : dest_seg_start - (unsigned long long)src_seg_start, (layout->is_signed && ((long long)raw_dest_addr < 0)) ? "-" : "", (layout->is_signed && ((long long)raw_dest_addr < 0)) ? (unsigned long long)-(long long)raw_dest_addr : raw_dest_addr, - (unsigned long long)seg_beg, - (unsigned long long)seg_end, - (unsigned long long)(seg_end - seg_beg), - (unsigned long long)seg_map->text_start); + (unsigned long long)dest_seg_start, + (unsigned long long)dest_seg_end, + (unsigned long long)(dest_seg_end - dest_seg_start), + (unsigned long long)src_seg_start, (unsigned long long)src_seg_end); } #endif } @@ -414,8 +446,8 @@ ssize_t wc_reloc_normalize_text( break; default: - RELOC_DEBUG_PRINTF("BUG: unrecognized relocation type %u in reloc record %zu, text offset 0x%x\n", - (unsigned)next_reloc->reloc_type, i, reloc_tab[i].offset); + RELOC_DEBUG_PRINTF("BUG: unrecognized relocation type %u in reloc record %zu, %s offset 0x%x\n", + (unsigned)next_reloc->reloc_type, i, src_seg_name, reloc_tab[i].offset); ++n_oob_r; dest_seg = WC_R_SEG_OTHER; } @@ -427,8 +459,8 @@ ssize_t wc_reloc_normalize_text( reloc_buf = 0; ++n_other_r; - RELOC_DEBUG_PRINTF("found non-wolfcrypt relocation at index %lld, text offset 0x%x.\n", - (long long)i, reloc_tab[i].offset); + RELOC_DEBUG_PRINTF("found non-wolfcrypt relocation at index %lld, %s offset 0x%x.\n", + (long long)i, src_seg_name, reloc_tab[i].offset); } /* xor in a label identifying the dest segment and reloc type. */ @@ -438,13 +470,13 @@ ssize_t wc_reloc_normalize_text( /* write the modified reloc_buf to the destination buffer. */ switch (layout->width) { case 32: - wc_put_unaligned((word32)reloc_buf, (word32 *)&text_out[next_reloc_rel]); + wc_put_unaligned((word32)reloc_buf, (word32 *)&seg_out[next_reloc_rel]); break; case 64: - wc_put_unaligned(reloc_buf, (word64 *)&text_out[next_reloc_rel]); + wc_put_unaligned(reloc_buf, (word64 *)&seg_out[next_reloc_rel]); break; case 16: - wc_put_unaligned((word16)reloc_buf, (word16 *)&text_out[next_reloc_rel]); + wc_put_unaligned((word16)reloc_buf, (word16 *)&seg_out[next_reloc_rel]); break; } } @@ -458,15 +490,15 @@ ssize_t wc_reloc_normalize_text( } if ((n_other_r > 0) || (n_oob_r > 0)) - RELOC_DEBUG_PRINTF("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, + RELOC_DEBUG_PRINTF("seg_in=%llx relocs=%d/%d/%d/%d/%d/%d ret = %llu\n", + (unsigned long long)(uintptr_t)seg_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); + (unsigned long long)*seg_in_out_len); if (cur_index_p) *cur_index_p = i; - return (ssize_t)text_in_len; + return (ssize_t)*seg_in_out_len; } #endif /* WC_SYM_RELOC_TABLES || WC_SYM_RELOC_TABLES_SUPPORT */ @@ -559,6 +591,12 @@ int wc_fips_generate_hash( RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_FUNC_ARG; } + if ((seg_map->rodata_reloc_tab.start == 0) || + (seg_map->rodata_reloc_tab.len_start == 0)) + { + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_FUNC_ARG; + } } else { if ((seg_map->text_reloc_tab.end == 0) || @@ -567,6 +605,12 @@ int wc_fips_generate_hash( RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_FUNC_ARG; } + if ((seg_map->rodata_reloc_tab.end == 0) || + (seg_map->rodata_reloc_tab.len_end == 0)) + { + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_FUNC_ARG; + } } #endif @@ -577,6 +621,8 @@ int wc_fips_generate_hash( || ((seg_map->text_reloc_tab.end != 0) && (seg_map->text_reloc_tab.start >= seg_map->text_reloc_tab.end)) || ((seg_map->text_reloc_tab.len_end != 0) && (seg_map->text_reloc_tab.len_start >= seg_map->text_reloc_tab.len_end)) || + ((seg_map->rodata_reloc_tab.end != 0) && (seg_map->rodata_reloc_tab.start >= seg_map->rodata_reloc_tab.end)) || + ((seg_map->rodata_reloc_tab.len_end != 0) && (seg_map->rodata_reloc_tab.len_start >= seg_map->rodata_reloc_tab.len_end)) || (seg_map->text_start >= seg_map->text_end) || (seg_map->rodata_start >= seg_map->rodata_end) || (seg_map->data_start >= seg_map->data_end) || @@ -596,6 +642,8 @@ int wc_fips_generate_hash( || (seg_map->text_reloc_tab.start < seg_map->start) || (seg_map->text_reloc_tab.len_start < seg_map->start) || + (seg_map->rodata_reloc_tab.start < seg_map->start) || + (seg_map->rodata_reloc_tab.len_start < seg_map->start) || (seg_map->text_start < seg_map->start) || (seg_map->rodata_start < seg_map->start) || (seg_map->data_start < seg_map->start) || @@ -618,6 +666,10 @@ int wc_fips_generate_hash( (seg_map->text_reloc_tab.end > seg_map->end)) || ((seg_map->text_reloc_tab.len_end != 0) && (seg_map->text_reloc_tab.len_end > seg_map->end)) || + ((seg_map->rodata_reloc_tab.end != 0) && + (seg_map->rodata_reloc_tab.end > seg_map->end)) || + ((seg_map->rodata_reloc_tab.len_end != 0) && + (seg_map->rodata_reloc_tab.len_end > seg_map->end)) || (seg_map->text_end > seg_map->end) || (seg_map->rodata_end > seg_map->end) || (seg_map->data_end > seg_map->end) || @@ -680,6 +732,56 @@ int wc_fips_generate_hash( return BAD_FUNC_ARG; } } + + if ((seg_map->rodata_reloc_tab.len_end != 0) && + (seg_map->rodata_reloc_tab.len_end - seg_map->rodata_reloc_tab.len_start != sizeof(word32))) + { + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_FUNC_ARG; + } + else if (seg_map->rodata_reloc_tab.len_start & (sizeof(word32) - 1)) { + /* fprintf(stderr, "%s: seg_map->rodata_reloc_tab.len_start isn't properly aligned: 0x%llx.\n", progname, ( + unsigned long long)seg_map->rodata_reloc_tab.len_start); */ + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_ALIGN_E; + } + else { + /* Note we don't currently handle modules that are endian-conflicted + * with the build host -- that'll be caught here, when reloc_tab_len is + * a nonsense byte-swapped value, or the final reloc_tab ent has + * nonsense flags. + */ + word32 reloc_tab_len = *(const word32 *)seg_map->rodata_reloc_tab.len_start; + const struct wc_reloc_table_ent *reloc_tab = (const struct wc_reloc_table_ent *)seg_map->rodata_reloc_tab.start; + if (reloc_tab_len == 0) { + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_FUNC_ARG; + } + else if ((seg_map->end != 0) && + ((unsigned long)(reloc_tab + reloc_tab_len) > seg_map->end)) + { + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_FUNC_ARG; + } + else if ((reloc_tab[reloc_tab_len - 1].dest_segment != WC_R_SEG_NONE) || + (reloc_tab[reloc_tab_len - 1].reloc_type != WC_R_NONE)) + { + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_FUNC_ARG; + } + else if ((seg_map->rodata_reloc_tab.end != 0) && + (seg_map->rodata_reloc_tab.end - seg_map->rodata_reloc_tab.start != sizeof(struct wc_reloc_table_ent) * *(const word32 *)seg_map->rodata_reloc_tab.len_start)) + { + /* + fprintf(stderr, "%s: wc_linuxkm_pie_rodata_reloc_tab_length from module (%u) is inconsistent with actual rodata_reloc_tab size %llu.\n", + progname, + *(const word32 *)seg_map->rodata_reloc_tab.len_start, + (unsigned long long)(seg_map->rodata_reloc_tab.end - seg_map->rodata_reloc_tab.start)); + */ + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_FUNC_ARG; + } + } #endif if (out_size == NULL) { @@ -728,9 +830,10 @@ int wc_fips_generate_hash( #if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT) { - ssize_t cur_reloc_index = -1; + ssize_t cur_reloc_index; const byte *text_p = (const byte *)seg_map->fips_text_start; - byte *buf = XMALLOC(WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + const byte *rodata_p = (const byte *)seg_map->fips_rodata_start; + byte *buf = XMALLOC(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (! buf) { ret = MEMORY_E; @@ -738,23 +841,23 @@ int wc_fips_generate_hash( goto out; } + cur_reloc_index = -1; while (text_p < (const byte *)seg_map->fips_text_end) { - /* wc_reloc_normalize_text() does its own WC_SANITIZE_DISABLE()s, so - * we defer it here. - */ - ssize_t progress = wc_reloc_normalize_text( + size_t text_in_out_len = min(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ, + (size_t)((const byte *)seg_map->fips_text_end - text_p)); + ssize_t progress = wc_reloc_normalize_segment( text_p, - min(WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ, (word32)((const byte *)seg_map->fips_text_end - text_p)), + &text_in_out_len, buf, &cur_reloc_index, seg_map, reloc_counts); if (progress <= 0) { - ret = IN_CORE_FIPS_E; - RELOC_DEBUG_PRINTF("wc_reloc_normalize_text() failed.\n"); + RELOC_DEBUG_PRINTF("wc_reloc_normalize_segment() for text failed: %zd.\n", progress); + ret = progress ? (int)progress : IN_CORE_FIPS_E; break; } - ret = hmac_update(hmac_ctx, buf, (word32)progress); + ret = hmac_update(hmac_ctx, buf, (word32)text_in_out_len); if (ret) { RELOC_DEBUG_PRINTF("hmac_update() failed.\n"); break; @@ -762,15 +865,53 @@ int wc_fips_generate_hash( text_p += progress; } + cur_reloc_index = -1; + while (rodata_p < (const byte *)seg_map->fips_rodata_end) { + size_t rodata_in_out_len = min(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ, + (size_t)((const byte *)seg_map->fips_rodata_end - rodata_p)); + /* don't hash verifyCore or changing verifyCore will change hash */ + if ((rodata_p < (const byte *)seg_map->verifyCore_end) && + (rodata_p + rodata_in_out_len >= (const byte *)seg_map->verifyCore_start)) + { + rodata_in_out_len = (size_t)((const byte *)seg_map->verifyCore_start - rodata_p); + if (rodata_in_out_len == 0) { + rodata_p = (const byte *)seg_map->verifyCore_end; + /* force recomputation of relocation offset when skipping + * a span (not processed by wc_reloc_normalize_segment()). + */ + cur_reloc_index = -1; + continue; + } + } + + ssize_t progress = wc_reloc_normalize_segment( + rodata_p, + &rodata_in_out_len, + buf, + &cur_reloc_index, + seg_map, + reloc_counts); + if (progress <= 0) { + RELOC_DEBUG_PRINTF("wc_reloc_normalize_segment() for rodata failed: %zd.\n", progress); + ret = progress ? (int)progress : IN_CORE_FIPS_E; + break; + } + ret = hmac_update(hmac_ctx, buf, (word32)rodata_in_out_len); + if (ret) { + RELOC_DEBUG_PRINTF("hmac_update() failed.\n"); + break; + } + rodata_p += progress; + } + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } - WC_SANITIZE_DISABLE(); -#else +#else /* ! (WC_SYM_RELOC_TABLES || WC_SYM_RELOC_TABLES_SUPPORT) */ + (void)reloc_counts; WC_SANITIZE_DISABLE(); ret = hmac_update(hmac_ctx, (byte *)(wc_ptr_t)seg_map->fips_text_start, (word32)(seg_map->fips_text_end - seg_map->fips_text_start)); -#endif /* !WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE */ if (ret) { RELOC_DEBUG_PRINTF("ERROR: hmac_update failed: err %d\n", ret); @@ -795,6 +936,8 @@ int wc_fips_generate_hash( WC_SANITIZE_ENABLE(); +#endif /* ! (WC_SYM_RELOC_TABLES || WC_SYM_RELOC_TABLES_SUPPORT) */ + if (ret) { RELOC_DEBUG_PRINTF("ERROR: hmac_update failed: err %d\n", ret); ret = BAD_STATE_E; diff --git a/linuxkm/linuxkm_memory.h b/linuxkm/linuxkm_memory.h index c60a734b8e5..76e681da805 100644 --- a/linuxkm/linuxkm_memory.h +++ b/linuxkm/linuxkm_memory.h @@ -175,7 +175,7 @@ struct wc_reloc_counts { #elif defined(HAVE_FIPS) /* barebones FIPS fencepost representation -- no provision for - * wc_reloc_normalize_text() + * wc_reloc_normalize_segment() */ struct wc_reloc_table_segments { @@ -216,18 +216,10 @@ struct wc_reloc_counts { #define WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ #endif -WOLFSSL_API ssize_t wc_reloc_normalize_text( - const byte *text_in, - size_t text_in_len, - byte *text_out, - ssize_t *cur_index_p, - const struct wc_reloc_table_segments *seg_map, - struct wc_reloc_counts *reloc_counts); - -WOLFSSL_API ssize_t wc_reloc_normalize_rodata( - const byte *rodata_in, - size_t rodata_in_len, - byte *rodata_out, +WOLFSSL_API ssize_t wc_reloc_normalize_segment( + const byte *seg_in, + size_t *seg_in_out_len, + byte *seg_out, ssize_t *cur_index_p, const struct wc_reloc_table_segments *seg_map, struct wc_reloc_counts *reloc_counts); diff --git a/linuxkm/linuxkm_wc_port.h b/linuxkm/linuxkm_wc_port.h index 22255af4560..c359277e34c 100644 --- a/linuxkm/linuxkm_wc_port.h +++ b/linuxkm/linuxkm_wc_port.h @@ -876,15 +876,33 @@ __wc_bss_end[]; extern ssize_t wc_linuxkm_normalize_relocations( - const u8 *text_in, - size_t text_in_len, - u8 *text_out, + const u8 *seg_in, + size_t *seg_in_out_len, + u8 *seg_out, ssize_t *cur_index_p); + extern ssize_t wc_linuxkm_normalize_relocations_noresize( + const u8 *seg_in, + size_t seg_in_len, + u8 *seg_out, + ssize_t *cur_index_p); + + #ifndef WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ + #define WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ 8192 + #endif + + #ifndef WOLFSSL_SEGMENT_CANONICALIZER + #define WOLFSSL_SEGMENT_CANONICALIZER(seg_in, seg_in_out_len, seg_out, cur_index_p) \ + wc_linuxkm_normalize_relocations(seg_in, seg_in_out_len, seg_out, cur_index_p) + #endif + + /* backward-compatible wrappers */ #ifndef WOLFSSL_TEXT_SEGMENT_CANONICALIZER #define WOLFSSL_TEXT_SEGMENT_CANONICALIZER(text_in, text_in_len, text_out, cur_index_p) \ - wc_linuxkm_normalize_relocations(text_in, text_in_len, text_out, cur_index_p) - #define WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ 8192 + wc_linuxkm_normalize_relocations_noresize(text_in, text_in_len, text_out, cur_index_p) + #endif + #ifndef WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ + #define WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ #endif #ifdef CONFIG_MIPS @@ -896,6 +914,7 @@ struct wolfssl_linuxkm_pie_redirect_table { #ifdef HAVE_FIPS typeof(wc_linuxkm_normalize_relocations) *wc_linuxkm_normalize_relocations; + typeof(wc_linuxkm_normalize_relocations_noresize) *wc_linuxkm_normalize_relocations_noresize; #endif #ifndef __ARCH_MEMCMP_NO_REDIRECT @@ -1234,6 +1253,8 @@ #ifdef HAVE_FIPS #define wc_linuxkm_normalize_relocations \ WC_PIE_INDIRECT_SYM(wc_linuxkm_normalize_relocations) + #define wc_linuxkm_normalize_relocations_noresize \ + WC_PIE_INDIRECT_SYM(wc_linuxkm_normalize_relocations_noresize) #endif #ifndef __ARCH_MEMCMP_NO_REDIRECT diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index 90a695aa453..03b6e2e44ec 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -711,13 +711,15 @@ static int wolfssl_init(void) { unsigned int text_hash = hash_span((const u8 *)__wc_text_start, (const u8 *)__wc_text_end, 1); unsigned int rodata_hash = hash_span((const u8 *)__wc_rodata_start, (const u8 *)__wc_rodata_end, 1); - u8 *canon_buf = malloc(WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ); + u8 *canon_buf = malloc(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ); ssize_t cur_reloc_index = -1; const u8 *text_p = (const u8 *)__wc_text_start; + const u8 *rodata_p = (const u8 *)__wc_rodata_start; unsigned int stabilized_text_hash = 1; + unsigned int stabilized_rodata_hash = 1; if (! canon_buf) { - pr_err("ERROR: malloc(%d) for WOLFSSL_TEXT_SEGMENT_CANONICALIZER failed: %ld.\n", WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ, PTR_ERR(canon_buf)); + pr_err("ERROR: malloc(%d) for WOLFSSL_*_SEGMENT_CANONICALIZER failed: %ld.\n", WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ, PTR_ERR(canon_buf)); return -ECANCELED; } @@ -725,14 +727,15 @@ static int wolfssl_init(void) reloc_counts.other = 0; while (text_p < (const u8 *)__wc_text_end) { + size_t text_in_out_len = min(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ, + (size_t)((const u8 *)__wc_text_end - text_p)); ssize_t progress = - WOLFSSL_TEXT_SEGMENT_CANONICALIZER( + WOLFSSL_SEGMENT_CANONICALIZER( text_p, - min(WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ, - (word32)((const u8 *)__wc_text_end - text_p)), + &text_in_out_len, 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", + pr_err("ERROR: progress=%ld from WOLFSSL_SEGMENT_CANONICALIZER() at offset %x (text=%x-%x).\n", (long)progress, (unsigned)(uintptr_t)text_p, (unsigned)(uintptr_t)__wc_text_start, @@ -740,10 +743,32 @@ static int wolfssl_init(void) free(canon_buf); return -ECANCELED; } - stabilized_text_hash = hash_span(canon_buf, canon_buf + progress, stabilized_text_hash); + stabilized_text_hash = hash_span(canon_buf, canon_buf + text_in_out_len, stabilized_text_hash); text_p += progress; } + /* note verifyCore is hashed along with the rest of .rodata_wolfcrypt. */ + while (rodata_p < (const u8 *)__wc_rodata_end) { + size_t rodata_in_out_len = min(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ, + (size_t)((const u8 *)__wc_rodata_end - rodata_p)); + ssize_t progress = + WOLFSSL_SEGMENT_CANONICALIZER( + rodata_p, + &rodata_in_out_len, + canon_buf, &cur_reloc_index); + if (progress <= 0) { + pr_err("ERROR: progress=%ld from WOLFSSL_SEGMENT_CANONICALIZER() at offset %x (rodata=%x-%x).\n", + (long)progress, + (unsigned)(uintptr_t)rodata_p, + (unsigned)(uintptr_t)__wc_rodata_start, + (unsigned)(uintptr_t)__wc_rodata_end); + free(canon_buf); + return -ECANCELED; + } + stabilized_rodata_hash = hash_span(canon_buf, canon_buf + rodata_in_out_len, stabilized_rodata_hash); + rodata_p += progress; + } + free(canon_buf); canon_buf = 0; @@ -1120,6 +1145,8 @@ MODULE_VERSION(LIBWOLFSSL_VERSION_STRING); extern const struct wc_reloc_table_ent wc_linuxkm_pie_text_reloc_tab[]; extern const unsigned int wc_linuxkm_pie_text_reloc_tab_length; +extern const struct wc_reloc_table_ent wc_linuxkm_pie_rodata_reloc_tab[]; +extern const unsigned int wc_linuxkm_pie_rodata_reloc_tab_length; static const struct wc_reloc_table_segments seg_map = { .start = 0, .end = 0, @@ -1129,6 +1156,10 @@ static const struct wc_reloc_table_segments seg_map = { .text_reloc_tab.end = 0, .text_reloc_tab.len_start = (size_t)(uintptr_t)&wc_linuxkm_pie_text_reloc_tab_length, .text_reloc_tab.len_end = 0, + .rodata_reloc_tab.start = (size_t)(uintptr_t)wc_linuxkm_pie_rodata_reloc_tab, + .rodata_reloc_tab.end = 0, + .rodata_reloc_tab.len_start = (size_t)(uintptr_t)&wc_linuxkm_pie_rodata_reloc_tab_length, + .rodata_reloc_tab.len_end = 0, #ifdef HAVE_FIPS #ifdef WC_USE_PIE_FENCEPOSTS_FOR_FIPS .fips_text_start = (size_t)(uintptr_t)__wc_text_start, @@ -1161,18 +1192,40 @@ static const struct wc_reloc_table_segments seg_map = { }; ssize_t wc_linuxkm_normalize_relocations( - const u8 *text_in, - size_t text_in_len, - u8 *text_out, + const u8 *seg_in, + size_t *seg_in_out_len, + u8 *seg_out, + ssize_t *cur_index_p) +{ + return wc_reloc_normalize_segment(seg_in, seg_in_out_len, seg_out, cur_index_p, &seg_map, +#ifdef DEBUG_LINUXKM_PIE_SUPPORT + &reloc_counts +#else + NULL +#endif + ); +} + +ssize_t wc_linuxkm_normalize_relocations_noresize( + const u8 *seg_in, + size_t seg_in_len, + u8 *seg_out, ssize_t *cur_index_p) { - return wc_reloc_normalize_text(text_in, text_in_len, text_out, cur_index_p, &seg_map, + ssize_t ret; + ret = wc_reloc_normalize_segment(seg_in, &seg_in_len, seg_out, cur_index_p, &seg_map, #ifdef DEBUG_LINUXKM_PIE_SUPPORT &reloc_counts #else NULL #endif ); + if (ret < 0) + return ret; + if ((size_t)ret != seg_in_len) + return -EINVAL; + else + return seg_in_len; } #elif defined(HAVE_FIPS) @@ -1227,6 +1280,8 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) { #ifdef HAVE_FIPS wolfssl_linuxkm_pie_redirect_table.wc_linuxkm_normalize_relocations = wc_linuxkm_normalize_relocations; + wolfssl_linuxkm_pie_redirect_table.wc_linuxkm_normalize_relocations_noresize = + wc_linuxkm_normalize_relocations_noresize; #endif #ifndef __ARCH_MEMCMP_NO_REDIRECT From b7ed41357197648b41f916b08c331d5dd0df0b5a Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Tue, 28 Apr 2026 15:05:30 -0500 Subject: [PATCH 5/8] wolfcrypt/src/wc_lms_impl.c: work around false-positive -Wmaybe-uninitialized in wc_lms_treehash_update(). --- wolfcrypt/src/wc_lms_impl.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/wolfcrypt/src/wc_lms_impl.c b/wolfcrypt/src/wc_lms_impl.c index a6fc89da7f5..8681080c943 100644 --- a/wolfcrypt/src/wc_lms_impl.c +++ b/wolfcrypt/src/wc_lms_impl.c @@ -2418,10 +2418,12 @@ static int wc_lms_treehash_update(LmsState* state, LmsPrivState* privState, } } - if (!useRoot && (ret == 0)) { - /* Copy stack back. */ - XMEMCPY(stackCache->stack, stack, params->height * params->hash_len); - stackCache->offset = (word32)((size_t)sp - (size_t)stack); + if (ret == 0) { + if (!useRoot) { + /* Copy stack back. */ + XMEMCPY(stackCache->stack, stack, params->height * params->hash_len); + stackCache->offset = (word32)((size_t)sp - (size_t)stack); + } } WC_FREE_VAR_EX(stack, NULL, DYNAMIC_TYPE_TMP_BUFFER); From 559b20750639e9f3384f09a5b40fc76874c0fdc6 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Tue, 28 Apr 2026 17:38:22 -0500 Subject: [PATCH 6/8] linuxkm/lkcapi_*.c and linuxkm/module_hooks.c: add missing linefeed characters in format args to pr_*(), for proper line flushing. --- linuxkm/lkcapi_dh_glue.c | 46 ++++++++++----------- linuxkm/lkcapi_ecdh_glue.c | 28 ++++++------- linuxkm/lkcapi_glue.c | 22 +++++----- linuxkm/lkcapi_rsa_glue.c | 18 ++++---- linuxkm/lkcapi_sha_glue.c | 84 +++++++++++++++++++------------------- linuxkm/module_hooks.c | 14 +++---- 6 files changed, 106 insertions(+), 106 deletions(-) diff --git a/linuxkm/lkcapi_dh_glue.c b/linuxkm/lkcapi_dh_glue.c index 9e885ed856c..6caabf06ac8 100644 --- a/linuxkm/lkcapi_dh_glue.c +++ b/linuxkm/lkcapi_dh_glue.c @@ -347,7 +347,7 @@ static int km_dh_decode_secret(const u8 * buf, unsigned int len, if (secret.len != expected_len) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: km_dh_decode_secret: got %d, expected %zu", + pr_err("%s: km_dh_decode_secret: got %d, expected %zu\n", WOLFKM_DH_DRIVER, secret.len, expected_len); #endif /* WOLFKM_DEBUG_DH */ return -EINVAL; @@ -413,7 +413,7 @@ static int km_dh_alloc_keys(struct km_dh_ctx * ctx) alloc_keys_end: if (err) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: km_dh_alloc_keys failed: %d", + pr_err("%s: km_dh_alloc_keys failed: %d\n", WOLFKM_DH_DRIVER, err); #endif km_dh_clear_keys(ctx); @@ -478,7 +478,7 @@ static int km_dh_set_secret(struct crypto_kpp *tfm, const void *buf, if (km_dh_decode_secret(buf, len, ¶ms) < 0) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: dh_set_secret: decode secret failed: %d", + pr_err("%s: dh_set_secret: decode secret failed: %d\n", WOLFKM_DH_DRIVER, params.key_size); #endif /* WOLFKM_DEBUG_DH */ err = -EINVAL; @@ -488,7 +488,7 @@ static int km_dh_set_secret(struct crypto_kpp *tfm, const void *buf, /* the key, p, and g, must all be provided for normal dh. */ if (!params.key || !params.key_size || !params.p_size || !params.g_size) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: dh_set_secret: empty params", WOLFKM_DH_DRIVER); + pr_err("%s: dh_set_secret: empty params\n", WOLFKM_DH_DRIVER); #endif err = -EINVAL; goto dh_secret_end; @@ -496,7 +496,7 @@ static int km_dh_set_secret(struct crypto_kpp *tfm, const void *buf, if (params.key_size > params.p_size || params.g_size > params.p_size) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: dh_set_secret: invalid params", WOLFKM_DH_DRIVER); + pr_err("%s: dh_set_secret: invalid params\n", WOLFKM_DH_DRIVER); #endif err = -EINVAL; goto dh_secret_end; @@ -518,7 +518,7 @@ static int km_dh_set_secret(struct crypto_kpp *tfm, const void *buf, if (err) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: wc_DhSetKey failed: %d", WOLFKM_DH_DRIVER, err); + pr_err("%s: wc_DhSetKey failed: %d\n", WOLFKM_DH_DRIVER, err); #endif err = -EINVAL; goto dh_secret_end; @@ -530,7 +530,7 @@ static int km_dh_set_secret(struct crypto_kpp *tfm, const void *buf, if (err) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: wc_DhImportKeyPair failed: %d", WOLFKM_DH_DRIVER, err); + pr_err("%s: wc_DhImportKeyPair failed: %d\n", WOLFKM_DH_DRIVER, err); #endif err = -EINVAL; goto dh_secret_end; @@ -585,7 +585,7 @@ static int km_ffdhe_set_secret(struct crypto_kpp *tfm, const void *buf, if (err) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: ffdhe_set_secret: decode secret failed: %d", + pr_err("%s: ffdhe_set_secret: decode secret failed: %d\n", WOLFKM_DH_DRIVER, params.key_size); #endif /* WOLFKM_DEBUG_DH */ err = -EINVAL; @@ -595,7 +595,7 @@ static int km_ffdhe_set_secret(struct crypto_kpp *tfm, const void *buf, /* p_size and g_size should be 0 for ffdhe. */ if (params.p_size || params.g_size) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: ffdhe_set_secret: unexpected p, g params: %d, %d", + pr_err("%s: ffdhe_set_secret: unexpected p, g params: %d, %d\n", WOLFKM_DH_DRIVER, params.p_size, params.g_size); #endif /* WOLFKM_DEBUG_DH */ err = -EINVAL; @@ -616,7 +616,7 @@ static int km_ffdhe_set_secret(struct crypto_kpp *tfm, const void *buf, if (!params.key_size) { /* generate the ffdhe key pair*/ #ifdef WOLFKM_DEBUG_DH - pr_info("ffdhe gen key pair"); + pr_info("ffdhe gen key pair\n"); #endif PRIVATE_KEY_UNLOCK(); err = wc_DhGenerateKeyPair(ctx->key, &ctx->rng, @@ -626,7 +626,7 @@ static int km_ffdhe_set_secret(struct crypto_kpp *tfm, const void *buf, if (err) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: wc_DhGenerateKeyPair failed: %d", + pr_err("%s: wc_DhGenerateKeyPair failed: %d\n", WOLFKM_DH_DRIVER, err); #endif err = -EINVAL; @@ -641,7 +641,7 @@ static int km_ffdhe_set_secret(struct crypto_kpp *tfm, const void *buf, if (ctx->pub_len < (ctx->nbits / WOLFSSL_BIT_SIZE)) { word32 pad_len = ctx->nbits / WOLFSSL_BIT_SIZE - ctx->pub_len; #ifdef WOLFKM_DEBUG_DH - pr_info("info: km_ffdhe_set_secret: pub key padding %d", pad_len); + pr_info("info: km_ffdhe_set_secret: pub key padding %d\n", pad_len); #endif memmove(ctx->pub_key + pad_len, ctx->pub_key, ctx->pub_len); @@ -660,7 +660,7 @@ static int km_ffdhe_set_secret(struct crypto_kpp *tfm, const void *buf, if (err) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: wc_DhImportKeyPair failed: %d", + pr_err("%s: wc_DhImportKeyPair failed: %d\n", WOLFKM_DH_DRIVER, err); #endif err = -EINVAL; @@ -783,7 +783,7 @@ static int km_ffdhe_init(struct crypto_kpp *tfm, int name, word32 nbits) } #ifdef WOLFKM_DEBUG_DH - pr_info("info: exiting km_dh_init: name %d, nbits %d", + pr_info("info: exiting km_dh_init: name %d, nbits %d\n", ctx->name, ctx->nbits); #endif /* WOLFKM_DEBUG_DH */ return 0; @@ -874,7 +874,7 @@ static int km_dh_gen_pub(struct kpp_request *req) if (ctx->pub_len > req->dst_len) { #ifdef WOLFKM_DEBUG_DH - pr_err("error: dst_len too small: %d", req->dst_len); + pr_err("error: dst_len too small: %d\n", req->dst_len); #endif /* WOLFKM_DEBUG_DH */ req->dst_len = ctx->pub_len; return -EOVERFLOW; @@ -885,7 +885,7 @@ static int km_dh_gen_pub(struct kpp_request *req) err = 0; #ifdef WOLFKM_DEBUG_DH - pr_info("info: exiting km_dh_gen_pub: %d", ctx->pub_len); + pr_info("info: exiting km_dh_gen_pub: %d\n", ctx->pub_len); #endif /* WOLFKM_DEBUG_DH */ return err; } @@ -921,7 +921,7 @@ static int km_dh_compute_shared_secret(struct kpp_request *req) if (req->src_len <= 0 || req->src_len > (ctx->nbits / WOLFSSL_BIT_SIZE)) { #ifdef WOLFKM_DEBUG_DH - pr_err("error: got src_len %d, expected %d", req->src_len, + pr_err("error: got src_len %d, expected %d\n", req->src_len, (ctx->nbits / WOLFSSL_BIT_SIZE)); #endif /* WOLFKM_DEBUG_DH */ err = -EINVAL; @@ -2903,7 +2903,7 @@ static int linuxkm_test_kpp_driver(const char * driver, dst_buf = malloc(dst_len); if (dst_buf == NULL) { - pr_err("error: allocating out buf failed"); + pr_err("error: allocating out buf failed\n"); test_rc = MEMORY_E; goto test_kpp_end; } @@ -2917,20 +2917,20 @@ static int linuxkm_test_kpp_driver(const char * driver, err = crypto_kpp_generate_public_key(req); if (err) { - pr_err("error: crypto_kpp_generate_public_key returned: %d", err); + pr_err("error: crypto_kpp_generate_public_key returned: %d\n", err); test_rc = BAD_FUNC_ARG; goto test_kpp_end; } if (memcmp(expected_a_pub, sg_virt(req->dst), pub_len)) { - pr_err("error: crypto_kpp_generate_public_key: wrong output"); + pr_err("error: crypto_kpp_generate_public_key: wrong output\n"); test_rc = WC_KEY_MISMATCH_E; goto test_kpp_end; } src_buf = malloc(src_len); if (src_buf == NULL) { - pr_err("error: allocating in buf failed"); + pr_err("error: allocating in buf failed\n"); test_rc = MEMORY_E; goto test_kpp_end; } @@ -2945,13 +2945,13 @@ static int linuxkm_test_kpp_driver(const char * driver, err = crypto_kpp_compute_shared_secret(req); if (err) { - pr_err("error: crypto_kpp_compute_shared_secret returned: %d", err); + pr_err("error: crypto_kpp_compute_shared_secret returned: %d\n", err); test_rc = BAD_FUNC_ARG; goto test_kpp_end; } if (memcmp(shared_secret, sg_virt(req->dst), shared_s_len)) { - pr_err("error: shared secret does not match"); + pr_err("error: shared secret does not match\n"); test_rc = BAD_FUNC_ARG; goto test_kpp_end; } diff --git a/linuxkm/lkcapi_ecdh_glue.c b/linuxkm/lkcapi_ecdh_glue.c index 86cef12ee3a..2f88bd20377 100644 --- a/linuxkm/lkcapi_ecdh_glue.c +++ b/linuxkm/lkcapi_ecdh_glue.c @@ -199,7 +199,7 @@ static int km_ecdh_decode_secret(const u8 * buf, unsigned int len, if (secret.len != expected_len) { #ifdef WOLFKM_DEBUG_ECDH - pr_err("%s: km_ecdh_decode_secret: got %d, expected %zu", + pr_err("%s: km_ecdh_decode_secret: got %d, expected %zu\n", WOLFKM_ECDH_DRIVER, secret.len, expected_len); #endif /* WOLFKM_DEBUG_ECDH */ return -EINVAL; @@ -249,7 +249,7 @@ static int km_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, if (km_ecdh_decode_secret(buf, len, ¶ms) < 0) { #ifdef WOLFKM_DEBUG_ECDH - pr_err("%s: ecdh_set_secret: decode secret failed: %d", + pr_err("%s: ecdh_set_secret: decode secret failed: %d\n", WOLFKM_ECDH_DRIVER, params.key_size); #endif /* WOLFKM_DEBUG_ECDH */ return -EINVAL; @@ -417,7 +417,7 @@ static int km_ecdh_init(struct crypto_kpp *tfm, int curve_id) #endif /* ECC_TIMING_RESISTANT */ #ifdef WOLFKM_DEBUG_ECDH - pr_info("info: exiting km_ecdh_init: curve_id %d, curve_len %d", + pr_info("info: exiting km_ecdh_init: curve_id %d, curve_len %d\n", ctx->curve_id, ctx->curve_len); #endif /* WOLFKM_DEBUG_ECDH */ return 0; @@ -484,7 +484,7 @@ static int km_ecdh_gen_pub(struct kpp_request *req) if (raw_pub_len > req->dst_len) { #ifdef WOLFKM_DEBUG_ECDH - pr_err("error: dst_len too small: %d", req->dst_len); + pr_err("error: dst_len too small: %d\n", req->dst_len); #endif /* WOLFKM_DEBUG_ECDH */ err = -EOVERFLOW; goto ecdh_gen_pub_end; @@ -504,7 +504,7 @@ static int km_ecdh_gen_pub(struct kpp_request *req) err = wc_ecc_make_pub(ctx->key, NULL); if (err) { #ifdef WOLFKM_DEBUG_ECDH - pr_err("error: ecc_make_pub returned: %d", err); + pr_err("error: ecc_make_pub returned: %d\n", err); #endif /* WOLFKM_DEBUG_ECDH */ goto ecdh_gen_pub_end; } @@ -522,7 +522,7 @@ static int km_ecdh_gen_pub(struct kpp_request *req) if (err || pub_x_len != ctx->curve_len || pub_y_len != ctx->curve_len) { #ifdef WOLFKM_DEBUG_ECDH - pr_err("error: ecc export pub returned: err=%d, x=%d, y=%d", err, + pr_err("error: ecc export pub returned: err=%d, x=%d, y=%d\n", err, pub_x_len, pub_y_len); #endif /* WOLFKM_DEBUG_ECDH */ err = -EINVAL; @@ -537,7 +537,7 @@ static int km_ecdh_gen_pub(struct kpp_request *req) if (pub) { free(pub); pub = NULL; } #ifdef WOLFKM_DEBUG_ECDH - pr_info("info: exiting km_ecdh_gen_pub: %d", err); + pr_info("info: exiting km_ecdh_gen_pub: %d\n", err); #endif /* WOLFKM_DEBUG_ECDH */ return err; } @@ -584,7 +584,7 @@ static int km_ecdh_compute_shared_secret(struct kpp_request *req) if (req->src_len != raw_pub_len) { #ifdef WOLFKM_DEBUG_ECDH - pr_err("error: got src_len %d, expected %d", req->src_len, raw_pub_len); + pr_err("error: got src_len %d, expected %d\n", req->src_len, raw_pub_len); #endif /* WOLFKM_DEBUG_ECDH */ err = -EINVAL; goto ecdh_shared_secret_end; @@ -928,7 +928,7 @@ static int linuxkm_test_ecdh_nist_driver(const char * driver, dst_buf = malloc(dst_len); if (dst_buf == NULL) { - pr_err("error: allocating out buf failed"); + pr_err("error: allocating out buf failed\n"); test_rc = BAD_FUNC_ARG; goto test_ecdh_nist_end; } @@ -942,20 +942,20 @@ static int linuxkm_test_ecdh_nist_driver(const char * driver, err = crypto_kpp_generate_public_key(req); if (err) { - pr_err("error: crypto_kpp_generate_public_key returned: %d", err); + pr_err("error: crypto_kpp_generate_public_key returned: %d\n", err); test_rc = BAD_FUNC_ARG; goto test_ecdh_nist_end; } if (memcmp(expected_a_pub, sg_virt(req->dst), pub_len)) { - pr_err("error: crypto_kpp_generate_public_key: wrong output"); + pr_err("error: crypto_kpp_generate_public_key: wrong output\n"); test_rc = BAD_FUNC_ARG; goto test_ecdh_nist_end; } src_buf = malloc(src_len); if (src_buf == NULL) { - pr_err("error: allocating in buf failed"); + pr_err("error: allocating in buf failed\n"); test_rc = MEMORY_E; goto test_ecdh_nist_end; } @@ -970,13 +970,13 @@ static int linuxkm_test_ecdh_nist_driver(const char * driver, err = crypto_kpp_compute_shared_secret(req); if (err) { - pr_err("error: crypto_kpp_compute_shared_secret returned: %d", err); + pr_err("error: crypto_kpp_compute_shared_secret returned: %d\n", err); test_rc = BAD_FUNC_ARG; goto test_ecdh_nist_end; } if (memcmp(shared_secret, sg_virt(req->dst), shared_s_len)) { - pr_err("error: shared secret does not match"); + pr_err("error: shared secret does not match\n"); test_rc = BAD_FUNC_ARG; goto test_ecdh_nist_end; } diff --git a/linuxkm/lkcapi_glue.c b/linuxkm/lkcapi_glue.c index f88da9e2bb4..4bb25a72982 100644 --- a/linuxkm/lkcapi_glue.c +++ b/linuxkm/lkcapi_glue.c @@ -244,7 +244,7 @@ static ssize_t install_algs_handler(struct kobject *kobj, struct kobj_attribute if (kstrtoint(buf, 10, &arg) || arg != 1) return -EINVAL; - pr_info("wolfCrypt: Installing algorithms"); + pr_info("wolfCrypt: Installing algorithms\n"); ret = linuxkm_lkcapi_register(); if (ret != 0) @@ -265,7 +265,7 @@ static ssize_t deinstall_algs_handler(struct kobject *kobj, struct kobj_attribut if (kstrtoint(buf, 10, &arg) || arg != 1) return -EINVAL; - pr_info("wolfCrypt: Deinstalling algorithms"); + pr_info("wolfCrypt: Deinstalling algorithms\n"); ret = linuxkm_lkcapi_unregister(); if (ret != 0) @@ -274,7 +274,7 @@ static ssize_t deinstall_algs_handler(struct kobject *kobj, struct kobj_attribut #if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \ !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) if (enabled_fips) { - pr_info("wolfCrypt: restoring fips_enabled to off."); + pr_info("wolfCrypt: restoring fips_enabled to off.\n"); enabled_fips = fips_enabled = 0; } #endif @@ -358,7 +358,7 @@ static int linuxkm_lkcapi_register(void) /* assert system-wide FIPS status, to disable FIPS-forbidden * test vectors and fuzzing from the CRYPTO_MANAGER. */ - pr_info("wolfCrypt: changing fips_enabled from 0 to 1 for FIPS module."); + pr_info("wolfCrypt: changing fips_enabled from 0 to 1 for FIPS module.\n"); enabled_fips = fips_enabled = 1; } #endif @@ -382,7 +382,7 @@ static int linuxkm_lkcapi_register(void) if (! ((alg).base.cra_flags & CRYPTO_ALG_DEAD)) { \ pr_err("ERROR: alg %s not _DEAD " \ "after crypto_unregister_%s -- " \ - "marking as loaded despite test failure.", \ + "marking as loaded despite test failure.\n", \ (alg).base.cra_driver_name, \ #alg_class); \ alg ## _loaded = 1; \ @@ -434,7 +434,7 @@ static int linuxkm_lkcapi_register(void) if (! ((alg).base.cra_flags & CRYPTO_ALG_DEAD)) { \ pr_err("ERROR: alg %s not _DEAD " \ "after crypto_unregister_%s -- " \ - "marking as loaded despite test failure.", \ + "marking as loaded despite test failure.\n", \ (alg).base.cra_driver_name, \ #alg_class); \ alg ## _loaded = 1; \ @@ -729,7 +729,7 @@ static int linuxkm_lkcapi_register(void) disable_setkey_warnings = 0; #endif - pr_info("wolfCrypt: %d algorithm%s registered.", linuxkm_lkcapi_n_registered, + pr_info("wolfCrypt: %d algorithm%s registered.\n", linuxkm_lkcapi_n_registered, linuxkm_lkcapi_n_registered == 1 ? "" : "s"); if (ret == -1) { @@ -794,7 +794,7 @@ static int linuxkm_lkcapi_unregister(void) do { \ if (alg ## _loaded) { \ if ((alg).base.cra_flags & CRYPTO_ALG_DEAD) { \ - pr_err("alg %s already CRYPTO_ALG_DEAD.", \ + pr_err("alg %s already CRYPTO_ALG_DEAD.\n", \ (alg).base.cra_driver_name); \ alg ## _loaded = 0; \ ++n_deregistered; \ @@ -807,7 +807,7 @@ static int linuxkm_lkcapi_unregister(void) if (! ((alg).base.cra_flags & CRYPTO_ALG_DEAD)) { \ pr_err("ERROR: alg %s not _DEAD after " \ "crypto_unregister_%s -- " \ - "leaving marked as loaded.", \ + "leaving marked as loaded.\n", \ (alg).base.cra_driver_name, \ #alg_class); \ seen_err = -EBUSY; \ @@ -817,7 +817,7 @@ static int linuxkm_lkcapi_unregister(void) } \ } \ else { \ - pr_err("alg %s cannot be uninstalled (refcnt = %d)", \ + pr_err("alg %s cannot be uninstalled (refcnt = %d)\n", \ (alg).base.cra_driver_name, cur_refcnt); \ if (cur_refcnt > 0) { seen_err = -EBUSY; } \ } \ @@ -1025,7 +1025,7 @@ static int linuxkm_lkcapi_unregister(void) #undef UNREGISTER_ALG linuxkm_lkcapi_n_registered -= n_deregistered; - pr_info("wolfCrypt: %d algorithm%s deregistered, %d remain%s registered.", + pr_info("wolfCrypt: %d algorithm%s deregistered, %d remain%s registered.\n", n_deregistered, n_deregistered == 1 ? "" : "s", linuxkm_lkcapi_n_registered, linuxkm_lkcapi_n_registered == 1 ? "s" : ""); diff --git a/linuxkm/lkcapi_rsa_glue.c b/linuxkm/lkcapi_rsa_glue.c index 056a0d589db..e38dfaf28cf 100644 --- a/linuxkm/lkcapi_rsa_glue.c +++ b/linuxkm/lkcapi_rsa_glue.c @@ -1172,7 +1172,7 @@ static int km_pkcs1pad_sign(struct akcipher_request *req) #ifdef WOLFKM_DEBUG_RSA pr_info("info: exiting km_pkcs1pad_sign msg_len %d, enc_msg_len %d," - " sig_len %d, err %d", req->src_len, enc_len, sig_len, err); + " sig_len %d, err %d\n", req->src_len, enc_len, sig_len, err); #endif /* WOLFKM_DEBUG_RSA */ return err; } @@ -1223,7 +1223,7 @@ static int km_pkcs1pad_verify(struct akcipher_request *req) hash_enc_len = get_hash_enc_len(ctx->hash_oid); if (hash_enc_len <= 0) { #ifdef WOLFKM_DEBUG_RSA - pr_err("error: %s: bad hash enc len %d", + pr_err("error: %s: bad hash enc len %d\n", WOLFKM_RSA_DRIVER, hash_enc_len); #endif /* WOLFKM_DEBUG_RSA */ err = -EINVAL; @@ -1233,7 +1233,7 @@ static int km_pkcs1pad_verify(struct akcipher_request *req) if (msg_len != ctx->digest_len || sig_len != ctx->key_len) { /* invalid src or dst args */ #ifdef WOLFKM_DEBUG_RSA - pr_err("error: %s: got msg_len %d, expected %d", + pr_err("error: %s: got msg_len %d, expected %d\n", WOLFKM_RSA_DRIVER, msg_len, ctx->digest_len); #endif /* WOLFKM_DEBUG_RSA */ err = -EINVAL; @@ -1287,7 +1287,7 @@ static int km_pkcs1pad_verify(struct akcipher_request *req) #ifdef WOLFKM_DEBUG_RSA pr_info("info: exiting km_pkcs1pad_verify msg_len %d, enc_msg_len %d," - " sig_len %d, err %d", msg_len, enc_msg_len, sig_len, err); + " sig_len %d, err %d\n", msg_len, enc_msg_len, sig_len, err); #endif /* WOLFKM_DEBUG_RSA */ return err; } @@ -1420,7 +1420,7 @@ static int km_pkcs1_sign(struct crypto_sig *tfm, #ifdef WOLFKM_DEBUG_RSA pr_info("info: exiting km_pkcs1_sign msg_len %d, enc_msg_len %d," - " sig_len %d, err %d", slen, enc_msg_len, sig_len, err); + " sig_len %d, err %d\n", slen, enc_msg_len, sig_len, err); #endif /* WOLFKM_DEBUG_RSA */ return err; } @@ -1474,7 +1474,7 @@ static int km_pkcs1_verify(struct crypto_sig *tfm, hash_enc_len = get_hash_enc_len(ctx->hash_oid); if (hash_enc_len <= 0) { #ifdef WOLFKM_DEBUG_RSA - pr_err("error: %s: bad hash enc len %d", + pr_err("error: %s: bad hash enc len %d\n", WOLFKM_RSA_DRIVER, hash_enc_len); #endif /* WOLFKM_DEBUG_RSA */ err = -EINVAL; @@ -1484,7 +1484,7 @@ static int km_pkcs1_verify(struct crypto_sig *tfm, if (msg_len != ctx->digest_len || sig_len != ctx->key_len) { /* invalid src or dst args */ #ifdef WOLFKM_DEBUG_RSA - pr_err("error: %s: got msg_len %d, expected %d", + pr_err("error: %s: got msg_len %d, expected %d\n", WOLFKM_RSA_DRIVER, msg_len, ctx->digest_len); #endif /* WOLFKM_DEBUG_RSA */ err = -EINVAL; @@ -1538,7 +1538,7 @@ static int km_pkcs1_verify(struct crypto_sig *tfm, #ifdef WOLFKM_DEBUG_RSA pr_info("info: exiting km_pkcs1_verify msg_len %d, enc_msg_len %d," - " sig_len %d, err %d", msg_len, enc_msg_len, sig_len, err); + " sig_len %d, err %d\n", msg_len, enc_msg_len, sig_len, err); #endif /* WOLFKM_DEBUG_RSA */ return err; } @@ -1817,7 +1817,7 @@ static int km_pkcs1pad_dec(struct akcipher_request *req) if (dec != NULL) { free(dec); dec = NULL; } #ifdef WOLFKM_DEBUG_RSA - pr_info("info: exiting km_pkcs1pad_dec %d", err); + pr_info("info: exiting km_pkcs1pad_dec %d\n", err); #endif /* WOLFKM_DEBUG_RSA */ return err; } diff --git a/linuxkm/lkcapi_sha_glue.c b/linuxkm/lkcapi_sha_glue.c index 6a75afc95f0..39754a64240 100644 --- a/linuxkm/lkcapi_sha_glue.c +++ b/linuxkm/lkcapi_sha_glue.c @@ -1188,7 +1188,7 @@ static int wc_linuxkm_drbg_generate(struct wc_rng_bank *ctx, struct wc_rng_bank_inst *drbg = linuxkm_get_drbg(ctx); if (! drbg) { - pr_err_once("BUG: linuxkm_get_drbg() failed."); + pr_err_once("BUG: linuxkm_get_drbg() failed.\n"); return -EFAULT; } @@ -1235,11 +1235,11 @@ static int wc_linuxkm_drbg_generate(struct wc_rng_bank *ctx, WC_RNG_BANK_FLAG_CAN_WAIT); if (ret == 0) { - pr_warn("WARNING: reinitialized DRBG #%d after RNG_FAILURE_E from wc_RNG_GenerateBlock().", raw_smp_processor_id()); + pr_warn("WARNING: reinitialized DRBG #%d after RNG_FAILURE_E from wc_RNG_GenerateBlock().\n", raw_smp_processor_id()); continue; } else { - pr_warn_once("ERROR: reinitialization of DRBG #%d after RNG_FAILURE_E failed with ret %d.", raw_smp_processor_id(), ret); + pr_warn_once("ERROR: reinitialization of DRBG #%d after RNG_FAILURE_E failed with ret %d.\n", raw_smp_processor_id(), ret); ret = -EINVAL; break; } @@ -1264,7 +1264,7 @@ static int wc_linuxkm_drbg_generate_tfm(struct crypto_rng *tfm, { if (tfm->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm) { - pr_err_once("BUG: mismatched tfm."); + pr_err_once("BUG: mismatched tfm.\n"); return -EFAULT; } @@ -1294,7 +1294,7 @@ static int wc_linuxkm_drbg_seed_tfm(struct crypto_rng *tfm, { if (tfm->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm) { - pr_err_once("BUG: mismatched tfm."); + pr_err_once("BUG: mismatched tfm.\n"); return -EFAULT; } @@ -1354,7 +1354,7 @@ static int wc__get_random_bytes(void *buf, size_t len) NULL, 0, buf, len); (void)wc_rng_bank_default_checkin(¤t_default_wc_rng_bank); if (ret) { - pr_warn("BUG: wc__get_random_bytes falling through to native get_random_bytes with wc_linuxkm_drbg_default_instance_registered, ret=%d.", ret); + pr_warn("BUG: wc__get_random_bytes falling through to native get_random_bytes with wc_linuxkm_drbg_default_instance_registered, ret=%d.\n", ret); } return ret; } @@ -1383,7 +1383,7 @@ static ssize_t wc_get_random_bytes_user(struct iov_iter *iter) { ret = wc_linuxkm_drbg_generate(current_default_wc_rng_bank, NULL, 0, block, sizeof block); if (unlikely(ret != 0)) { - pr_err("ERROR: wc_get_random_bytes_user() wc_linuxkm_drbg_generate() returned %d.", ret); + pr_err("ERROR: wc_get_random_bytes_user() wc_linuxkm_drbg_generate() returned %d.\n", ret); break; } @@ -1445,7 +1445,7 @@ static ssize_t wc_extract_crng_user(void __user *buf, size_t nbytes) { ret = wc_linuxkm_drbg_generate(current_default_wc_rng_bank, NULL, 0, block, sizeof block); if (unlikely(ret != 0)) { - pr_err("ERROR: wc_extract_crng_user() wc_linuxkm_drbg_generate() returned %d.", ret); + pr_err("ERROR: wc_extract_crng_user() wc_linuxkm_drbg_generate() returned %d.\n", ret); break; } @@ -1610,10 +1610,10 @@ static int wc_get_random_bytes_by_kprobe(struct kprobe *p, struct pt_regs *regs) regs->ip = (unsigned long)p->addr + p->ainsn.size; return 1; /* Handled. */ } - pr_warn("BUG: wc_get_random_bytes_by_kprobe falling through to native get_random_bytes with wc_linuxkm_drbg_default_instance_registered, ret=%d.", ret); + pr_warn("BUG: wc_get_random_bytes_by_kprobe falling through to native get_random_bytes with wc_linuxkm_drbg_default_instance_registered, ret=%d.\n", ret); } else - pr_warn("BUG: wc_get_random_bytes_by_kprobe called without wc_linuxkm_drbg_default_instance_registered."); + pr_warn("BUG: wc_get_random_bytes_by_kprobe called without wc_linuxkm_drbg_default_instance_registered.\n"); /* Not handled. Fall through to native implementation, given * that the alternative is an immediate kernel panic. @@ -1668,7 +1668,7 @@ static int wc_get_random_bytes_user_kretprobe_enter(struct kretprobe_instance *p byte block[WC_SHA256_BLOCK_SIZE]; if (unlikely(!wc_linuxkm_drbg_default_instance_registered)) { - pr_warn("BUG: wc_get_random_bytes_user_kretprobe_enter() without wc_linuxkm_drbg_default_instance_registered."); + pr_warn("BUG: wc_get_random_bytes_user_kretprobe_enter() without wc_linuxkm_drbg_default_instance_registered.\n"); ret = -ENOENT; goto out; } @@ -1681,7 +1681,7 @@ static int wc_get_random_bytes_user_kretprobe_enter(struct kretprobe_instance *p for (;;) { ret = crypto_rng_get_bytes(crypto_default_rng, block, sizeof block); if (ret != 0) { - pr_err("ERROR: wc_get_random_bytes_user_kretprobe_enter() crypto_rng_get_bytes() returned %d.", ret); + pr_err("ERROR: wc_get_random_bytes_user_kretprobe_enter() crypto_rng_get_bytes() returned %d.\n", ret); break; } @@ -1714,7 +1714,7 @@ static int wc_get_random_bytes_user_kretprobe_enter(struct kretprobe_instance *p if ((ret != 0) && (this_copied == (size_t)(-1L))) { /* crypto_rng_get_bytes() failed on the first call, before any update to the iov_iter. */ - pr_warn("WARNING: wc_get_random_bytes_user_kretprobe_enter() falling through to native get_random_bytes_user()."); + pr_warn("WARNING: wc_get_random_bytes_user_kretprobe_enter() falling through to native get_random_bytes_user().\n"); return -EFAULT; } @@ -1741,7 +1741,7 @@ static int wc_get_random_bytes_user_kretprobe_exit(struct kretprobe_instance *p, struct wc_get_random_bytes_user_kretprobe_ctx *ctx = (struct wc_get_random_bytes_user_kretprobe_ctx *)p->data; if (unlikely(!wc_linuxkm_drbg_default_instance_registered)) { - pr_warn("BUG: wc_get_random_bytes_user_kretprobe_exit without wc_linuxkm_drbg_default_instance_registered."); + pr_warn("BUG: wc_get_random_bytes_user_kretprobe_exit without wc_linuxkm_drbg_default_instance_registered.\n"); return -EFAULT; } @@ -1777,7 +1777,7 @@ static int wc_linuxkm_drbg_startup(void) int ret; if (wc_linuxkm_drbg_loaded) { - pr_err("ERROR: wc_linuxkm_drbg_set_default called with wc_linuxkm_drbg_loaded."); + pr_err("ERROR: wc_linuxkm_drbg_set_default called with wc_linuxkm_drbg_loaded.\n"); return -EBUSY; } @@ -1791,7 +1791,7 @@ static int wc_linuxkm_drbg_startup(void) ret = crypto_register_rng(&wc_linuxkm_drbg); if (ret != 0) { - pr_err("ERROR: crypto_register_rng: %d", ret); + pr_err("ERROR: crypto_register_rng: %d\n", ret); return ret; } @@ -1860,7 +1860,7 @@ static int wc_linuxkm_drbg_startup(void) } if (ret) - pr_err("ERROR: wc_linuxkm_drbg_startup: PRNG quality test failed, block length %d, iters %d, ret %d", + pr_err("ERROR: wc_linuxkm_drbg_startup: PRNG quality test failed, block length %d, iters %d, ret %d\n", i, j, ret); } } @@ -1890,7 +1890,7 @@ static int wc_linuxkm_drbg_startup(void) ret = crypto_del_default_rng(); if (ret) { wc_linuxkm_rng_initing_default_bank_flag = 0; - pr_err("ERROR: crypto_del_default_rng returned %d", ret); + pr_err("ERROR: crypto_del_default_rng returned %d\n", ret); return ret; } @@ -1899,27 +1899,27 @@ static int wc_linuxkm_drbg_startup(void) wc_linuxkm_rng_initing_default_bank_flag = 0; if (ret) { - pr_err("ERROR: crypto_get_default_rng returned %d", ret); + pr_err("ERROR: crypto_get_default_rng returned %d\n", ret); return ret; } { int cur_refcnt = WC_LKM_REFCOUNT_TO_INT(wc_linuxkm_drbg.base.cra_refcnt); if (cur_refcnt < 2) { - pr_err("ERROR: wc_linuxkm_drbg refcnt = %d after crypto_get_default_rng()", cur_refcnt); + pr_err("ERROR: wc_linuxkm_drbg refcnt = %d after crypto_get_default_rng()\n", cur_refcnt); crypto_put_default_rng(); return -EINVAL; } } if (! crypto_default_rng) { - pr_err("ERROR: crypto_default_rng is null"); + pr_err("ERROR: crypto_default_rng is null\n"); crypto_put_default_rng(); return -EINVAL; } if (crypto_default_rng->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm) { - pr_err("ERROR: %s NOT registered as systemwide default stdrng -- found \"%s\".", wc_linuxkm_drbg.base.cra_driver_name, crypto_tfm_alg_driver_name(&crypto_default_rng->base)); + pr_err("ERROR: %s NOT registered as systemwide default stdrng -- found \"%s\".\n", wc_linuxkm_drbg.base.cra_driver_name, crypto_tfm_alg_driver_name(&crypto_default_rng->base)); crypto_put_default_rng(); return -EINVAL; } @@ -1935,7 +1935,7 @@ static int wc_linuxkm_drbg_startup(void) ret = crypto_del_default_rng(); if (ret) { wc_linuxkm_rng_initing_default_bank_flag = 0; - pr_err("ERROR: crypto_del_default_rng returned %d", ret); + pr_err("ERROR: crypto_del_default_rng returned %d\n", ret); return ret; } @@ -1944,7 +1944,7 @@ static int wc_linuxkm_drbg_startup(void) wc_linuxkm_rng_initing_default_bank_flag = 0; if (ret) { - pr_err("ERROR: __crypto_stdrng_get_bytes returned %d", ret); + pr_err("ERROR: __crypto_stdrng_get_bytes returned %d\n", ret); return ret; } } @@ -1954,7 +1954,7 @@ static int wc_linuxkm_drbg_startup(void) ret = wc_linuxkm_rng_bank_init(&default_bank); wc_linuxkm_rng_initing_default_bank_flag = 0; if (ret) { - pr_err("ERROR: wc_linuxkm_rng_bank_init returned %d", ret); + pr_err("ERROR: wc_linuxkm_rng_bank_init returned %d\n", ret); return ret; } default_bank_inited = 1; @@ -1966,11 +1966,11 @@ static int wc_linuxkm_drbg_startup(void) struct wc_rng_bank *current_default_wc_rng_bank; ret = wc_rng_bank_default_checkout(¤t_default_wc_rng_bank); if (ret) - pr_err("ERROR: wc_rng_bank_default_checkout() after default stdrng registration returned %d", ret); + pr_err("ERROR: wc_rng_bank_default_checkout() after default stdrng registration returned %d\n", ret); else { ret = wc_rng_bank_default_checkin(¤t_default_wc_rng_bank); if (ret) - pr_err("ERROR: wc_rng_bank_default_checkin() after wc_rng_bank_default_checkout() returned %d", ret); + pr_err("ERROR: wc_rng_bank_default_checkin() after wc_rng_bank_default_checkout() returned %d\n", ret); } if (ret != 0) { #if defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT) && \ @@ -1986,8 +1986,8 @@ static int wc_linuxkm_drbg_startup(void) } wc_linuxkm_drbg_default_instance_registered = 1; - pr_info("%s registered as systemwide default stdrng.", wc_linuxkm_drbg.base.cra_driver_name); - pr_info("libwolfssl: to unload module, first echo 1 > /sys/module/libwolfssl/deinstall_algs"); + pr_info("%s registered as systemwide default stdrng.\n", wc_linuxkm_drbg.base.cra_driver_name); + pr_info("libwolfssl: to unload module, first echo 1 > /sys/module/libwolfssl/deinstall_algs\n"); #ifdef LINUXKM_DRBG_GET_RANDOM_BYTES @@ -1999,7 +1999,7 @@ static int wc_linuxkm_drbg_startup(void) if (ret == 0) { wc_get_random_bytes_callbacks_installed = 1; - pr_info("libwolfssl: kernel global random_bytes handlers installed."); + pr_info("libwolfssl: kernel global random_bytes handlers installed.\n"); } else { pr_err("ERROR: wolfssl_linuxkm_register_random_bytes_handlers() failed: %d\n", ret); @@ -2039,22 +2039,22 @@ static int wc_linuxkm_drbg_startup(void) byte scratch[4]; ret = wc__get_random_bytes(scratch, sizeof(scratch)); if (ret != 0) { - pr_err("ERROR: wc__get_random_bytes() returned %d", ret); + pr_err("ERROR: wc__get_random_bytes() returned %d\n", ret); return -EINVAL; } ret = wc_mix_pool_bytes(scratch, sizeof(scratch)); if (ret != 0) { - pr_err("ERROR: wc_mix_pool_bytes() returned %d", ret); + pr_err("ERROR: wc_mix_pool_bytes() returned %d\n", ret); return -EINVAL; } ret = wc_crng_reseed(); if (ret != 0) { - pr_err("ERROR: wc_crng_reseed() returned %d", ret); + pr_err("ERROR: wc_crng_reseed() returned %d\n", ret); return -EINVAL; } ret = wc__get_random_bytes(scratch, sizeof(scratch)); if (ret != 0) { - pr_err("ERROR: wc__get_random_bytes() returned %d", ret); + pr_err("ERROR: wc__get_random_bytes() returned %d\n", ret); return -EINVAL; } } @@ -2071,7 +2071,7 @@ static int wc_linuxkm_drbg_cleanup(void) { int cur_refcnt; if (! wc_linuxkm_drbg_loaded) { - pr_err("ERROR: wc_linuxkm_drbg_cleanup called with ! wc_linuxkm_drbg_loaded"); + pr_err("ERROR: wc_linuxkm_drbg_cleanup called with ! wc_linuxkm_drbg_loaded\n"); return -EINVAL; } @@ -2094,7 +2094,7 @@ static int wc_linuxkm_drbg_cleanup(void) { if (wc_get_random_bytes_callbacks_installed) { ret = wolfssl_linuxkm_unregister_random_bytes_handlers(); if (ret != 0) { - pr_err("ERROR: wolfssl_linuxkm_unregister_random_bytes_handlers returned %d", ret); + pr_err("ERROR: wolfssl_linuxkm_unregister_random_bytes_handlers returned %d\n", ret); return ret; } pr_info("libwolfssl: kernel global random_bytes handlers uninstalled\n"); @@ -2127,7 +2127,7 @@ static int wc_linuxkm_drbg_cleanup(void) { #if LINUX_VERSION_CODE < KERNEL_VERSION(7, 1, 0) ret = crypto_del_default_rng(); if (ret) { - pr_err("ERROR: crypto_del_default_rng failed: %d", ret); + pr_err("ERROR: crypto_del_default_rng failed: %d\n", ret); return ret; } #else /* >= 7.1.0 */ @@ -2136,7 +2136,7 @@ static int wc_linuxkm_drbg_cleanup(void) { if (fips_enabled) { ret = crypto_del_default_rng(); if (ret) { - pr_err("ERROR: crypto_del_default_rng failed: %d", ret); + pr_err("ERROR: crypto_del_default_rng failed: %d\n", ret); return ret; } } @@ -2145,11 +2145,11 @@ static int wc_linuxkm_drbg_cleanup(void) { if (default_bank_inited) { ret = wc_rng_bank_default_clear(&default_bank); if (ret) - pr_err("ERROR: wc_rng_bank_default_clear in wc_linuxkm_drbg_cleanup failed: %d", ret); + pr_err("ERROR: wc_rng_bank_default_clear in wc_linuxkm_drbg_cleanup failed: %d\n", ret); else { ret = wc_rng_bank_fini(&default_bank); if (ret) - pr_err("ERROR: wc_rng_bank_fini in wc_linuxkm_drbg_cleanup failed: %d", ret); + pr_err("ERROR: wc_rng_bank_fini in wc_linuxkm_drbg_cleanup failed: %d\n", ret); } default_bank_inited = 0; } @@ -2162,14 +2162,14 @@ static int wc_linuxkm_drbg_cleanup(void) { cur_refcnt = WC_LKM_REFCOUNT_TO_INT(wc_linuxkm_drbg.base.cra_refcnt); if (cur_refcnt != 1) { - pr_err("ERROR: wc_linuxkm_drbg_cleanup called with refcnt = %d", cur_refcnt); + pr_err("ERROR: wc_linuxkm_drbg_cleanup called with refcnt = %d\n", cur_refcnt); return -EBUSY; } crypto_unregister_rng(&wc_linuxkm_drbg); if (! (wc_linuxkm_drbg.base.cra_flags & CRYPTO_ALG_DEAD)) { - pr_warn("WARNING: wc_linuxkm_drbg_cleanup: after crypto_unregister_rng, wc_linuxkm_drbg isn't dead."); + pr_warn("WARNING: wc_linuxkm_drbg_cleanup: after crypto_unregister_rng, wc_linuxkm_drbg isn't dead.\n"); return -EBUSY; } diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index 03b6e2e44ec..cb41051a034 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -1115,7 +1115,7 @@ static void wolfssl_exit(void) pr_err("ERROR: wc_RunAllCast_fips() failed at shutdown with return value %d\n", ret); } else - pr_info("wolfCrypt FIPS re-self-test succeeded at unload: all algorithms re-verified."); + pr_info("wolfCrypt FIPS re-self-test succeeded at unload: all algorithms re-verified.\n"); #endif (void)libwolfssl_cleanup(); @@ -1772,7 +1772,7 @@ static int updateFipsHash(void) size_t desc_size = crypto_shash_descsize(tfm) + sizeof *desc; desc = XMALLOC(desc_size, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (desc == NULL) { - pr_err("ERROR: failed allocating desc."); + pr_err("ERROR: failed allocating desc.\n"); ret = MEMORY_E; goto out; } @@ -1845,13 +1845,13 @@ static WC_MAYBE_UNUSED void *my_kallsyms_lookup_name(const char *name) { int ret; kallsyms_lookup_name_kp.addr = NULL; if ((ret = register_kprobe(&kallsyms_lookup_name_kp)) != 0) { - pr_err_once("ERROR: register_kprobe(&kallsyms_lookup_name_kp) failed: %d", ret); + pr_err_once("ERROR: register_kprobe(&kallsyms_lookup_name_kp) failed: %d\n", ret); return 0; } kallsyms_lookup_name_ptr = (typeof(kallsyms_lookup_name_ptr))kallsyms_lookup_name_kp.addr; unregister_kprobe(&kallsyms_lookup_name_kp); if (! kallsyms_lookup_name_ptr) { - pr_err_once("ERROR: kallsyms_lookup_name_kp.addr is null."); + pr_err_once("ERROR: kallsyms_lookup_name_kp.addr is null.\n"); return 0; } } @@ -1880,7 +1880,7 @@ static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_at return -EINVAL; } - pr_info("wolfCrypt: rerunning FIPS self-test on command."); + pr_info("wolfCrypt: rerunning FIPS self-test on command.\n"); if (WC_SIG_IGNORE_BEGIN() >= 0) { ret = wolfCrypt_IntegrityTest_fips(); @@ -1891,7 +1891,7 @@ static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_at ret = -1; } if (ret != 0) { - pr_err("ERROR: wolfCrypt_IntegrityTest_fips: error %d", ret); + pr_err("ERROR: wolfCrypt_IntegrityTest_fips: error %d\n", ret); return -EINVAL; } @@ -1910,7 +1910,7 @@ static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_at return -EINVAL; } - pr_info("wolfCrypt FIPS re-self-test succeeded: all algorithms verified and available."); + pr_info("wolfCrypt FIPS re-self-test succeeded: all algorithms verified and available.\n"); return count; } From 1d21858be17d215de56ff4770432b2cb653a6577 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Tue, 28 Apr 2026 18:12:25 -0500 Subject: [PATCH 7/8] linuxkm/module_hooks.c: in wolfssl_init() DEBUG_LINUXKM_PIE_SUPPORT hash_span() loops, reset cur_reloc_index before each loop (Fenrir review). --- linuxkm/module_hooks.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index cb41051a034..fa0067acc27 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -712,7 +712,7 @@ static int wolfssl_init(void) unsigned int text_hash = hash_span((const u8 *)__wc_text_start, (const u8 *)__wc_text_end, 1); unsigned int rodata_hash = hash_span((const u8 *)__wc_rodata_start, (const u8 *)__wc_rodata_end, 1); u8 *canon_buf = malloc(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ); - ssize_t cur_reloc_index = -1; + ssize_t cur_reloc_index; const u8 *text_p = (const u8 *)__wc_text_start; const u8 *rodata_p = (const u8 *)__wc_rodata_start; unsigned int stabilized_text_hash = 1; @@ -726,6 +726,7 @@ static int wolfssl_init(void) reloc_counts.text = reloc_counts.rodata = reloc_counts.rwdata = reloc_counts.bss = reloc_counts.other = 0; + cur_reloc_index = -1; while (text_p < (const u8 *)__wc_text_end) { size_t text_in_out_len = min(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ, (size_t)((const u8 *)__wc_text_end - text_p)); @@ -748,6 +749,7 @@ static int wolfssl_init(void) } /* note verifyCore is hashed along with the rest of .rodata_wolfcrypt. */ + cur_reloc_index = -1; while (rodata_p < (const u8 *)__wc_rodata_end) { size_t rodata_in_out_len = min(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ, (size_t)((const u8 *)__wc_rodata_end - rodata_p)); From 5dbf2e7382dcd923945cfc01e86811c71ea80c98 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Wed, 29 Apr 2026 17:35:11 -0500 Subject: [PATCH 8/8] linuxkm/linuxkm_memory.c: in wc_fips_generate_hash(), fix handling of failed hmac_update() in text segment loop; linuxkm/module_hooks.c: in wolfssl_init() DEBUG_LINUXKM_PIE_SUPPORT section, render stabilized_rodata_hash; in my_kallsyms_lookup_name(), gate kprobe failure messages behind WOLFSSL_LINUXKM_VERBOSE_DEBUG. --- linuxkm/linuxkm_memory.c | 12 ++++++++++-- linuxkm/module_hooks.c | 9 +++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/linuxkm/linuxkm_memory.c b/linuxkm/linuxkm_memory.c index 9969a7fc732..27814207e60 100644 --- a/linuxkm/linuxkm_memory.c +++ b/linuxkm/linuxkm_memory.c @@ -865,6 +865,11 @@ int wc_fips_generate_hash( text_p += progress; } + if (ret) { + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + goto out; + } + cur_reloc_index = -1; while (rodata_p < (const byte *)seg_map->fips_rodata_end) { size_t rodata_in_out_len = min(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ, @@ -905,6 +910,9 @@ int wc_fips_generate_hash( } XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (ret) + goto out; } #else /* ! (WC_SYM_RELOC_TABLES || WC_SYM_RELOC_TABLES_SUPPORT) */ @@ -936,14 +944,14 @@ int wc_fips_generate_hash( WC_SANITIZE_ENABLE(); -#endif /* ! (WC_SYM_RELOC_TABLES || WC_SYM_RELOC_TABLES_SUPPORT) */ - if (ret) { RELOC_DEBUG_PRINTF("ERROR: hmac_update failed: err %d\n", ret); ret = BAD_STATE_E; goto out; } +#endif /* ! (WC_SYM_RELOC_TABLES || WC_SYM_RELOC_TABLES_SUPPORT) */ + ret = hmac_final(hmac_ctx, hash, digest_size); if (ret) { RELOC_DEBUG_PRINTF("ERROR: hmac_final failed: err %d\n", ret); diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index fa0067acc27..1cbde5a6ee1 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -778,12 +778,13 @@ 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 (%llu), rodata 0x%x (%llu), offset %c0x%llx, canon text 0x%x\n", + pr_info("wolfCrypt segment hashes (spans): text 0x%x (%llu), rodata 0x%x (%llu), offset %c0x%llx, canon text 0x%x, canon rodata 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] ? (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); + stabilized_text_hash, + stabilized_rodata_hash); pr_info("wolfCrypt segments: text=%llx-%llx, rodata=%llx-%llx, " "rwdata=%llx-%llx, bss=%llx-%llx\n", @@ -1847,13 +1848,17 @@ static WC_MAYBE_UNUSED void *my_kallsyms_lookup_name(const char *name) { int ret; kallsyms_lookup_name_kp.addr = NULL; if ((ret = register_kprobe(&kallsyms_lookup_name_kp)) != 0) { +#ifdef WOLFSSL_LINUXKM_VERBOSE_DEBUG pr_err_once("ERROR: register_kprobe(&kallsyms_lookup_name_kp) failed: %d\n", ret); +#endif return 0; } kallsyms_lookup_name_ptr = (typeof(kallsyms_lookup_name_ptr))kallsyms_lookup_name_kp.addr; unregister_kprobe(&kallsyms_lookup_name_kp); if (! kallsyms_lookup_name_ptr) { +#ifdef WOLFSSL_LINUXKM_VERBOSE_DEBUG pr_err_once("ERROR: kallsyms_lookup_name_kp.addr is null.\n"); +#endif return 0; } }