@@ -89,22 +89,18 @@ static int libwolfssl_cleanup(void) {
8989
9090#ifdef DEBUG_LINUXKM_PIE_SUPPORT
9191
92- extern int wolfCrypt_PIE_first_function (void );
93- extern int wolfCrypt_PIE_last_function (void );
94- extern const unsigned int wolfCrypt_PIE_rodata_start [];
95- extern const unsigned int wolfCrypt_PIE_rodata_end [];
96-
9792/* cheap portable ad-hoc hash function to confirm bitwise stability of the PIE
9893 * binary image.
9994 */
100- static unsigned int hash_span (const u8 * start , const u8 * end ) {
101- unsigned int sum = 1 ;
95+ static unsigned int hash_span (const u8 * start , const u8 * end , unsigned int sum ) {
96+ WC_SANITIZE_DISABLE () ;
10297 while (start < end ) {
10398 unsigned int rotate_by ;
10499 sum ^= * start ++ ;
105100 rotate_by = (sum ^ (sum >> 5 )) & 31 ;
106101 sum = (sum << rotate_by ) | (sum >> (32 - rotate_by ));
107102 }
103+ WC_SANITIZE_ENABLE ();
108104 return sum ;
109105}
110106
@@ -118,6 +114,11 @@ extern struct wolfssl_linuxkm_pie_redirect_table wolfssl_linuxkm_pie_redirect_ta
118114static int set_up_wolfssl_linuxkm_pie_redirect_table (void );
119115#endif /* USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE */
120116
117+ #ifdef HAVE_FIPS
118+ extern const unsigned int wolfCrypt_FIPS_ro_start [];
119+ extern const unsigned int wolfCrypt_FIPS_ro_end [];
120+ #endif
121+
121122#endif /* HAVE_LINUXKM_PIE_SUPPORT */
122123
123124#ifdef HAVE_FIPS
@@ -398,6 +399,17 @@ static int wolfssl_init(void)
398399 return ret ;
399400#endif
400401
402+ #if defined(HAVE_FIPS ) && defined(HAVE_LINUXKM_PIE_SUPPORT )
403+ if (((uintptr_t )__wc_text_start > (uintptr_t )wolfCrypt_FIPS_first ) ||
404+ ((uintptr_t )__wc_text_end < (uintptr_t )wolfCrypt_FIPS_last ) ||
405+ ((uintptr_t )__wc_rodata_start > (uintptr_t )wolfCrypt_FIPS_ro_start ) ||
406+ ((uintptr_t )__wc_rodata_end < (uintptr_t )wolfCrypt_FIPS_ro_end ))
407+ {
408+ pr_err ("ERROR: ELF segment fenceposts and FIPS fenceposts conflict.\n" );
409+ return - ECANCELED ;
410+ }
411+ #endif
412+
401413#if defined(HAVE_LINUXKM_PIE_SUPPORT ) && defined(DEBUG_LINUXKM_PIE_SUPPORT )
402414
403415#if LINUX_VERSION_CODE >= KERNEL_VERSION (6 , 4 , 0 )
@@ -419,18 +431,55 @@ static int wolfssl_init(void)
419431#endif
420432
421433 {
422- unsigned int text_hash = hash_span (__wc_text_start , __wc_text_end );
423- unsigned int rodata_hash = hash_span (__wc_rodata_start , __wc_rodata_end );
434+ unsigned int text_hash = hash_span (__wc_text_start , __wc_text_end , 1 );
435+ unsigned int rodata_hash = hash_span (__wc_rodata_start , __wc_rodata_end , 1 );
436+ u8 * canon_buf = malloc (WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ );
437+ ssize_t cur_reloc_index = -1 ;
438+ const byte * text_p = __wc_text_start ;
439+ unsigned int stabilized_text_hash = 1 ;
440+
441+ if (! canon_buf ) {
442+ pr_err ("ERROR: malloc(%d) for WOLFSSL_TEXT_SEGMENT_CANONICALIZER failed: %ld.\n" , WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ , PTR_ERR (canon_buf ));
443+ return - ECANCELED ;
444+ }
445+
446+ total_text_r = total_rodata_r = total_rwdata_r = total_bss_r =
447+ total_other_r = 0 ;
448+
449+ while (text_p < __wc_text_end ) {
450+ ssize_t progress =
451+ WOLFSSL_TEXT_SEGMENT_CANONICALIZER (
452+ text_p ,
453+ min (WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ ,
454+ (word32 )(__wc_text_end - text_p )),
455+ canon_buf , & cur_reloc_index );
456+ if (progress <= 0 ) {
457+ pr_err ("ERROR: progress=%ld from WOLFSSL_TEXT_SEGMENT_CANONICALIZER() at offset %x (text=%x-%x).\n" ,
458+ progress ,
459+ (unsigned )(uintptr_t )text_p ,
460+ (unsigned )(uintptr_t )__wc_text_start ,
461+ (unsigned )(uintptr_t )__wc_text_end );
462+ free (canon_buf );
463+ return - ECANCELED ;
464+ }
465+ stabilized_text_hash = hash_span (canon_buf , canon_buf + progress , stabilized_text_hash );
466+ text_p += progress ;
467+ }
468+
469+ free (canon_buf );
470+ canon_buf = 0 ;
424471
425472 /* note, "%pK" conceals the actual layout information. "%px" exposes
426473 * the true module start address, which is potentially useful to an
427474 * attacker.
428475 */
429- pr_info ("wolfCrypt section hashes (spans): text 0x%x (%lu), rodata 0x%x (%lu), offset %c0x%lx\n" ,
476+ pr_info ("wolfCrypt segment hashes (spans): text 0x%x (%lu), rodata 0x%x (%lu), offset %c0x%lx, canon text 0x%x \n" ,
430477 text_hash , __wc_text_end - __wc_text_start ,
431478 rodata_hash , __wc_rodata_end - __wc_rodata_start ,
432479 & __wc_text_start [0 ] < & __wc_rodata_start [0 ] ? '+' : '-' ,
433- & __wc_text_start [0 ] < & __wc_rodata_start [0 ] ? & __wc_rodata_start [0 ] - & __wc_text_start [0 ] : & __wc_text_start [0 ] - & __wc_rodata_start [0 ]);
480+ & __wc_text_start [0 ] < & __wc_rodata_start [0 ] ? & __wc_rodata_start [0 ] - & __wc_text_start [0 ] : & __wc_text_start [0 ] - & __wc_rodata_start [0 ],
481+ stabilized_text_hash );
482+
434483 pr_info ("wolfCrypt segments: text=%x-%x, rodata=%x-%x, "
435484 "rwdata=%x-%x, bss=%x-%x\n" ,
436485 (unsigned )(uintptr_t )__wc_text_start ,
@@ -441,6 +490,9 @@ static int wolfssl_init(void)
441490 (unsigned )(uintptr_t )__wc_rwdata_end ,
442491 (unsigned )(uintptr_t )__wc_bss_start ,
443492 (unsigned )(uintptr_t )__wc_bss_end );
493+
494+ pr_info ("whole-segment relocation normalizations: text=%d, rodata=%d, rwdata=%d, bss=%d, other=%d\n" ,
495+ total_text_r , total_rodata_r , total_rwdata_r , total_bss_r , total_other_r );
444496 }
445497
446498#endif /* HAVE_LINUXKM_PIE_SUPPORT && DEBUG_LINUXKM_PIE_SUPPORT */
@@ -460,7 +512,7 @@ static int wolfssl_init(void)
460512 fipsEntry ();
461513
462514#if defined(HAVE_LINUXKM_PIE_SUPPORT ) && defined(DEBUG_LINUXKM_PIE_SUPPORT )
463- pr_info ("relocation normalizations: text=%d, rodata=%d, rwdata=%d, bss=%d, other=%d\n" ,
515+ pr_info ("FIPS-bounded relocation normalizations: text=%d, rodata=%d, rwdata=%d, bss=%d, other=%d\n" ,
464516 total_text_r , total_rodata_r , total_rwdata_r , total_bss_r , total_other_r );
465517#endif
466518
@@ -664,12 +716,24 @@ MODULE_VERSION(LIBWOLFSSL_VERSION_STRING);
664716
665717static inline int find_reloc_tab_offset (size_t text_in_offset ) {
666718 int ret , hop ;
667- if (wc_linuxkm_pie_reloc_tab_length <= 1 )
719+ if (wc_linuxkm_pie_reloc_tab_length <= 1 ) {
720+ #ifdef DEBUG_LINUXKM_PIE_SUPPORT
721+ pr_err ("ERROR: %s failed at L %d.\n" , __FUNCTION__ , __LINE__ );
722+ #endif
668723 return -1 ;
669- if (text_in_offset >= (size_t )((uintptr_t )__wc_text_end - (uintptr_t )__wc_text_start ))
724+ }
725+ if (text_in_offset >= (size_t )((uintptr_t )__wc_text_end - (uintptr_t )__wc_text_start )) {
726+ #ifdef DEBUG_LINUXKM_PIE_SUPPORT
727+ pr_err ("ERROR: %s failed at L %d.\n" , __FUNCTION__ , __LINE__ );
728+ #endif
670729 return -1 ;
671- if (text_in_offset >= (size_t )wc_linuxkm_pie_reloc_tab [wc_linuxkm_pie_reloc_tab_length - 1 ])
730+ }
731+ if (text_in_offset >= (size_t )wc_linuxkm_pie_reloc_tab [wc_linuxkm_pie_reloc_tab_length - 1 ]) {
732+ #ifdef DEBUG_LINUXKM_PIE_SUPPORT
733+ pr_err ("ERROR: %s failed at L %d.\n" , __FUNCTION__ , __LINE__ );
734+ #endif
672735 return -1 ;
736+ }
673737 for (ret = 0 ,
674738 hop = (int )wc_linuxkm_pie_reloc_tab_length / 2 ;
675739 hop ;
@@ -691,6 +755,10 @@ static inline int find_reloc_tab_offset(size_t text_in_offset) {
691755 ((size_t )wc_linuxkm_pie_reloc_tab [ret - 1 ] >= text_in_offset ))
692756 -- ret ;
693757
758+ #ifdef DEBUG_LINUXKM_PIE_SUPPORT
759+ if (ret < 0 )
760+ pr_err ("ERROR: %s returning %d at L %d.\n" , __FUNCTION__ , ret , __LINE__ );
761+ #endif
694762 return ret ;
695763}
696764
@@ -720,8 +788,11 @@ ssize_t wc_linuxkm_normalize_relocations(
720788
721789 if ((text_in_len == 0 ) ||
722790 (text_in < __wc_text_start ) ||
723- (text_in + text_in_len >= __wc_text_end ))
791+ (text_in + text_in_len > __wc_text_end ))
724792 {
793+ #ifdef DEBUG_LINUXKM_PIE_SUPPORT
794+ pr_err ("ERROR: %s returning -1 at L %d with span %x-%x versus segment %x-%x.\n" , __FUNCTION__ , __LINE__ , (unsigned )(uintptr_t )text_in , (unsigned )(uintptr_t )(text_in + text_in_len ), (unsigned )(uintptr_t )__wc_text_start , (unsigned )(uintptr_t )__wc_text_end );
795+ #endif
725796 return -1 ;
726797 }
727798
@@ -788,13 +859,17 @@ ssize_t wc_linuxkm_normalize_relocations(
788859#endif
789860 continue ;
790861 }
791- /* for the rodata, rwdata, and bss segments, recognize dest addrs one
792- * byte outside the segment -- the compiler occasionally generates
793- * these, e.g. __wc_rwdata_start - 1 in DoInCoreCheck() in kernel 6.1
794- * build of FIPS v5.
862+ /* for the various data segments, recognize dest addrs a few bytes
863+ * outside the segment -- the compiler occasionally generates these,
864+ * e.g. __wc_rwdata_start - 1 in DoInCoreCheck() in kernel 6.1 build of
865+ * FIPS v5, __wc_bss_start - 4 in kernel 4.4, and __wc_rodata_end + 26
866+ * in kernel 6.18.
795867 */
796- else if ((abs_ptr >= (uintptr_t )__wc_rodata_start - 1 ) &&
797- (abs_ptr <= (uintptr_t )__wc_rodata_end + 1 ))
868+ #ifndef LINUXKM_PIE_DATA_SLOP_MARGIN
869+ #define LINUXKM_PIE_DATA_SLOP_MARGIN 0x20
870+ #endif
871+ else if ((abs_ptr >= (uintptr_t )__wc_rodata_start - LINUXKM_PIE_DATA_SLOP_MARGIN ) &&
872+ (abs_ptr <= (uintptr_t )__wc_rodata_end + LINUXKM_PIE_DATA_SLOP_MARGIN ))
798873 {
799874#ifdef DEBUG_LINUXKM_PIE_SUPPORT
800875 ++ n_rodata_r ;
@@ -803,8 +878,8 @@ ssize_t wc_linuxkm_normalize_relocations(
803878 (uintptr_t )__wc_text_start );
804879 reloc_buf ^= WC_RODATA_TAG ;
805880 }
806- else if ((abs_ptr >= (uintptr_t )__wc_rwdata_start - 1 ) &&
807- (abs_ptr <= (uintptr_t )__wc_rwdata_end + 1 ))
881+ else if ((abs_ptr >= (uintptr_t )__wc_rwdata_start - LINUXKM_PIE_DATA_SLOP_MARGIN ) &&
882+ (abs_ptr <= (uintptr_t )__wc_rwdata_end + LINUXKM_PIE_DATA_SLOP_MARGIN ))
808883 {
809884#ifdef DEBUG_LINUXKM_PIE_SUPPORT
810885 ++ n_rwdata_r ;
@@ -813,8 +888,8 @@ ssize_t wc_linuxkm_normalize_relocations(
813888 (uintptr_t )__wc_text_start );
814889 reloc_buf ^= WC_RWDATA_TAG ;
815890 }
816- else if ((abs_ptr >= (uintptr_t )__wc_bss_start - 1 ) &&
817- (abs_ptr <= (uintptr_t )__wc_bss_end + 1 ))
891+ else if ((abs_ptr >= (uintptr_t )__wc_bss_start - LINUXKM_PIE_DATA_SLOP_MARGIN ) &&
892+ (abs_ptr <= (uintptr_t )__wc_bss_end + LINUXKM_PIE_DATA_SLOP_MARGIN ))
818893 {
819894#ifdef DEBUG_LINUXKM_PIE_SUPPORT
820895 ++ n_bss_r ;
0 commit comments