diff --git a/linuxkm/Kbuild b/linuxkm/Kbuild index 49d5225a5d..d902e596f5 100644 --- a/linuxkm/Kbuild +++ b/linuxkm/Kbuild @@ -43,6 +43,10 @@ ifeq "$(KERNEL_ARCH)" "aarch64" WOLFSSL_CFLAGS += -mno-outline-atomics else ifeq "$(KERNEL_ARCH)" "arm64" WOLFSSL_CFLAGS += -mno-outline-atomics +else ifeq "$(KERNEL_ARCH)" "arm" + # avoids R_ARM_THM_JUMP11 relocations, including a stubborn tail recursion + # optimization from wc_sp_cmp to wc_sp_cmp_mag: + WOLFSSL_CFLAGS += -fno-optimize-sibling-calls -Os endif obj-m := libwolfssl.o @@ -97,7 +101,7 @@ else WOLFSSL_CFLAGS_YES_VECTOR_INSNS := $(WOLFSSL_CFLAGS_NO_VECTOR_INSNS) endif -ccflags-y := $(WOLFSSL_CFLAGS) $(WOLFSSL_CFLAGS_NO_VECTOR_INSNS) +ccflags-y = $(WOLFSSL_CFLAGS) $(WOLFSSL_CFLAGS_NO_VECTOR_INSNS) ifeq "$(ENABLED_LINUXKM_PIE)" "yes" # note, we need -fno-stack-protector to avoid references to @@ -127,6 +131,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 @@ -139,7 +146,7 @@ ifeq "$(ENABLED_LINUXKM_PIE)" "yes" endif ifdef KERNEL_EXTRA_CFLAGS_REMOVE - ccflags-remove-y += KERNEL_EXTRA_CFLAGS_REMOVE + ccflags-remove-y += $(KERNEL_EXTRA_CFLAGS_REMOVE) endif $(obj)/libwolfssl.mod.o: ccflags-y := $(PIE_SUPPORT_FLAGS) diff --git a/linuxkm/Makefile b/linuxkm/Makefile index 089702ca1a..4cd05cf965 100644 --- a/linuxkm/Makefile +++ b/linuxkm/Makefile @@ -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 "; \ 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 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,139 @@ 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 + @[[ '$(V)' == 1 ]] && { echo 'MODULE_TOP = "$(MODULE_TOP)"'; + echo 'SRC_TOP = "$(SRC_TOP)"'; + echo 'AM_CPPFLAGS = "$(AM_CPPFLAGS)"'; + echo 'CPPFLAGS = "$(CPPFLAGS)"'; + echo 'AM_CFLAGS = "$(AM_CFLAGS)"'; + echo 'CFLAGS = "$(CFLAGS)"'; + echo 'KERNEL_EXTRA_CFLAGS = "$(KERNEL_EXTRA_CFLAGS)"'; + echo 'FIPS_OPTEST = "$(FIPS_OPTEST)"'; + echo 'AM_CCASFLAGS = "$(AM_CCASFLAGS)"'; + echo 'CCASFLAGS = "$(CCASFLAGS)"'; + echo 'src_libwolfssl_la_OBJECTS = "$(src_libwolfssl_la_OBJECTS)"'; + echo 'ENABLED_CRYPT_TESTS = "$(ENABLED_CRYPT_TESTS)"'; + echo 'ENABLED_LINUXKM_LKCAPI_REGISTER = "$(ENABLED_LINUXKM_LKCAPI_REGISTER)"'; + echo 'ENABLED_LINUXKM_BENCHMARKS = "$(ENABLED_LINUXKM_BENCHMARKS)"'; + echo 'ENABLED_LINUXKM_PIE = "$(ENABLED_LINUXKM_PIE)"'; + echo 'host_triplet = "$(host_triplet)"'; + echo 'build_triplet = "$(build_triplet)"'; + echo 'CC = "$(CC)"'; + echo 'AS = "$(AS)"'; + echo 'LD = "$(LD)"'; + echo 'READELF = "$(READELF)"'; + echo 'AWK = "$(AWK)"'; + echo 'TMPDIR = "$(TMPDIR)"'; + echo 'MAKE_TMPDIR = "$(MAKE_TMPDIR)"'; + echo 'KERNEL_ROOT = "$(KERNEL_ROOT)"'; + echo 'obj = "$(obj)"'; + echo 'RM = "$(RM)"'; + echo 'KERNEL_ARCH = "$(KERNEL_ARCH)"'; + echo 'FIPS_HASH = "$(FIPS_HASH)"'; + echo 'MAKE = "$(MAKE)"'; + echo 'ENABLED_ASM = "$(ENABLED_ASM)"'; + echo 'CFLAGS_FPU_DISABLE = "$(CFLAGS_FPU_DISABLE)"'; + echo 'CFLAGS_FPU_ENABLE = "$(CFLAGS_FPU_ENABLE)"'; + echo 'CFLAGS_SIMD_DISABLE = "$(CFLAGS_SIMD_DISABLE)"'; + echo 'CFLAGS_SIMD_ENABLE = "$(CFLAGS_SIMD_ENABLE)"'; + echo 'CFLAGS_AUTO_VECTORIZE_DISABLE = "$(CFLAGS_AUTO_VECTORIZE_DISABLE)"'; + echo 'CFLAGS_AUTO_VECTORIZE_ENABLE = "$(CFLAGS_AUTO_VECTORIZE_ENABLE)"'; + echo 'ASFLAGS_FPU_DISABLE_SIMD_ENABLE = "$(ASFLAGS_FPU_DISABLE_SIMD_ENABLE)"'; + echo 'ASFLAGS_FPU_ENABLE_SIMD_DISABLE = "$(ASFLAGS_FPU_ENABLE_SIMD_DISABLE)"'; + echo 'ASFLAGS_FPUSIMD_DISABLE = "$(ASFLAGS_FPUSIMD_DISABLE)"'; + echo 'ASFLAGS_FPUSIMD_ENABLE = "$(ASFLAGS_FPUSIMD_ENABLE)"'; } + @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 +346,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: diff --git a/linuxkm/linuxkm_wc_port.h b/linuxkm/linuxkm_wc_port.h index 97aad4fddb..834e95819e 100644 --- a/linuxkm/linuxkm_wc_port.h +++ b/linuxkm/linuxkm_wc_port.h @@ -428,7 +428,9 @@ */ #ifdef __PIE__ #include + #if USE_SPLIT_PMD_PTLOCKS static __always_inline struct page *pmd_to_page(pmd_t *pmd); + #endif #endif #include #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, diff --git a/linuxkm/lkcapi_sha_glue.c b/linuxkm/lkcapi_sha_glue.c index 196ade40fe..ab741057bd 100644 --- a/linuxkm/lkcapi_sha_glue.c +++ b/linuxkm/lkcapi_sha_glue.c @@ -1198,7 +1198,7 @@ static int wc_linuxkm_drbg_seed(struct crypto_rng *tfm, { struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_rng_ctx(tfm); u8 *seed_copy = NULL; - int ret; + int ret = 0; int n; if ((tfm->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm) || diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index 9735afebaf..788aa66007 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -142,11 +142,11 @@ static void lkmFipsCb(int ok, int err, const char* hash) } } } -#endif #ifdef WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE static int updateFipsHash(void); #endif +#endif /* HAVE_FIPS */ #ifdef WOLFSSL_LINUXKM_BENCHMARKS extern int wolfcrypt_benchmark_main(int argc, char** argv); @@ -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 #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. */ + #ifndef LINUXKM_PIE_DATA_SLOP_MARGIN + #define LINUXKM_PIE_DATA_SLOP_MARGIN 0x20 + #endif + abs_ptr = (uintptr_t)text_in + next_reloc + 4 + reloc_buf; +#endif /* DEBUG_LINUXKM_PIE_SUPPORT */ - if ((abs_ptr >= (uintptr_t)__wc_text_start) && - (abs_ptr <= (uintptr_t)__wc_text_end)) - { + 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; } } @@ -1478,7 +1507,7 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) { #endif /* WC_PIE_RELOC_TABLES */ -#ifdef WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE +#if defined(HAVE_FIPS) && defined(WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE) #include @@ -1734,7 +1763,7 @@ static int updateFipsHash(void) return ret; } -#endif /* WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE */ +#endif /* HAVE_FIPS && WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE */ #ifdef CONFIG_HAVE_KPROBES diff --git a/wolfcrypt/src/fe_operations.c b/wolfcrypt/src/fe_operations.c index bd36a424cf..e449ad5bd6 100644 --- a/wolfcrypt/src/fe_operations.c +++ b/wolfcrypt/src/fe_operations.c @@ -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); diff --git a/wolfcrypt/src/ge_operations.c b/wolfcrypt/src/ge_operations.c index 1aa4375eab..c6120d4d66 100644 --- a/wolfcrypt/src/ge_operations.c +++ b/wolfcrypt/src/ge_operations.c @@ -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);