Skip to content

Commit 99c983d

Browse files
authored
Merge pull request #9269 from douzzer/20251002-linuxkm-fencepost-and-fortify-tweaks
20251002-linuxkm-fencepost-and-fortify-tweaks
2 parents 781c9bb + 46fd3d6 commit 99c983d

3 files changed

Lines changed: 110 additions & 27 deletions

File tree

linuxkm/Kbuild

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ endif
177177

178178
ifeq "$(ENABLED_LINUXKM_PIE)" "yes"
179179

180-
LDFLAGS_libwolfssl.o += -T $(src)/wolfcrypt.lds
180+
ldflags-y += -T $(src)/wolfcrypt.lds
181181

182182
ifndef NM
183183
NM := nm

linuxkm/linuxkm_wc_port.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,14 @@
228228

229229
#include <linux/kconfig.h>
230230

231+
#if defined(CONFIG_FORTIFY_SOURCE) && defined(HAVE_LINUXKM_PIE_SUPPORT)
232+
/* fortify-source causes all sorts of awkward problems for the PIE
233+
* build, up to and including stubborn external references and multiple
234+
* definitions of string functions.
235+
*/
236+
#undef CONFIG_FORTIFY_SOURCE
237+
#endif
238+
231239
#if defined(__PIE__) && defined(CONFIG_ARM64)
232240
#define alt_cb_patch_nops my__alt_cb_patch_nops
233241
#define queued_spin_lock_slowpath my__queued_spin_lock_slowpath

linuxkm/module_hooks.c

Lines changed: 101 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -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
118114
static 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

665717
static 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

Comments
 (0)