mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 11:00:54 +02:00
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.
This commit is contained in:
+41
-16
@@ -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 <wolfssl/wolfcrypt/libwolfssl_sources.h>"; \
|
||||
print "\#include <wolfssl/wolfcrypt/memory.h>"; \
|
||||
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 <ENVIRON["SECTION_MAP"] > 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...'
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
+247
-104
@@ -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 (seg_in_offset >= (size_t)reloc_tab[reloc_tab_len - 1].offset) {
|
||||
RELOC_DEBUG_PRINTF("ERROR: %s failed.\n", __FUNCTION__);
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
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)) {
|
||||
RELOC_DEBUG_PRINTF("ERROR: %s failed.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
if (text_in_offset >= (size_t)reloc_tab[reloc_tab_len - 1].offset) {
|
||||
RELOC_DEBUG_PRINTF("ERROR: %s failed.\n", __FUNCTION__);
|
||||
return -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 ((text_in_len == 0) ||
|
||||
((uintptr_t)text_in < seg_map->text_start) ||
|
||||
((uintptr_t)(text_in + text_in_len) > seg_map->text_end))
|
||||
if (*seg_in_out_len == 0)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (((uintptr_t)seg_in >= seg_map->text_start) &&
|
||||
((uintptr_t)(seg_in + *seg_in_out_len) <= seg_map->text_end))
|
||||
{
|
||||
RELOC_DEBUG_PRINTF("ERROR: %s returning -1 with span %llx-%llx versus segment %llx-%llx.\n",
|
||||
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 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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
+66
-11
@@ -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,12 +1192,12 @@ 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_text(text_in, text_in_len, text_out, cur_index_p, &seg_map,
|
||||
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
|
||||
@@ -1175,6 +1206,28 @@ ssize_t wc_linuxkm_normalize_relocations(
|
||||
);
|
||||
}
|
||||
|
||||
ssize_t wc_linuxkm_normalize_relocations_noresize(
|
||||
const u8 *seg_in,
|
||||
size_t seg_in_len,
|
||||
u8 *seg_out,
|
||||
ssize_t *cur_index_p)
|
||||
{
|
||||
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)
|
||||
|
||||
static const struct wc_reloc_table_segments seg_map = {
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user