linuxkm/Kbuild and linuxkm/module_hooks.c: refactor wc_linuxkm_pie_reloc_tab to include ground truth segment tag from ELF metadata.

tweaks for ARM32: recognize R_ARM_* relocations, and add -fno-unwind-tables to PIE_FLAGS.

linuxkm/linuxkm_wc_port.h:
* __PIE__: don't declare static pmd_to_page() unless USE_SPLIT_PMD_PTLOCKS.
* add wc_lkm_refcount_to_int() helper with -Wnested-externs suppressed.

wolfcrypt/src/fe_operations.c: in fe_frombytes() and fe_sq2(), use explicit XMEMSET()s to initialize working vars, rather than implicit, to avoid implicit (unshimmable) memset() calls.

wolfcrypt/src/ge_operations.c: fix gate on _wc_curve25519_dummy() to require CURVED25519_ASM.
This commit is contained in:
Daniel Pouzzner
2025-11-14 19:24:53 -06:00
parent 96dde5b4a8
commit 06d3d6d3df
6 changed files with 253 additions and 128 deletions

View File

@@ -127,6 +127,9 @@ ifeq "$(ENABLED_LINUXKM_PIE)" "yes"
OBJECT_FILES_NON_STANDARD := y
endif
ifeq "$(KERNEL_ARCH)" "arm"
PIE_FLAGS += -fno-unwind-tables
endif
ifeq "$(KERNEL_ARCH)" "mips"
PIE_FLAGS += -mabicalls
endif

View File

@@ -73,17 +73,17 @@ OVERRIDE_PATHS :=
ifdef CC
ifneq "$(CC)" "cc"
OVERRIDE_PATHS := $(OVERRIDE_PATHS) 'CC=$(CC)'
OVERRIDE_PATHS := $(OVERRIDE_PATHS) 'CC=$(CC)'
endif
endif
ifdef AS
ifneq "$(AS)" "as"
OVERRIDE_PATHS := $(OVERRIDE_PATHS) 'AS=$(AS)'
OVERRIDE_PATHS := $(OVERRIDE_PATHS) 'AS=$(AS)'
endif
endif
ifdef LD
ifneq "$(LD)" "ld"
OVERRIDE_PATHS := $(OVERRIDE_PATHS) 'LD=$(LD)'
OVERRIDE_PATHS := $(OVERRIDE_PATHS) 'LD=$(LD)'
endif
endif
@@ -103,14 +103,39 @@ ifndef MAKE_TMPDIR
MAKE_TMPDIR := $(TMPDIR)
endif
GENERATE_RELOC_TAB := $(AWK) 'BEGIN { \
GENERATE_SECTION_MAP := $(AWK) 'BEGIN { printf("") >ENVIRON["SECTION_MAP"]; } \
{ \
if ($$7 !~ "^[0-9]+$$") \
next; \
if ($$4 == "SECTION") { \
sections[$$7] = $$8; \
next; \
} \
if (($$4 == "NOTYPE") || ($$4 == "OBJECT") || ($$4 == "FUNC")) { \
if (($$8 == "$$d") || ($$8 == "$$t")) \
next; \
if ($$7 in sections) { \
if (sections[$$7] ~ "_wolfcrypt$$") \
print $$8 "\t" sections[$$7] >>ENVIRON["SECTION_MAP"]; \
} else \
print $$8 " is in section " $$7 " with no name mapping." >"/dev/stderr";\
} \
}'
GENERATE_RELOC_TAB := $(AWK) ' \
BEGIN { \
n=0; \
bad_relocs=0; \
print "\#include <wolfssl/wolfcrypt/libwolfssl_sources.h>"; \
printf("%s\n ", \
"WOLFSSL_LOCAL const unsigned int wc_linuxkm_pie_reloc_tab[] = { "); \
"WOLFSSL_LOCAL const unsigned int wc_linuxkm_pie_reloc_tab[] = { "); \
if ("SECTION_MAP" in ENVIRON) { \
while (getline <ENVIRON["SECTION_MAP"] > 0) \
section_map[$$1] = $$2; \
close(ENVIRON["SECTION_MAP"]); \
} \
} \
/^Relocation section '\''\.rela\.text_wolfcrypt'\''/ { \
/^Relocation section '\''\.rela?\.text_wolfcrypt'\''/ { \
p=1; \
next; \
} \
@@ -119,19 +144,55 @@ GENERATE_RELOC_TAB := $(AWK) 'BEGIN { \
} \
/^0/ { \
if (p) { \
if ($$3 !~ "^(R_X86_64_PLT32|R_X86_64_PC32|R_AARCH64_.*)$$") { \
print "Unexpected relocation type:\n" $$0 >"/dev/stderr"; \
++bad_relocs; \
} \
printf("0x%s%s", \
gensub("^0*","",1,$$1), \
((++n%8) ? ", " : ",\n ")); \
if ($$3 !~ "^(R_X86_64_PLT32|R_X86_64_PC32|R_AARCH64_.*|R_ARM.*)$$") { \
print "Unexpected relocation type:\n" $$0 >"/dev/stderr"; \
++bad_relocs; \
} \
if ($$5 in section_map) \
section = section_map[$$5]; \
else if ($$5 ~ "^\\.") \
section = $$5; \
else \
section = ""; \
if (section) { \
switch (section) { \
case ".text_wolfcrypt": \
section_tag = 0; \
break; \
case ".rodata_wolfcrypt": \
section_tag = 1; \
break; \
case ".data_wolfcrypt": \
section_tag = 2; \
break; \
case ".bss_wolfcrypt": \
section_tag = 3; \
break; \
default: \
print "Unexpected section:\n" $$0 >"/dev/stderr"; \
++bad_relocs; \
section_tag = 4; \
} \
} else { \
print "Unresolvable symbol reference for relocation:\n" $$0 >"/dev/stderr";\
++bad_relocs; \
section_tag = 4; \
} \
if (strtonum("0x" gensub("^0*","",1,$$1)) >= lshift(1, 29)) { \
print "Relocation offset overflow:" >"/dev/stderr"; \
print >"/dev/stderr"; \
exit(1); \
} \
printf("0x%xU%s", \
or(strtonum("0x" gensub("^0*","",1,$$1)), \
lshift(section_tag, 29)), \
((++n%8) ? ", " : ",\n ")); \
} \
} \
END { \
if (bad_relocs) { \
print "Found " bad_relocs " unexpected relocations." >"/dev/stderr"; \
exit(1); \
print "Found " bad_relocs " unresolvable relocations." >"/dev/stderr"; \
exit(1); \
} \
print "~0U };\nWOLFSSL_LOCAL const unsigned long wc_linuxkm_pie_reloc_tab_length = sizeof wc_linuxkm_pie_reloc_tab / sizeof wc_linuxkm_pie_reloc_tab[0];";\
}'
@@ -140,88 +201,98 @@ ifeq "$(V)" "1"
vflag := --verbose
endif
# This rule is .PHONY because it doesn't actually build the module -- Kbuild
# does, and we always need to call Kbuild to enforce rebuild for dependencies
# and config changes.
.PHONY: libwolfssl.ko
libwolfssl.ko:
@function resolved_link_is_equal() { [[ -L "$$1" && ("$$(readlink -f "$$1")" == "$$(readlink -f "$$2")") ]] }
@set -e
@function resolved_link_is_equal() { [[ -L "$$1" && "$$(readlink -f "$$1")" == "$$(readlink -f "$$2")" ]]; }
@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
@if test -z '$(src_libwolfssl_la_OBJECTS)'; then echo '$$src_libwolfssl_la_OBJECTS is unset.' >&2; exit 1; fi
# after commit 9a0ebe5011 (6.10), sources must be in $(obj). work around this by making links to all needed sources:
# after commit 9a0ebe5011 (6.10), sources must be in $(obj). work around this by making links to all needed sources:
@mkdir -p '$(MODULE_TOP)/linuxkm'
@resolved_link_is_equal '$(MODULE_TOP)/linuxkm/module_hooks.c' '$(MODULE_TOP)/module_hooks.c' || cp $(vflag) --no-dereference --symbolic-link --no-clobber '$(MODULE_TOP)'/*.[ch] '$(MODULE_TOP)/linuxkm/'
@resolved_link_is_equal '$(MODULE_TOP)/wolfcrypt/src/wc_port.c' '$(SRC_TOP)/wolfcrypt/src/wc_port.c' || cp $(vflag) --no-dereference --symbolic-link --no-clobber --recursive '$(SRC_TOP)/wolfcrypt' '$(MODULE_TOP)/'
@resolved_link_is_equal '$(MODULE_TOP)/src/wolfio.c' '$(SRC_TOP)/src/wolfio.c' || cp $(vflag) --no-dereference --symbolic-link --no-clobber --recursive '$(SRC_TOP)/src' '$(MODULE_TOP)/'
ifeq "$(FIPS_OPTEST)" "1"
@resolved_link_is_equal '$(MODULE_TOP)/linuxkm/optest-140-3/linuxkm_optest_wrapper.c' '$(SRC_TOP)/../fips/optest-140-3/linuxkm_optest_wrapper.c' || cp $(vflag) --no-dereference --symbolic-link --no-clobber --recursive '$(SRC_TOP)/../fips/optest-140-3' '$(MODULE_TOP)/linuxkm'
@resolved_link_is_equal '$(MODULE_TOP)/linuxkm/optest-140-3/linuxkm_optest_wrapper.c' '$(SRC_TOP)/../fips/optest-140-3/linuxkm_optest_wrapper.c' || cp $(vflag) --no-dereference --symbolic-link --no-clobber --recursive '$(SRC_TOP)/../fips/optest-140-3' '$(MODULE_TOP)/linuxkm/'
endif
ifeq "$(ENABLED_LINUXKM_PIE)" "yes"
@[[ -f '$(MODULE_TOP)/linuxkm/wc_linuxkm_pie_reloc_tab.c' && ! -L '$(MODULE_TOP)/linuxkm/wc_linuxkm_pie_reloc_tab.c' ]] || \
{ $(RM) -f '$(MODULE_TOP)/linuxkm/wc_linuxkm_pie_reloc_tab.c' && $(GENERATE_RELOC_TAB) < /dev/null > '$(MODULE_TOP)/linuxkm/wc_linuxkm_pie_reloc_tab.c'; }
@$(eval RELOC_TMP := $(shell mktemp "$(MAKE_TMPDIR)/wc_linuxkm_pie_reloc_tab.c.XXXXXX"))
@if [[ -f libwolfssl.ko ]]; then touch -r libwolfssl.ko '$(RELOC_TMP)'; fi
@RELOC_TMP=$$(mktemp "$(MAKE_TMPDIR)/wc_linuxkm_pie_reloc_tab.c.XXXXXX")
@trap 'rm "$$RELOC_TMP"' EXIT
@if [[ -f "$@" ]]; then touch -r "$@" "$$RELOC_TMP"; fi
+$(MAKE) ARCH='$(KERNEL_ARCH)' $(OVERRIDE_PATHS) $(CROSS_COMPILE) -C '$(KERNEL_ROOT)' M='$(MODULE_TOP)' $(KBUILD_EXTRA_FLAGS) CC_FLAGS_FTRACE=
# if the above make didn't build a fresh libwolfssl.ko, then the module is already up to date and we leave it untouched, assuring stability for purposes of module-update-fips-hash.
@if [[ ! libwolfssl.ko -nt '$(RELOC_TMP)' ]]; then rm '$(RELOC_TMP)'; echo ' Module already up-to-date.'; exit 0; fi
@$(READELF) --wide -r libwolfssl.ko | $(GENERATE_RELOC_TAB) >| '$(MODULE_TOP)/linuxkm/wc_linuxkm_pie_reloc_tab.c'
@if [[ ! "$@" -nt "$$RELOC_TMP" ]]; then echo ' Module already up-to-date.'; exit 0; fi
@SECTION_MAP=$$(mktemp)
@trap 'rm "$$SECTION_MAP"' EXIT
@export SECTION_MAP
@$(READELF) --wide --symbols "$@" | $(GENERATE_SECTION_MAP)
@$(READELF) --wide --relocs "$@" | $(GENERATE_RELOC_TAB) >| '$(MODULE_TOP)/linuxkm/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 | $(GENERATE_RELOC_TAB) >| '$(RELOC_TMP)'
@if diff '$(MODULE_TOP)/linuxkm/wc_linuxkm_pie_reloc_tab.c' '$(RELOC_TMP)'; then echo " Relocation table is stable."; else echo "PIE failed: relocation table is unstable." 1>&2; rm '$(RELOC_TMP)'; exit 1; fi
@rm '$(RELOC_TMP)'
@$(READELF) --wide --relocs "$@" | $(GENERATE_RELOC_TAB) >| "$$RELOC_TMP"
@if diff '$(MODULE_TOP)/linuxkm/wc_linuxkm_pie_reloc_tab.c' "$$RELOC_TMP"; then echo " Relocation table is stable."; else echo "PIE failed: relocation table is unstable." 1>&2; exit 1; fi
else
+$(MAKE) ARCH='$(KERNEL_ARCH)' $(OVERRIDE_PATHS) $(CROSS_COMPILE) -C '$(KERNEL_ROOT)' M='$(MODULE_TOP)' $(KBUILD_EXTRA_FLAGS)
endif
.PHONY: module-update-fips-hash
module-update-fips-hash: libwolfssl.ko
@if test -z '$(FIPS_HASH)'; then echo ' $$FIPS_HASH is unset' >&2; exit 1; fi
@set -e
@if test -z '$(FIPS_HASH)'; then echo ' $$FIPS_HASH is unset' >&2; exit 1; fi
@if [[ ! '$(FIPS_HASH)' =~ [0-9a-fA-F]{64} ]]; then echo ' $$FIPS_HASH is malformed' >&2; exit 1; fi
@readarray -t rodata_segment < <($(READELF) --wide --sections libwolfssl.ko | \
@readarray -t rodata_segment < <($(READELF) --wide --sections "$<" | \
sed -E -n 's/^[[:space:]]*\[[[:space:]]*([0-9]+)\][[:space:]]+\.rodata_wolfcrypt[[:space:]]+PROGBITS[[:space:]]+[0-9a-fA-F]+[[:space:]]+([0-9a-fA-F]+)[[:space:]].*$$/\1\n\2/p'); \
if [[ $${#rodata_segment[@]} != 2 ]]; then echo ' unexpected rodata_segment.' >&2; exit 1; fi; \
readarray -t verifyCore_attrs < <($(READELF) --wide --symbols libwolfssl.ko | \
readarray -t verifyCore_attrs < <($(READELF) --wide --symbols "$<" | \
sed -E -n 's/^[[:space:]]*[0-9]+: ([0-9a-fA-F]+)[[:space:]]+([0-9]+)[[:space:]]+OBJECT[[:space:]]+[A-Z]+[[:space:]]+[A-Z]+[[:space:]]+'"$${rodata_segment[0]}"'[[:space:]]+verifyCore$$/\1\n\2/p'); \
if [[ $${#verifyCore_attrs[@]} != 2 ]]; then echo ' unexpected verifyCore_attrs.' >&2; exit 1; fi; \
if [[ "$${verifyCore_attrs[1]}" != "65" ]]; then echo " verifyCore has unexpected length $${verifyCore_attrs[1]}." >&2; exit 1; fi; \
if [[ "$${verifyCore_attrs[1]}" != "65" ]]; then echo " verifyCore has unexpected length $${verifyCore_attrs[1]}." >&2; exit 1; fi; \
verifyCore_offset=$$((0x$${rodata_segment[1]} + 0x$${verifyCore_attrs[0]})); \
current_verifyCore=$$(dd bs=1 if=libwolfssl.ko skip=$$verifyCore_offset count=64 status=none); \
current_verifyCore=$$(dd bs=1 if="$<" skip=$$verifyCore_offset count=64 status=none); \
if [[ ! "$$current_verifyCore" =~ [0-9a-fA-F]{64} ]]; then echo " verifyCore at offset $$verifyCore_offset has unexpected value." >&2; exit 1; fi; \
if [[ '$(FIPS_HASH)' == "$$current_verifyCore" ]]; then echo ' Supplied FIPS_HASH matches existing verifyCore -- no update needed.'; exit 0; fi; \
echo -n '$(FIPS_HASH)' | dd bs=1 conv=notrunc of=libwolfssl.ko seek=$$verifyCore_offset count=64 status=none && \
echo " FIPS verifyCore updated successfully." && \
if [[ '$(FIPS_HASH)' == "$$current_verifyCore" ]]; then echo ' Supplied FIPS_HASH matches existing verifyCore -- no update needed.'; exit 0; fi; \
echo -n '$(FIPS_HASH)' | dd bs=1 conv=notrunc of="$<" seek=$$verifyCore_offset count=64 status=none && \
echo " FIPS verifyCore updated successfully." && \
if [[ -f libwolfssl.ko.signed ]]; then $(MAKE) -C . libwolfssl.ko.signed; fi
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 \
@set -e
@cd '$(KERNEL_ROOT)'
while read configline; do
case "$$configline" in
CONFIG_MODULE_SIG*=*)
declare "$${configline%=*}"="$${configline#*=}"
;;
esac
done < .config
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
@@ -234,10 +305,10 @@ install modules_install:
# note, must supply $(MODULE_TOP) as the src value for clean so that Kbuild is included, else
# the top Makefile (which is not for the kernel build) would be included here.
clean:
+$(MAKE) -C $(KERNEL_ROOT) M=$(MODULE_TOP) src=$(MODULE_TOP) clean
$(RM) -rf '$(MODULE_TOP)/linuxkm'
$(RM) -rf '$(MODULE_TOP)/wolfcrypt'
$(RM) -rf '$(MODULE_TOP)/src'
+$(MAKE) -C $(KERNEL_ROOT) M=$(MODULE_TOP) src=$(MODULE_TOP) clean
.PHONY: check
check:

View File

@@ -428,7 +428,9 @@
*/
#ifdef __PIE__
#include <linux/mm_types.h>
#if USE_SPLIT_PMD_PTLOCKS
static __always_inline struct page *pmd_to_page(pmd_t *pmd);
#endif
#endif
#include <linux/mm.h>
#endif
@@ -496,10 +498,21 @@
#endif /* linux ver >= 6.13 */
#if defined(_LINUX_REFCOUNT_H) || defined(_LINUX_REFCOUNT_TYPES_H)
#define WC_LKM_REFCOUNT_TO_INT(refcount) (atomic_read(&(refcount.refs)))
static inline int wc_lkm_refcount_to_int(refcount_t *refcount) {
_Pragma("GCC diagnostic push");
_Pragma("GCC diagnostic ignored \"-Wnested-externs\"");
return atomic_read(&(refcount->refs));
_Pragma("GCC diagnostic pop");
}
#else
#define WC_LKM_REFCOUNT_TO_INT(refcount) (atomic_read(&(refcount)))
static inline int wc_lkm_refcount_to_int(atomic_t *refcount) {
_Pragma("GCC diagnostic push");
_Pragma("GCC diagnostic ignored \"-Wnested-externs\"");
return atomic_read(&refcount);
_Pragma("GCC diagnostic pop");
}
#endif
#define WC_LKM_REFCOUNT_TO_INT(refcount) wc_lkm_refcount_to_int(&(refcount))
#endif /* !__PIE__ */
#endif /* LINUXKM_LKCAPI_REGISTER */
@@ -747,7 +760,7 @@
__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 const unsigned long wc_linuxkm_pie_reloc_tab_length;
extern ssize_t wc_linuxkm_normalize_relocations(
const u8 *text_in,
size_t text_in_len,

View File

@@ -864,8 +864,18 @@ MODULE_VERSION(LIBWOLFSSL_VERSION_STRING);
#ifdef WC_PIE_RELOC_TABLES
static inline int find_reloc_tab_offset(size_t text_in_offset) {
int ret, hop;
#define WC_TEXT_TAG (0x0 << 29)
#define WC_RODATA_TAG (0x1U << 29)
#define WC_RWDATA_TAG (0x2U << 29)
#define WC_BSS_TAG (0x3U << 29)
#define WC_OTHER_TAG (0x4U << 29)
#define WC_RELOC_TAG_MASK (0x7U << 29)
#define WC_RELOC_OFFSET_MASK (~WC_RELOC_TAG_MASK)
static inline long find_reloc_tab_offset(size_t text_in_offset) {
long ret;
unsigned long hop;
if (wc_linuxkm_pie_reloc_tab_length <= 1) {
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
pr_err("ERROR: %s failed at L %d.\n", __FUNCTION__, __LINE__);
@@ -878,45 +888,40 @@ static inline int find_reloc_tab_offset(size_t text_in_offset) {
#endif
return -1;
}
if (text_in_offset >= (size_t)wc_linuxkm_pie_reloc_tab[wc_linuxkm_pie_reloc_tab_length - 1]) {
if (text_in_offset >= (size_t)(wc_linuxkm_pie_reloc_tab[wc_linuxkm_pie_reloc_tab_length - 1] & WC_RELOC_OFFSET_MASK)) {
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
pr_err("ERROR: %s failed at L %d.\n", __FUNCTION__, __LINE__);
#endif
return -1;
}
for (ret = 0,
hop = (int)wc_linuxkm_pie_reloc_tab_length / 2;
hop = wc_linuxkm_pie_reloc_tab_length >> 1;
hop;
hop >>= 1)
{
if (text_in_offset == (size_t)wc_linuxkm_pie_reloc_tab[ret])
if (text_in_offset == (size_t)(wc_linuxkm_pie_reloc_tab[ret] & WC_RELOC_OFFSET_MASK))
break;
else if (text_in_offset > (size_t)wc_linuxkm_pie_reloc_tab[ret])
else if (text_in_offset > (size_t)(wc_linuxkm_pie_reloc_tab[ret] & WC_RELOC_OFFSET_MASK))
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))
while ((ret < (long)wc_linuxkm_pie_reloc_tab_length - 1) &&
((size_t)(wc_linuxkm_pie_reloc_tab[ret] & WC_RELOC_OFFSET_MASK) < text_in_offset))
++ret;
while ((ret > 0) &&
((size_t)wc_linuxkm_pie_reloc_tab[ret - 1] >= text_in_offset))
((size_t)(wc_linuxkm_pie_reloc_tab[ret - 1] & WC_RELOC_OFFSET_MASK) >= text_in_offset))
--ret;
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
if (ret < 0)
pr_err("ERROR: %s returning %d at L %d.\n", __FUNCTION__, ret, __LINE__);
pr_err("ERROR: %s returning %ld at L %d.\n", __FUNCTION__, ret, __LINE__);
#endif
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
@@ -941,7 +946,12 @@ ssize_t wc_linuxkm_normalize_relocations(
((uintptr_t)(text_in + text_in_len) > (uintptr_t)__wc_text_end))
{
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
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);
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);
#endif
return -1;
}
@@ -969,16 +979,21 @@ ssize_t wc_linuxkm_normalize_relocations(
++i)
{
size_t next_reloc = wc_linuxkm_pie_reloc_tab[i];
unsigned int reloc_tag;
int reloc_buf;
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
uintptr_t abs_ptr;
#endif
if (last_reloc > next_reloc) {
if ((last_reloc & WC_RELOC_OFFSET_MASK) > (next_reloc & WC_RELOC_OFFSET_MASK)) {
pr_err("BUG: out-of-order offset found at wc_linuxkm_pie_reloc_tab[%zd]: %zu > %zu\n",
i, last_reloc, next_reloc);
i, last_reloc & WC_RELOC_OFFSET_MASK, next_reloc & WC_RELOC_OFFSET_MASK);
return -1;
}
last_reloc = next_reloc;
reloc_tag = next_reloc & WC_RELOC_TAG_MASK;
next_reloc &= WC_RELOC_OFFSET_MASK;
next_reloc -= text_in_offset;
if (next_reloc >= text_in_len) {
@@ -996,7 +1011,14 @@ ssize_t wc_linuxkm_normalize_relocations(
/* set reloc_buf to the relative address from the live text segment. */
reloc_buf = (int)get_unaligned((int32_t *)&text_out[next_reloc]);
/* abs_ptr is the absolute address referred to by the relocation. we
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
/* when debugging runtime segment consistency, for the various data
* segments, recognize dest addrs a few bytes outside the segment -- the
* compiler occasionally generates these, e.g. __wc_rwdata_start - 1 in
* DoInCoreCheck() in kernel 6.1 build of FIPS v5, __wc_bss_start - 4 in
* kernel 4.4, and __wc_rodata_end + 26 in kernel 6.18.
*
* abs_ptr is the absolute address referred to by the relocation. we
* need this in order to identify the target segment of the relocation,
* thereby allowing us to use the correct normalization tag and
* corrective offset for the relocation.
@@ -1009,59 +1031,66 @@ ssize_t wc_linuxkm_normalize_relocations(
* 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;
#ifndef LINUXKM_PIE_DATA_SLOP_MARGIN
#define LINUXKM_PIE_DATA_SLOP_MARGIN 0x20
#endif
if ((abs_ptr >= (uintptr_t)__wc_text_start) &&
(abs_ptr <= (uintptr_t)__wc_text_end))
{
abs_ptr = (uintptr_t)text_in + next_reloc + 4 + reloc_buf;
#endif /* DEBUG_LINUXKM_PIE_SUPPORT */
switch (reloc_tag) {
case WC_TEXT_TAG:
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
if ((abs_ptr >= (uintptr_t)__wc_text_start) &&
(abs_ptr <= (uintptr_t)__wc_text_end))
++n_text_r;
else {
reloc_tag = WC_OTHER_TAG;
break;
}
#endif
/* internal references in the .wolfcrypt.text segment don't need
* normalization.
*/
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
++n_text_r;
#endif
continue;
}
/* for the various data segments, recognize dest addrs a few bytes
* outside the segment -- the compiler occasionally generates these,
* e.g. __wc_rwdata_start - 1 in DoInCoreCheck() in kernel 6.1 build of
* FIPS v5, __wc_bss_start - 4 in kernel 4.4, and __wc_rodata_end + 26
* in kernel 6.18.
*/
#ifndef LINUXKM_PIE_DATA_SLOP_MARGIN
#define LINUXKM_PIE_DATA_SLOP_MARGIN 0x20
#endif
else if ((abs_ptr >= (uintptr_t)__wc_rodata_start - LINUXKM_PIE_DATA_SLOP_MARGIN) &&
(abs_ptr <= (uintptr_t)__wc_rodata_end + LINUXKM_PIE_DATA_SLOP_MARGIN))
{
case WC_RODATA_TAG:
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
++n_rodata_r;
if ((abs_ptr >= (uintptr_t)__wc_rodata_start - LINUXKM_PIE_DATA_SLOP_MARGIN) &&
(abs_ptr <= (uintptr_t)__wc_rodata_end + LINUXKM_PIE_DATA_SLOP_MARGIN))
++n_rodata_r;
else
reloc_tag = WC_OTHER_TAG;
#endif
reloc_buf -= (int)((uintptr_t)__wc_rodata_start - 1 -
(uintptr_t)__wc_text_start);
reloc_buf ^= WC_RODATA_TAG;
}
else if ((abs_ptr >= (uintptr_t)__wc_rwdata_start - LINUXKM_PIE_DATA_SLOP_MARGIN) &&
(abs_ptr <= (uintptr_t)__wc_rwdata_end + LINUXKM_PIE_DATA_SLOP_MARGIN))
{
break;
case WC_RWDATA_TAG:
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
++n_rwdata_r;
if ((abs_ptr >= (uintptr_t)__wc_rwdata_start - LINUXKM_PIE_DATA_SLOP_MARGIN) &&
(abs_ptr <= (uintptr_t)__wc_rwdata_end + LINUXKM_PIE_DATA_SLOP_MARGIN))
++n_rwdata_r;
else
reloc_tag = WC_OTHER_TAG;
#endif
reloc_buf -= (int)((uintptr_t)__wc_rwdata_start - 1 -
(uintptr_t)__wc_text_start);
reloc_buf ^= WC_RWDATA_TAG;
}
else if ((abs_ptr >= (uintptr_t)__wc_bss_start - LINUXKM_PIE_DATA_SLOP_MARGIN) &&
(abs_ptr <= (uintptr_t)__wc_bss_end + LINUXKM_PIE_DATA_SLOP_MARGIN))
{
break;
case WC_BSS_TAG:
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
++n_bss_r;
if ((abs_ptr >= (uintptr_t)__wc_bss_start - LINUXKM_PIE_DATA_SLOP_MARGIN) &&
(abs_ptr <= (uintptr_t)__wc_bss_end + LINUXKM_PIE_DATA_SLOP_MARGIN))
++n_bss_r;
else
reloc_tag = WC_OTHER_TAG;
#endif
reloc_buf -= (int)((uintptr_t)__wc_bss_start - 1 -
(uintptr_t)__wc_text_start);
reloc_buf ^= WC_BSS_TAG;
break;
}
else {
if (reloc_tag == WC_OTHER_TAG) {
/* relocation referring to non-wolfcrypt segment -- these can only
* be stabilized by zeroing them.
*/
@@ -1075,7 +1104,7 @@ ssize_t wc_linuxkm_normalize_relocations(
pr_notice("found non-wolfcrypt relocation at text offset 0x%x to "
"addr 0x%x, text=%x-%x, rodata=%x-%x, "
"rwdata=%x-%x, bss=%x-%x\n",
wc_linuxkm_pie_reloc_tab[i],
wc_linuxkm_pie_reloc_tab[i] & WC_RELOC_OFFSET_MASK,
(unsigned)(uintptr_t)abs_ptr,
(unsigned)(uintptr_t)__wc_text_start,
(unsigned)(uintptr_t)__wc_text_end,
@@ -1467,8 +1496,8 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) {
++i)
if (*i == 0) {
pr_err("ERROR: wolfCrypt container redirect table initialization was "
"incomplete [%lu].\n",
i-(unsigned long *)&wolfssl_linuxkm_pie_redirect_table);
"incomplete [%u].\n",
(unsigned)(i-(unsigned long *)&wolfssl_linuxkm_pie_redirect_table));
return -EFAULT;
}
}

View File

@@ -710,12 +710,17 @@ void fe_frombytes(fe h,const unsigned char *s)
void fe_invert(fe out,const fe z)
{
fe t0 = {0};
fe t1 = {0};
fe t2 = {0};
fe t3 = {0};
fe t0;
fe t1;
fe t2;
fe t3;
int i = 0;
XMEMSET(&t0, 0, sizeof(t0));
XMEMSET(&t1, 0, sizeof(t1));
XMEMSET(&t2, 0, sizeof(t2));
XMEMSET(&t3, 0, sizeof(t3));
/* pow225521 */
fe_sq(t0,z);
fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1);
@@ -1328,11 +1333,15 @@ void fe_sq2(fe h,const fe f)
void fe_pow22523(fe out,const fe z)
{
fe t0 = {0};
fe t1 = {0};
fe t2 = {0};
fe t0;
fe t1;
fe t2;
int i = 0;
XMEMSET(&t0, 0, sizeof(t0));
XMEMSET(&t1, 0, sizeof(t1));
XMEMSET(&t2, 0, sizeof(t2));
fe_sq(t0,z);
fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1);
fe_mul(t1,z,t1);

View File

@@ -9824,8 +9824,8 @@ void ge_tobytes(unsigned char *s,const ge_p2 *h)
* then curve25519() won't get its WOLFSSL_LOCAL attribute unless we dummy-call
* it here.
*/
#if defined(WOLFSSL_API_PREFIX_MAP) && !defined(HAVE_CURVE25519) && \
!defined(FREESCALE_LTC_ECC)
#if defined(CURVED25519_ASM) && defined(WOLFSSL_API_PREFIX_MAP) && \
!defined(HAVE_CURVE25519) && !defined(FREESCALE_LTC_ECC)
WOLFSSL_LOCAL void _wc_curve25519_dummy(void);
WOLFSSL_LOCAL void _wc_curve25519_dummy(void) {
(void)curve25519((byte *)0, (byte *)0, (const byte *)0);