mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-01-28 03:02:20 +01:00
linuxkm/: implement wc_linuxkm_pie_reloc_tab and wc_linuxkm_normalize_relocations(), and integrate with updateFipsHash().
This commit is contained in:
@@ -82,6 +82,14 @@ ifdef LD
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef READELF
|
||||
READELF := readelf
|
||||
endif
|
||||
|
||||
ifndef AWK
|
||||
AWK := awk
|
||||
endif
|
||||
|
||||
libwolfssl.ko:
|
||||
@if test -z '$(KERNEL_ROOT)'; then echo '$$KERNEL_ROOT is unset' >&2; exit 1; fi
|
||||
@if test -z '$(AM_CFLAGS)$(CFLAGS)'; then echo '$$AM_CFLAGS and $$CFLAGS are both unset.' >&2; exit 1; fi
|
||||
@@ -92,6 +100,31 @@ libwolfssl.ko:
|
||||
@test '$(SRC_TOP)/wolfcrypt/src/wc_port.c' -ef '$(MODULE_TOP)/wolfcrypt/src/wc_port.c' || cp --no-dereference --symbolic-link --no-clobber --recursive '$(SRC_TOP)/wolfcrypt' '$(MODULE_TOP)/'
|
||||
@test '$(SRC_TOP)/src/wolfio.c' -ef '$(MODULE_TOP)/src/wolfio.c' || cp --no-dereference --symbolic-link --no-clobber --recursive '$(SRC_TOP)/src' '$(MODULE_TOP)/'
|
||||
ifeq "$(ENABLED_LINUXKM_PIE)" "yes"
|
||||
@echo -e "const unsigned int wc_linuxkm_pie_reloc_tab[] = { ~0U };\nconst size_t wc_linuxkm_pie_reloc_tab_length = 1;" > wc_linuxkm_pie_reloc_tab.c
|
||||
+$(MAKE) ARCH='$(KERNEL_ARCH)' $(OVERRIDE_PATHS) $(CROSS_COMPILE) -C '$(KERNEL_ROOT)' M='$(MODULE_TOP)' $(KBUILD_EXTRA_FLAGS) CC_FLAGS_FTRACE=
|
||||
@$(READELF) --wide -r libwolfssl.ko | \
|
||||
$(AWK) 'BEGIN { \
|
||||
n=0; \
|
||||
printf("%s\n ", \
|
||||
"const unsigned int wc_linuxkm_pie_reloc_tab[] = { "); \
|
||||
} \
|
||||
/^Relocation section '\''\.rela\.text\.wolfcrypt'\''/ { \
|
||||
p=1; \
|
||||
next; \
|
||||
} \
|
||||
/^Relocation section/ { \
|
||||
p=0; \
|
||||
} \
|
||||
/^0/ { \
|
||||
if (p) { \
|
||||
printf("0x%s%s", \
|
||||
gensub("^0*","",1,$$1), \
|
||||
((++n%8) ? ", " : ",\n ")); \
|
||||
} \
|
||||
} \
|
||||
END { \
|
||||
print "~0U };\nconst size_t wc_linuxkm_pie_reloc_tab_length = sizeof wc_linuxkm_pie_reloc_tab / sizeof wc_linuxkm_pie_reloc_tab[0];";\
|
||||
}' > wc_linuxkm_pie_reloc_tab.c
|
||||
+$(MAKE) ARCH='$(KERNEL_ARCH)' $(OVERRIDE_PATHS) $(CROSS_COMPILE) -C '$(KERNEL_ROOT)' M='$(MODULE_TOP)' $(KBUILD_EXTRA_FLAGS) CC_FLAGS_FTRACE=
|
||||
else
|
||||
+$(MAKE) ARCH='$(KERNEL_ARCH)' $(OVERRIDE_PATHS) $(CROSS_COMPILE) -C '$(KERNEL_ROOT)' M='$(MODULE_TOP)' $(KBUILD_EXTRA_FLAGS)
|
||||
@@ -101,34 +134,34 @@ libwolfssl.ko.signed: libwolfssl.ko
|
||||
ifdef FORCE_NO_MODULE_SIG
|
||||
@echo 'Skipping module signature operation because FORCE_NO_MODULE_SIG.'
|
||||
else
|
||||
@cd '$(KERNEL_ROOT)' || exit $$?; \
|
||||
while read configline; do \
|
||||
case "$$configline" in \
|
||||
CONFIG_MODULE_SIG*=*) \
|
||||
declare "$${configline%=*}"="$${configline#*=}" \
|
||||
;; \
|
||||
esac; \
|
||||
done < .config || exit $$?; \
|
||||
if [[ "$${CONFIG_MODULE_SIG}" = "y" && -n "$${CONFIG_MODULE_SIG_KEY}" && \
|
||||
-n "$${CONFIG_MODULE_SIG_HASH}" && ( ! -f '$(MODULE_TOP)/$@' || \
|
||||
'$(MODULE_TOP)/$<' -nt '$(MODULE_TOP)/$@' ) ]]; then \
|
||||
CONFIG_MODULE_SIG_KEY="$${CONFIG_MODULE_SIG_KEY#\"}"; \
|
||||
CONFIG_MODULE_SIG_KEY="$${CONFIG_MODULE_SIG_KEY%\"}"; \
|
||||
CONFIG_MODULE_SIG_HASH="$${CONFIG_MODULE_SIG_HASH#\"}"; \
|
||||
CONFIG_MODULE_SIG_HASH="$${CONFIG_MODULE_SIG_HASH%\"}"; \
|
||||
cp -p '$(MODULE_TOP)/$<' '$(MODULE_TOP)/$@' || exit $$?; \
|
||||
./scripts/sign-file "$${CONFIG_MODULE_SIG_HASH}" \
|
||||
"$${CONFIG_MODULE_SIG_KEY}" \
|
||||
"$${CONFIG_MODULE_SIG_KEY/%.pem/.x509}" \
|
||||
'$(MODULE_TOP)/$@'; \
|
||||
sign_file_exitval=$$?; \
|
||||
if [[ $$sign_file_exitval != 0 ]]; then \
|
||||
$(RM) -f '$(MODULE_TOP)/$@'; \
|
||||
exit $$sign_file_exitval; \
|
||||
fi; \
|
||||
if [[ "$(quiet)" != "silent_" ]]; then \
|
||||
echo " Module $@ signed by $${CONFIG_MODULE_SIG_KEY}."; \
|
||||
fi \
|
||||
@cd '$(KERNEL_ROOT)' || exit $$?; \
|
||||
while read configline; do \
|
||||
case "$$configline" in \
|
||||
CONFIG_MODULE_SIG*=*) \
|
||||
declare "$${configline%=*}"="$${configline#*=}" \
|
||||
;; \
|
||||
esac; \
|
||||
done < .config || exit $$?; \
|
||||
if [[ "$${CONFIG_MODULE_SIG}" = "y" && -n "$${CONFIG_MODULE_SIG_KEY}" && \
|
||||
-n "$${CONFIG_MODULE_SIG_HASH}" && ( ! -f '$(MODULE_TOP)/$@' || \
|
||||
'$(MODULE_TOP)/$<' -nt '$(MODULE_TOP)/$@' ) ]]; then \
|
||||
CONFIG_MODULE_SIG_KEY="$${CONFIG_MODULE_SIG_KEY#\"}"; \
|
||||
CONFIG_MODULE_SIG_KEY="$${CONFIG_MODULE_SIG_KEY%\"}"; \
|
||||
CONFIG_MODULE_SIG_HASH="$${CONFIG_MODULE_SIG_HASH#\"}"; \
|
||||
CONFIG_MODULE_SIG_HASH="$${CONFIG_MODULE_SIG_HASH%\"}"; \
|
||||
cp -p '$(MODULE_TOP)/$<' '$(MODULE_TOP)/$@' || exit $$?; \
|
||||
./scripts/sign-file "$${CONFIG_MODULE_SIG_HASH}" \
|
||||
"$${CONFIG_MODULE_SIG_KEY}" \
|
||||
"$${CONFIG_MODULE_SIG_KEY/%.pem/.x509}" \
|
||||
'$(MODULE_TOP)/$@'; \
|
||||
sign_file_exitval=$$?; \
|
||||
if [[ $$sign_file_exitval != 0 ]]; then \
|
||||
$(RM) -f '$(MODULE_TOP)/$@'; \
|
||||
exit $$sign_file_exitval; \
|
||||
fi; \
|
||||
if [[ "$(quiet)" != "silent_" ]]; then \
|
||||
echo " Module $@ signed by $${CONFIG_MODULE_SIG_KEY}."; \
|
||||
fi \
|
||||
fi
|
||||
endif
|
||||
|
||||
|
||||
@@ -654,7 +654,26 @@
|
||||
extern int memcmp(const void *s1, const void *s2, size_t n);
|
||||
#endif
|
||||
|
||||
extern const u8
|
||||
__wc_text_start[],
|
||||
__wc_text_end[],
|
||||
__wc_rodata_start[],
|
||||
__wc_rodata_end[],
|
||||
__wc_rwdata_start[],
|
||||
__wc_rwdata_end[],
|
||||
__wc_bss_start[],
|
||||
__wc_bss_end[];
|
||||
extern const unsigned int wc_linuxkm_pie_reloc_tab[];
|
||||
extern const size_t wc_linuxkm_pie_reloc_tab_length;
|
||||
extern ssize_t wc_linuxkm_normalize_relocations(
|
||||
const u8 *text_in,
|
||||
size_t text_in_len,
|
||||
u8 *text_out,
|
||||
ssize_t *cur_index_p);
|
||||
|
||||
struct wolfssl_linuxkm_pie_redirect_table {
|
||||
typeof(wc_linuxkm_normalize_relocations) *wc_linuxkm_normalize_relocations;
|
||||
|
||||
#ifndef __ARCH_MEMCMP_NO_REDIRECT
|
||||
typeof(memcmp) *memcmp;
|
||||
#endif
|
||||
@@ -933,6 +952,9 @@
|
||||
|
||||
#ifdef __PIE__
|
||||
|
||||
#define wc_linuxkm_normalize_relocations \
|
||||
WC_LKM_INDIRECT_SYM(wc_linuxkm_normalize_relocations)
|
||||
|
||||
#ifndef __ARCH_MEMCMP_NO_REDIRECT
|
||||
#define memcmp WC_LKM_INDIRECT_SYM(memcmp)
|
||||
#endif
|
||||
|
||||
@@ -43,6 +43,12 @@
|
||||
#endif
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#include <wolfssl/wolfcrypt/sha256.h>
|
||||
#ifdef NO_INLINE
|
||||
#include <wolfssl/wolfcrypt/misc.h>
|
||||
#else
|
||||
#define WOLFSSL_MISC_INCLUDED
|
||||
#include <wolfcrypt/src/misc.c>
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES
|
||||
enum linux_errcodes {
|
||||
@@ -548,12 +554,202 @@ static int my_preempt_count(void) {
|
||||
return preempt_count();
|
||||
}
|
||||
|
||||
#include "linuxkm/wc_linuxkm_pie_reloc_tab.c"
|
||||
|
||||
static inline int find_reloc_tab_offset(size_t text_in_offset) {
|
||||
int ret, hop;
|
||||
if (wc_linuxkm_pie_reloc_tab_length <= 1)
|
||||
return -1;
|
||||
if (text_in_offset >= (size_t)((uintptr_t)__wc_text_end - (uintptr_t)__wc_text_start))
|
||||
return -1;
|
||||
if (text_in_offset >= (size_t)wc_linuxkm_pie_reloc_tab[wc_linuxkm_pie_reloc_tab_length - 1])
|
||||
return -1;
|
||||
for (ret = 0,
|
||||
hop = (int)wc_linuxkm_pie_reloc_tab_length / 2;
|
||||
hop;
|
||||
hop >>= 1)
|
||||
{
|
||||
if (text_in_offset == (size_t)wc_linuxkm_pie_reloc_tab[ret])
|
||||
break;
|
||||
else if (text_in_offset > (size_t)wc_linuxkm_pie_reloc_tab[ret])
|
||||
ret += hop;
|
||||
else if (ret)
|
||||
ret -= hop;
|
||||
}
|
||||
|
||||
while ((ret < (int)wc_linuxkm_pie_reloc_tab_length - 1) &&
|
||||
((size_t)wc_linuxkm_pie_reloc_tab[ret] < text_in_offset))
|
||||
++ret;
|
||||
|
||||
while ((ret > 0) &&
|
||||
((size_t)wc_linuxkm_pie_reloc_tab[ret - 1] >= text_in_offset))
|
||||
--ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define WC_RODATA_TAG (0x1U << 29)
|
||||
#define WC_RWDATA_TAG (0x2U << 29)
|
||||
#define WC_BSS_TAG (0x3U << 29)
|
||||
#define WC_OTHER_TAG (0x4U << 29)
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
|
||||
#include <linux/unaligned.h>
|
||||
#else
|
||||
#include <asm-generic/unaligned.h>
|
||||
#endif
|
||||
|
||||
ssize_t wc_linuxkm_normalize_relocations(
|
||||
const u8 *text_in,
|
||||
size_t text_in_len,
|
||||
u8 *text_out,
|
||||
ssize_t *cur_index_p)
|
||||
{
|
||||
ssize_t i = -1;
|
||||
size_t text_in_offset;
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
int n_text_r = 0, n_rodata_r = 0, n_rwdata_r = 0, n_bss_r = 0, n_other_r = 0;
|
||||
#endif
|
||||
|
||||
if ((text_in < __wc_text_start) ||
|
||||
(text_in >= __wc_text_end))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
text_in_offset = (uintptr_t)text_in - (uintptr_t)__wc_text_start;
|
||||
|
||||
if (cur_index_p)
|
||||
i = *cur_index_p;
|
||||
|
||||
if (i == -1)
|
||||
i = find_reloc_tab_offset(text_in_offset);
|
||||
|
||||
if (i < 0) {
|
||||
return i;
|
||||
}
|
||||
|
||||
WC_SANITIZE_DISABLE();
|
||||
memcpy(text_out, text_in, text_in_len);
|
||||
WC_SANITIZE_ENABLE();
|
||||
|
||||
for (;
|
||||
(size_t)i < wc_linuxkm_pie_reloc_tab_length - 1;
|
||||
++i)
|
||||
{
|
||||
size_t next_reloc = wc_linuxkm_pie_reloc_tab[i];
|
||||
int reloc_buf;
|
||||
uintptr_t abs_ptr;
|
||||
|
||||
next_reloc -= text_in_offset;
|
||||
|
||||
if (next_reloc >= text_in_len) {
|
||||
/* no more relocations in this buffer. */
|
||||
break;
|
||||
}
|
||||
if (next_reloc > text_in_len - sizeof reloc_buf) {
|
||||
/* relocation straddles buffer at end -- caller will try again with
|
||||
* that relocation at the start.
|
||||
*/
|
||||
text_in_len -= (sizeof reloc_buf - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
reloc_buf = (int)get_unaligned((int32_t *)&text_out[next_reloc]);
|
||||
|
||||
/* the +4 accounts for the disp32 field size, as RIP points to the next
|
||||
* instruction byte per the x86_64 ABI.
|
||||
*/
|
||||
abs_ptr = (uintptr_t)text_in + next_reloc + 4 + reloc_buf;
|
||||
|
||||
if ((abs_ptr >= (uintptr_t)__wc_text_start) &&
|
||||
(abs_ptr < (uintptr_t)__wc_text_end))
|
||||
{
|
||||
/* internal references in the .wolfcrypt.text segment don't need
|
||||
* normalization.
|
||||
*/
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
++n_text_r;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
else if ((abs_ptr >= (uintptr_t)__wc_rodata_start) &&
|
||||
(abs_ptr < (uintptr_t)__wc_rodata_end))
|
||||
{
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
++n_rodata_r;
|
||||
#endif
|
||||
reloc_buf -= (int)((uintptr_t)__wc_rodata_start -
|
||||
(uintptr_t)__wc_text_start);
|
||||
reloc_buf |= WC_RODATA_TAG;
|
||||
}
|
||||
else if ((abs_ptr >= (uintptr_t)__wc_rwdata_start) &&
|
||||
(abs_ptr < (uintptr_t)__wc_rwdata_end))
|
||||
{
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
++n_rwdata_r;
|
||||
#endif
|
||||
reloc_buf -= (int)((uintptr_t)__wc_rwdata_start -
|
||||
(uintptr_t)__wc_text_start);
|
||||
reloc_buf |= WC_RWDATA_TAG;
|
||||
}
|
||||
else if ((abs_ptr >= (uintptr_t)__wc_bss_start) &&
|
||||
(abs_ptr < (uintptr_t)__wc_bss_end))
|
||||
{
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
++n_bss_r;
|
||||
#endif
|
||||
reloc_buf -= (int)((uintptr_t)__wc_bss_start -
|
||||
(uintptr_t)__wc_text_start);
|
||||
reloc_buf |= WC_BSS_TAG;
|
||||
}
|
||||
else {
|
||||
/* relocation referring to non-wolfcrypt segment -- these can only
|
||||
* be stabilized by zeroing them.
|
||||
*/
|
||||
reloc_buf = WC_OTHER_TAG;
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
++n_other_r;
|
||||
pr_notice("found non-wolfcrypt relocation at text offset 0x%x to "
|
||||
"addr 0x%lx, text=%px-%px, rodata=%px-%px, "
|
||||
"rwdata=%px-%px, bss=%px-%px\n",
|
||||
wc_linuxkm_pie_reloc_tab[i],
|
||||
abs_ptr,
|
||||
__wc_text_start,
|
||||
__wc_text_end,
|
||||
__wc_rodata_start,
|
||||
__wc_rodata_end,
|
||||
__wc_rwdata_start,
|
||||
__wc_rwdata_end,
|
||||
__wc_bss_start,
|
||||
__wc_bss_end);
|
||||
#endif
|
||||
}
|
||||
put_unaligned((u32)reloc_buf, (int32_t *)&text_out[next_reloc]);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
if (n_other_r > 0)
|
||||
pr_notice("text_in=%px relocs=%d/%d/%d/%d/%d ret = %zu\n",
|
||||
text_in, n_text_r, n_rodata_r, n_rwdata_r, n_bss_r, n_other_r,
|
||||
text_in_len);
|
||||
#endif
|
||||
|
||||
if (cur_index_p)
|
||||
*cur_index_p = i;
|
||||
|
||||
return text_in_len;
|
||||
}
|
||||
|
||||
static int set_up_wolfssl_linuxkm_pie_redirect_table(void) {
|
||||
memset(
|
||||
&wolfssl_linuxkm_pie_redirect_table,
|
||||
0,
|
||||
sizeof wolfssl_linuxkm_pie_redirect_table);
|
||||
|
||||
wolfssl_linuxkm_pie_redirect_table.wc_linuxkm_normalize_relocations =
|
||||
wc_linuxkm_normalize_relocations;
|
||||
|
||||
#ifndef __ARCH_MEMCMP_NO_REDIRECT
|
||||
wolfssl_linuxkm_pie_redirect_table.memcmp = memcmp;
|
||||
#endif
|
||||
@@ -958,12 +1154,47 @@ static int updateFipsHash(void)
|
||||
goto out;
|
||||
}
|
||||
|
||||
WC_SANITIZE_DISABLE();
|
||||
#if defined(WOLFSSL_LINUXKM) && defined(USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE)
|
||||
{
|
||||
ssize_t cur_reloc_index = -1;
|
||||
const byte *text_p = (const byte *)first;
|
||||
byte *buf = XMALLOC(8192, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
if (! buf) {
|
||||
pr_err("ERROR: malloc failed in updateFipsHash()\n");
|
||||
ret = MEMORY_E;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (text_p < (const byte *)last) {
|
||||
ssize_t progress = wc_linuxkm_normalize_relocations(
|
||||
text_p,
|
||||
min(8192, (word32)((const byte *)last - text_p)),
|
||||
buf,
|
||||
&cur_reloc_index);
|
||||
if (progress < 0) {
|
||||
ret = IN_CORE_FIPS_E;
|
||||
break;
|
||||
}
|
||||
ret = crypto_shash_update(desc, buf, (word32)progress);
|
||||
if (ret)
|
||||
break;
|
||||
text_p += progress;
|
||||
}
|
||||
|
||||
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
|
||||
WC_SANITIZE_DISABLE();
|
||||
#else
|
||||
WC_SANITIZE_DISABLE();
|
||||
ret = crypto_shash_update(desc, (byte *)(wc_ptr_t)first, (word32)code_sz);
|
||||
#endif /* !WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE */
|
||||
|
||||
if (ret) {
|
||||
pr_err("ERROR: crypto_shash_update failed: err %d\n", ret);
|
||||
ret = BAD_STATE_E;
|
||||
WC_SANITIZE_ENABLE();
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -983,6 +1214,7 @@ static int updateFipsHash(void)
|
||||
if (ret) {
|
||||
pr_err("ERROR: crypto_shash_update failed: err %d\n", ret);
|
||||
ret = BAD_STATE_E;
|
||||
WC_SANITIZE_ENABLE();
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
SECTIONS {
|
||||
. = ALIGN(4096);
|
||||
.text.wolfcrypt : {
|
||||
__wc_text_start = .;
|
||||
*(.text.wolfcrypt)
|
||||
__wc_text_end = .;
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
.rodata.wolfcrypt : {
|
||||
__wc_rodata_start = .;
|
||||
*(.rodata.wolfcrypt)
|
||||
__wc_rodata_end = .;
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
.data.wolfcrypt : {
|
||||
__wc_rwdata_start = .;
|
||||
*(.data.wolfcrypt)
|
||||
__wc_rwdata_end = .;
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
.bss.wolfcrypt : {
|
||||
__wc_bss_start = .;
|
||||
*(.bss.wolfcrypt)
|
||||
__wc_bss_end = .;
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user