mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-09 23:00:55 +02:00
Makefile.am: for linuxkm module target, pass through "module" target as such, for compatibility with alt LIBWOLFSSL_NAME.
linuxkm/Makefile: * don't use `readarray -d` -- it's a recent bashism; * rework libwolfssl-user-build/src/.libs/libwolfssl.so recipe to better isolate sub-build settings. * add support for HOSTCC and HOSTCFLAGS in libwolfssl.so build. * deploy $(QFLAG) --no-print-directory --no-silent in several submakes for neatness and resilience. * tweak $(LIBWOLFSSL_NAME).ko.signed recipe to add a "skipping" message and some consistency checking. linuxkm/README.md: update FIPS DRBG /proc/crypto content to show seed source. linuxkm/linuxkm_memory.c: fixes for format character portability in a RELOC_DEBUG_PRINTF() in wc_reloc_normalize_text). linuxkm/linuxkm_wc_port.h: pull in linux/moduleparam.h, and if WC_LINUXKM_SUPPORT_DUMP_TO_FILE, pull in linux/fs.h and linux/uaccess.h. linuxkm/module_hooks.c: implement WC_LINUXKM_SUPPORT_DUMP_TO_FILE: dump_to_file() and module args text_dump_path=... and rodata_dump_path=... linuxkm/patches/7.0/WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-7v0.patch: add to accommodate patch-breaking change in Linux 7dff99b354.
This commit is contained in:
@@ -637,6 +637,7 @@ WC_DILITHIUM_FIXED_ARRAY
|
||||
WC_DISABLE_RADIX_ZERO_PAD
|
||||
WC_FLAG_DONT_USE_AESNI
|
||||
WC_FORCE_LINUXKM_FORTIFY_SOURCE
|
||||
WC_LINUXKM_SUPPORT_DUMP_TO_FILE
|
||||
WC_LMS_FULL_HASH
|
||||
WC_NO_ASYNC_SLEEP
|
||||
WC_NO_RNG_SIMPLE
|
||||
|
||||
+1
-1
@@ -229,7 +229,7 @@ if BUILD_LINUXKM
|
||||
FIPS_FLAVOR
|
||||
|
||||
module:
|
||||
+$(MAKE) -C linuxkm libwolfssl.ko
|
||||
+$(MAKE) -C linuxkm module
|
||||
|
||||
module-update-fips-hash:
|
||||
+$(MAKE) -C linuxkm module-update-fips-hash
|
||||
|
||||
+66
-37
@@ -33,6 +33,8 @@ ifndef LIBWOLFSSL_NAME
|
||||
LIBWOLFSSL_NAME := libwolfssl
|
||||
endif
|
||||
|
||||
module: $(LIBWOLFSSL_NAME).ko
|
||||
|
||||
all: $(LIBWOLFSSL_NAME).ko $(LIBWOLFSSL_NAME).ko.signed
|
||||
|
||||
ifndef MODULE_TOP
|
||||
@@ -249,6 +251,7 @@ $(LIBWOLFSSL_NAME).ko:
|
||||
echo 'CPPFLAGS = "$(CPPFLAGS)"';
|
||||
echo 'AM_CFLAGS = "$(AM_CFLAGS)"';
|
||||
echo 'CFLAGS = "$(CFLAGS)"';
|
||||
echo 'HOSTCFLAGS = "$(HOSTCFLAGS)"';
|
||||
echo 'KERNEL_EXTRA_CFLAGS = "$(KERNEL_EXTRA_CFLAGS)"';
|
||||
echo 'FIPS_OPTEST = "$(FIPS_OPTEST)"';
|
||||
echo 'AM_CCASFLAGS = "$(AM_CCASFLAGS)"';
|
||||
@@ -261,6 +264,7 @@ $(LIBWOLFSSL_NAME).ko:
|
||||
echo 'host_triplet = "$(host_triplet)"';
|
||||
echo 'build_triplet = "$(build_triplet)"';
|
||||
echo 'CC = "$(CC)"';
|
||||
echo 'HOSTCC = "$(HOSTCC)"';
|
||||
echo 'AS = "$(AS)"';
|
||||
echo 'LD = "$(LD)"';
|
||||
echo 'READELF = "$(READELF)"';
|
||||
@@ -302,7 +306,8 @@ ifeq "$(ENABLED_LINUXKM_PIE)" "yes"
|
||||
@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=
|
||||
# --no-silent works around make bug that otherwise leads to "No rule to make target 's'. Stop." (due to a bug around $(MAKEFLAGS)) in --quiet builds.
|
||||
+$(MAKE) $(QFLAG) --no-print-directory --no-silent 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 [[ ! "$@" -nt "$$RELOC_TMP" ]]; then echo ' Module already up-to-date.'; exit 0; fi
|
||||
@SECTION_MAP=$$(mktemp)
|
||||
@@ -310,13 +315,16 @@ ifeq "$(ENABLED_LINUXKM_PIE)" "yes"
|
||||
@export SECTION_MAP
|
||||
@$(READELF) --wide --sections --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=
|
||||
+$(MAKE) $(QFLAG) --no-print-directory --no-silent ARCH='$(KERNEL_ARCH)' $(OVERRIDE_PATHS) $(CROSS_COMPILE) -C '$(KERNEL_ROOT)' M='$(MODULE_TOP)' $(KBUILD_EXTRA_FLAGS) CC_FLAGS_FTRACE=
|
||||
@$(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)
|
||||
# --no-silent works around make bug that otherwise leads to "No rule to make target 's'. Stop." (due to a bug around $(MAKEFLAGS)) in --quiet builds.
|
||||
+$(MAKE) $(QFLAG) --no-print-directory --no-silent ARCH='$(KERNEL_ARCH)' $(OVERRIDE_PATHS) $(CROSS_COMPILE) -C '$(KERNEL_ROOT)' M='$(MODULE_TOP)' $(KBUILD_EXTRA_FLAGS)
|
||||
endif
|
||||
|
||||
$(MODULE_TOP)/$(LIBWOLFSSL_NAME).ko: $(LIBWOLFSSL_NAME).ko
|
||||
|
||||
.PHONY: module-update-fips-hash
|
||||
module-update-fips-hash: $(LIBWOLFSSL_NAME).ko
|
||||
@set -e
|
||||
@@ -335,7 +343,7 @@ module-update-fips-hash: $(LIBWOLFSSL_NAME).ko
|
||||
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_NAME).ko.signed' ]]; then $(MAKE) -C . '$(LIBWOLFSSL_NAME).ko.signed'; fi
|
||||
if [[ -f '$(LIBWOLFSSL_NAME).ko.signed' ]]; then $(MAKE) $(QFLAG) --no-print-directory --no-silent -C . '$(LIBWOLFSSL_NAME).ko.signed'; fi
|
||||
|
||||
|
||||
# linuxkm-fips-hash implements offline (no-load) FIPS hash calculation and graft-in.
|
||||
@@ -348,45 +356,61 @@ module-update-fips-hash: $(LIBWOLFSSL_NAME).ko
|
||||
# depending on changes/config in the source directory. Also, aside from
|
||||
# FIPS_FLAVOR, inherited configuration settings in the environment are cleansed.
|
||||
|
||||
libwolfssl-user-build/src/.libs/libwolfssl.so:
|
||||
@set -e
|
||||
@$(RM) -rf '$(MODULE_TOP)/libwolfssl-user-build'
|
||||
@mkdir '$(MODULE_TOP)/libwolfssl-user-build'
|
||||
@cd '$(MODULE_TOP)/libwolfssl-user-build'
|
||||
@pushd '$(SRC_TOP)' >/dev/null
|
||||
@echo -n 'Populating tree of symlinks...'
|
||||
@readarray -d '' -t srcfiles < <(find examples src support tests testsuite wolfcrypt wolfssl configure *.in build-aux debian rpm scripts certs doc mcapi cmake linuxkm/*.[ch] \( -name options.h -o -name user_settings\* \) -prune -o \( ! -type d \) \( -name '*.[chsSi]' -o -name configure -o -name '*.in' -o -name \*.sh -o -path support/\* -o -path build-aux/\* -o -path debian/\* -o -path rpm/\* -o -path scripts/\* -o -path certs/\* -o -path doc/\* -o -path mcapi/\* -o -path cmake/\* \) -print0)
|
||||
@popd >/dev/null
|
||||
@for file in "$${srcfiles[@]}"; do if [[ ! -e "$$file" ]]; then mkdir -p "$$(dirname "$$file")" && cp --no-dereference --symbolic-link --no-clobber '$(SRC_TOP)'/"$$file" "$$file"; fi; done
|
||||
@echo ' done.'
|
||||
@echo '__attribute__ ((visibility("default"))) extern const char coreKey[];' > user_settings.h
|
||||
@echo > user_settings_asm.h
|
||||
@echo -n 'Configuring libwolfssl.so...'
|
||||
@unset WOLFSSL_CFLAGS WOLFCRYPT_PIE_FILES ASFLAGS_FPUSIMD_ENABLE ASFLAGS_FPU_DISABLE_SIMD_ENABLE src_libwolfssl_la_OBJECTS WOLFSSL_ASFLAGS AM_CFLAGS WOLFSSL_OBJ_FILES ENABLED_LINUXKM_LKCAPI_REGISTER EXTRA_LDFLAGS CC LD
|
||||
@./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'
|
||||
@echo ' done.'
|
||||
@echo -n 'Compiling and linking libwolfssl.so...'
|
||||
+$(MAKE) $(QFLAG) >/dev/null
|
||||
@echo ' done.'
|
||||
@echo -n 'Fixing FIPS hash...'
|
||||
@userhash=$$(wolfcrypt/test/testwolfcrypt 2>&1 | sed -n -E 's/^hash = (.+)$$/\1/p')
|
||||
@if [[ -z "$$userhash" ]]; then echo ' FIPS hash not found!' >&2; exit 1; fi
|
||||
@find wolfcrypt/src -name '*fips_test*o' -delete
|
||||
+$(MAKE) $(QFLAG) EXTRA_CFLAGS=-DWOLFCRYPT_FIPS_CORE_HASH_VALUE="$$userhash"
|
||||
@echo ' done.'
|
||||
FRESH_MAKEFLAGS := $(patsubst -j%,-j %,$(filter -%,$(filter-out -- --jobserver-auth=%,$(MAKEFLAGS))))
|
||||
FRESH_ENV := env -i HOME="$$HOME" PATH="/usr/local/bin:/usr/bin:/bin:$$PATH" LANG="$${LANG-C.UTF-8}" LC_ALL="$${LC_ALL-C.UTF-8}" TERM="$${TERM-dumb}"
|
||||
|
||||
linuxkm-fips-hash: libwolfssl-user-build/src/.libs/libwolfssl.so linuxkm-fips-hash.c
|
||||
.PHONY: $(MODULE_TOP)/libwolfssl-user-build/src/.libs/libwolfssl.so
|
||||
$(MODULE_TOP)/libwolfssl-user-build/src/.libs/libwolfssl.so: $(LIBWOLFSSL_NAME).ko
|
||||
@set -o errexit -o pipefail
|
||||
@if [[ '$(SRC_TOP)/configure' -nt '$@' ]]; then
|
||||
@ echo 'Purging stale libwolfssl-user-build tree.'
|
||||
@ $(RM) -rf '$(MODULE_TOP)/libwolfssl-user-build'
|
||||
@fi
|
||||
@mkdir -p '$(MODULE_TOP)/libwolfssl-user-build'
|
||||
@cd '$(MODULE_TOP)/libwolfssl-user-build'
|
||||
@if [[ ! -e '$(MODULE_TOP)/libwolfssl-user-build/configure' ]]; then
|
||||
@ pushd '$(SRC_TOP)' >/dev/null
|
||||
@ echo -n 'Populating tree of symlinks for user libwolfssl.so build...'
|
||||
@ readarray -t srcfiles < <(find examples src support tests testsuite wolfcrypt wolfssl configure *.in build-aux debian rpm scripts certs doc mcapi cmake linuxkm/*.[ch] \( -name options.h -o -name user_settings\* \) -prune -o \( ! -type d \) \( -name '*.[chsSi]' -o -name configure -o -name '*.in' -o -name \*.sh -o -path support/\* -o -path build-aux/\* -o -path debian/\* -o -path rpm/\* -o -path scripts/\* -o -path certs/\* -o -path doc/\* -o -path mcapi/\* -o -path cmake/\* \) -print)
|
||||
@ popd >/dev/null
|
||||
@ for file in "$${srcfiles[@]}"; do if [[ ! -e "$$file" ]]; then mkdir -p "$$(dirname "$$file")" && cp --no-dereference --symbolic-link --no-clobber '$(SRC_TOP)'/"$$file" "$$file"; fi; done
|
||||
@ echo ' done.'
|
||||
@fi
|
||||
@if [[ ! -f user_settings.h ]]; then
|
||||
@ echo '__attribute__ ((visibility("default"))) extern const char coreKey[];' > user_settings.h
|
||||
@ echo > user_settings_asm.h
|
||||
@fi
|
||||
@if [[ -f Makefile ]]; then
|
||||
@ 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))'
|
||||
@ echo ' done.'
|
||||
@fi
|
||||
@echo -n 'Building user libwolfssl.so...'
|
||||
@$(FRESH_ENV) $(MAKE) $(QFLAG) $(FRESH_MAKEFLAGS) >/dev/null
|
||||
@echo ' done.'
|
||||
@echo -n 'Fixing FIPS hash in user libwolfssl.so...'
|
||||
@if ! userhash=$$(wolfcrypt/test/testwolfcrypt 2>&1 | sed -n -E 's/^hash = (.+)$$/\1/p'); then
|
||||
@ if [[ -z "$$userhash" ]]; then echo ' FIPS hash not found!' >&2; exit 1; fi
|
||||
@ find wolfcrypt/src -name '*fips_test*o' -delete
|
||||
@ $(FRESH_ENV) $(MAKE) $(QFLAG) $(FRESH_MAKEFLAGS) EXTRA_CFLAGS=-DWOLFCRYPT_FIPS_CORE_HASH_VALUE="$$userhash" >/dev/null
|
||||
@ echo ' done.'
|
||||
@else
|
||||
@ @echo ' already matches (no update needed).'
|
||||
@fi
|
||||
|
||||
linuxkm-fips-hash: $(MODULE_TOP)/libwolfssl-user-build/src/.libs/libwolfssl.so linuxkm-fips-hash.c
|
||||
@set -e
|
||||
@echo -n 'Compiling linuxkm-fips-hash...'
|
||||
# note direct invocation of cc -- we are compiling for the build host, not the target host.
|
||||
@cc -Wall -Wextra -O2 -I'$(MODULE_TOP)/libwolfssl-user-build' -o linuxkm-fips-hash linuxkm/linuxkm-fips-hash.c -L '$(MODULE_TOP)/libwolfssl-user-build/src/.libs' -Wl,-rpath-link='$(MODULE_TOP)/libwolfssl-user-build/src/.libs' -Wl,-rpath='$(MODULE_TOP)/libwolfssl-user-build/src/.libs' -lwolfssl
|
||||
@$(or $(HOSTCC),cc) $(or $(HOSTCFLAGS),-Wall -Wextra -O2) -I'$(MODULE_TOP)/libwolfssl-user-build' -o linuxkm-fips-hash linuxkm/linuxkm-fips-hash.c -L '$(MODULE_TOP)/libwolfssl-user-build/src/.libs' -Wl,-rpath-link='$(MODULE_TOP)/libwolfssl-user-build/src/.libs' -Wl,-rpath='$(MODULE_TOP)/libwolfssl-user-build/src/.libs' -lwolfssl
|
||||
@echo ' done.'
|
||||
|
||||
.PHONY: module-with-matching-fips-hash
|
||||
module-with-matching-fips-hash: $(LIBWOLFSSL_NAME).ko linuxkm-fips-hash
|
||||
@set -e
|
||||
@./linuxkm-fips-hash-wrapper.sh "$<" $(QFLAG) $(VFLAG)
|
||||
+$(MAKE) $(QFLAG) -C . '$(LIBWOLFSSL_NAME).ko.signed'
|
||||
+$(MAKE) $(QFLAG) --no-print-directory --no-silent -C . '$(LIBWOLFSSL_NAME).ko.signed'
|
||||
|
||||
.PHONY: module-with-matching-fips-hash-no-sign
|
||||
module-with-matching-fips-hash-no-sign: $(LIBWOLFSSL_NAME).ko linuxkm-fips-hash
|
||||
@@ -406,7 +430,9 @@ else
|
||||
;;
|
||||
esac
|
||||
done < .config
|
||||
if [[ "$${CONFIG_MODULE_SIG}" = "y" && -n "$${CONFIG_MODULE_SIG_KEY}" && \
|
||||
if [[ "$${CONFIG_MODULE_SIG}" != "y" ]]; then
|
||||
echo ' [skipping $@ -- CONFIG_MODULE_SIG is unset in target kernel]'
|
||||
elif [[ -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#\"}"
|
||||
@@ -426,19 +452,22 @@ else
|
||||
if [[ "$(quiet)" != "silent_" ]]; then
|
||||
echo " Module $@ signed by $${CONFIG_MODULE_SIG_KEY}."
|
||||
fi
|
||||
elif [[ ! -f '$(MODULE_TOP)/$@' || '$(MODULE_TOP)/$<' -nt '$(MODULE_TOP)/$@' ]]; then
|
||||
echo 'Unable to generate $@ from $<: CONFIG_MODULE_SIG_KEY and/or CONFIG_MODULE_SIG_HASH is missing.' >&2
|
||||
exit 1
|
||||
fi
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: install modules_install
|
||||
install modules_install:
|
||||
+$(MAKE) -C $(KERNEL_ROOT) M=$(MODULE_TOP) src=$(SRC_TOP) INSTALL_MOD_DIR=wolfssl modules_install
|
||||
+$(MAKE) $(QFLAG) --no-silent -C $(KERNEL_ROOT) M=$(MODULE_TOP) src=$(SRC_TOP) INSTALL_MOD_DIR=wolfssl modules_install
|
||||
|
||||
.PHONY: clean
|
||||
# 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
|
||||
+$(MAKE) $(QFLAG) --no-silent -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'
|
||||
|
||||
+2
-2
@@ -92,10 +92,10 @@ libwolfssl: kernel global random_bytes handlers installed.
|
||||
```
|
||||
|
||||
Additionally, `/proc/crypto` will advertise that the FIPS DRBG is installed at
|
||||
highest priority "-with-global-replace":
|
||||
highest priority, with "-wolfentropy" and/or "-rdseed", and "-with-global-replace":
|
||||
```ini
|
||||
name : stdrng
|
||||
driver : sha2-256-drbg-nopr-wolfcrypt-fips-140-3-with-global-replace
|
||||
driver : sha2-256-drbg-nopr-wolfentropy-wolfcrypt-fips-140-3-with-global-replace
|
||||
module : libwolfssl
|
||||
priority : 100000
|
||||
refcnt : 2
|
||||
|
||||
+13
-13
@@ -354,23 +354,23 @@ ssize_t wc_reloc_normalize_text(
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
if (reloc_buf >= seg_end - seg_beg) {
|
||||
++n_oob_r;
|
||||
RELOC_DEBUG_PRINTF("WARNING: normalized value is out of bounds (%s0x%lx) at index %ld, text offset 0x%x, reloc type %s, "
|
||||
"dest seg .%s_wolfcrypt, offset from text to dest segment %s0x%lx, raw dest addr %s0x%lx, "
|
||||
"seg span 0x%lx - 0x%lx, seg size 0x%lx, text base 0x%lx\n",
|
||||
(sword64)reloc_buf < 0 ? "-" : "",
|
||||
(sword64)reloc_buf < 0 ? -reloc_buf : reloc_buf,
|
||||
i,
|
||||
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",
|
||||
(long long)reloc_buf < 0 ? "-" : "",
|
||||
(long long)reloc_buf < 0 ? -(long long)reloc_buf : (long long)reloc_buf,
|
||||
(long long)i,
|
||||
next_reloc->offset,
|
||||
layout->name,
|
||||
seg_name,
|
||||
seg_beg < seg_map->text_start ? "-" : "+",
|
||||
seg_beg < seg_map->text_start ? (word64)seg_map->text_start - seg_beg : seg_beg - (word64)seg_map->text_start,
|
||||
(layout->is_signed && ((sword64)raw_dest_addr < 0)) ? "-" : "",
|
||||
(layout->is_signed && ((sword64)raw_dest_addr < 0)) ? (word64)-(sword64)raw_dest_addr : raw_dest_addr,
|
||||
(word64)seg_beg,
|
||||
(word64)seg_end,
|
||||
(word64)(seg_end - seg_beg),
|
||||
(word64)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,
|
||||
(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);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -459,6 +459,7 @@
|
||||
#ifndef WC_CONTAINERIZE_THIS
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/delay.h>
|
||||
#endif
|
||||
|
||||
@@ -508,6 +509,10 @@
|
||||
#endif /* !WOLFCRYPT_ONLY */
|
||||
#endif /* !WC_CONTAINERIZE_THIS */
|
||||
|
||||
#ifdef WC_LINUXKM_SUPPORT_DUMP_TO_FILE
|
||||
#include <linux/fs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#endif
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
#if __has_include(<linux/sched/task_stack.h>)
|
||||
|
||||
@@ -239,6 +239,74 @@ WC_MAYBE_UNUSED static int linuxkm_lkcapi_sysfs_deinstall_node(struct kobj_attri
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WC_LINUXKM_SUPPORT_DUMP_TO_FILE
|
||||
static ssize_t dump_to_file(const char *path, const u8 *buf, size_t buf_len)
|
||||
{
|
||||
loff_t pos = 0;
|
||||
struct file *fp;
|
||||
ssize_t ret;
|
||||
char tmp;
|
||||
|
||||
if (buf_len == 0) {
|
||||
pr_info("libwolfssl: dump_to_file() called with buf_len == 0. Not dumping.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
WC_SANITIZE_DISABLE();
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0)
|
||||
ret = probe_kernel_read(&tmp, buf, 1);
|
||||
if (ret == 0)
|
||||
ret = probe_kernel_read(&tmp, buf + buf_len - 1, 1);
|
||||
#else
|
||||
ret = copy_from_kernel_nofault(&tmp, buf, 1);
|
||||
if (ret == 0)
|
||||
ret = copy_from_kernel_nofault(&tmp, buf + buf_len - 1, 1);
|
||||
#endif
|
||||
WC_SANITIZE_ENABLE();
|
||||
if (ret != 0) {
|
||||
pr_err("libwolfssl: cannot safely read from buffer %px: %d\n", buf, (int)ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
fp = filp_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (IS_ERR(fp)) {
|
||||
pr_err("libwolfssl: cannot open %s: %ld\n", path, PTR_ERR(fp));
|
||||
return PTR_ERR(fp);
|
||||
}
|
||||
|
||||
WC_SANITIZE_DISABLE();
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
|
||||
/* kernel_write() exported by 7bb307e894d51 */
|
||||
ret = kernel_write(fp, buf, buf_len, &pos);
|
||||
#else
|
||||
ret = vfs_write(fp, buf, buf_len, &pos);
|
||||
#endif
|
||||
WC_SANITIZE_ENABLE();
|
||||
|
||||
filp_close(fp, NULL);
|
||||
|
||||
if (ret < 0)
|
||||
pr_err("libwolfssl: write to %s failed: %zd\n", path, ret);
|
||||
else if ((size_t)ret != buf_len)
|
||||
pr_warn("libwolfssl: short write to %s: %zd of %zu bytes\n", path, ret, buf_len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *text_dump_path;
|
||||
static char *rodata_dump_path;
|
||||
|
||||
/* indent these so they don't look like flush-left function calls. */
|
||||
module_param(text_dump_path, charp, 0444);
|
||||
module_param(rodata_dump_path, charp, 0444);
|
||||
|
||||
MODULE_PARM_DESC(text_dump_path,
|
||||
"Path to dump live .wolfcrypt_text section to (e.g. /tmp/wc_text.bin)");
|
||||
MODULE_PARM_DESC(rodata_dump_path,
|
||||
"Path to dump live .wolfcrypt_rodata section to (e.g. /tmp/wc_rodata.bin)");
|
||||
|
||||
#endif /* WC_LINUXKM_SUPPORT_DUMP_TO_FILE */
|
||||
|
||||
#ifdef HAVE_FIPS
|
||||
static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
@@ -503,6 +571,27 @@ static int wolfssl_init(void)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
#ifdef WC_LINUXKM_SUPPORT_DUMP_TO_FILE
|
||||
|
||||
#ifdef WC_SYM_RELOC_TABLES
|
||||
if (text_dump_path) {
|
||||
if (dump_to_file(text_dump_path, (u8 *)__wc_text_start, (size_t)((uintptr_t)__wc_text_end - (uintptr_t)__wc_text_start)) == 0)
|
||||
pr_info("libwolfssl: dumped .wolfcrypt_text (%zu bytes) to %s.\n", (size_t)((uintptr_t)__wc_text_end - (uintptr_t)__wc_text_start), text_dump_path);
|
||||
}
|
||||
if (rodata_dump_path) {
|
||||
if (dump_to_file(rodata_dump_path, (u8 *)__wc_rodata_start, (size_t)(__wc_rodata_end - __wc_rodata_start)) == 0)
|
||||
pr_info("libwolfssl: dumped .wolfcrypt_rodata (%zu bytes) to %s.\n", (size_t)((uintptr_t)__wc_rodata_end - (uintptr_t)__wc_rodata_start), text_dump_path);
|
||||
}
|
||||
#else
|
||||
if ((text_dump_path != NULL) ||
|
||||
(rodata_dump_path != NULL))
|
||||
{
|
||||
pr_info("libwolfssl: ignoring module dump path argument(s) -- module lacks WC_SYM_RELOC_TABLES.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WC_LINUXKM_SUPPORT_DUMP_TO_FILE */
|
||||
|
||||
#ifdef WC_LINUXKM_TEST_INET_PTON
|
||||
{
|
||||
const char *src;
|
||||
|
||||
@@ -0,0 +1,484 @@
|
||||
--- linux-next-9999/drivers/char/random.c.dist 2026-02-27 20:38:28.210284927 +0000
|
||||
+++ linux-next-9999/drivers/char/random.c 2026-02-27 20:39:23.770059819 +0000
|
||||
@@ -67,6 +67,265 @@
|
||||
#include <asm/irq_regs.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
+#ifdef WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS
|
||||
+
|
||||
+#include <linux/delay.h>
|
||||
+
|
||||
+static atomic_long_t random_bytes_cb_owner =
|
||||
+ ATOMIC_INIT((long)NULL);
|
||||
+static atomic_t random_bytes_cb_refcnt =
|
||||
+ ATOMIC_INIT(0); /* 0 if unregistered, 1 if no calls in flight. */
|
||||
+static _get_random_bytes_cb_t _get_random_bytes_cb;
|
||||
+static get_random_bytes_user_cb_t get_random_bytes_user_cb;
|
||||
+static crng_ready_cb_t crng_ready_cb;
|
||||
+static mix_pool_bytes_cb_t mix_pool_bytes_cb;
|
||||
+static credit_init_bits_cb_t credit_init_bits_cb;
|
||||
+static crng_reseed_cb_t crng_reseed_cb;
|
||||
+
|
||||
+int wolfssl_linuxkm_register_random_bytes_handlers(
|
||||
+ struct module *new_random_bytes_cb_owner,
|
||||
+ const struct wolfssl_linuxkm_random_bytes_handlers *handlers)
|
||||
+{
|
||||
+ if ((new_random_bytes_cb_owner == NULL) ||
|
||||
+ (handlers == NULL) ||
|
||||
+ (handlers->_get_random_bytes == NULL) ||
|
||||
+ (handlers->get_random_bytes_user == NULL)) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* random_bytes_cb_owner is used to enforce serialization of
|
||||
+ * wolfssl_register_random_bytes_handlers() and
|
||||
+ * wolfssl_unregister_random_bytes_handlers().
|
||||
+ */
|
||||
+ if (atomic_long_cmpxchg(&random_bytes_cb_owner,
|
||||
+ (long)NULL,
|
||||
+ (long)new_random_bytes_cb_owner)
|
||||
+ != (long)NULL) {
|
||||
+ return -EBUSY;
|
||||
+ }
|
||||
+
|
||||
+ {
|
||||
+ int current_random_bytes_cb_refcnt = atomic_read(&random_bytes_cb_refcnt);
|
||||
+
|
||||
+ if (current_random_bytes_cb_refcnt) {
|
||||
+ pr_err("BUG: random_bytes_cb_refcnt == %d with null random_bytes_cb_owner",
|
||||
+ current_random_bytes_cb_refcnt);
|
||||
+ atomic_long_set(&random_bytes_cb_owner, (long)NULL);
|
||||
+ return -EFAULT;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!try_module_get(new_random_bytes_cb_owner)) {
|
||||
+ atomic_long_set(&random_bytes_cb_owner, (long)NULL);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ _get_random_bytes_cb = handlers->_get_random_bytes;
|
||||
+ get_random_bytes_user_cb = handlers->get_random_bytes_user;
|
||||
+ crng_ready_cb = handlers->crng_ready;
|
||||
+ mix_pool_bytes_cb = handlers->mix_pool_bytes;
|
||||
+ credit_init_bits_cb = handlers->credit_init_bits;
|
||||
+ crng_reseed_cb = handlers->crng_reseed;
|
||||
+
|
||||
+ barrier();
|
||||
+ atomic_set_release(&random_bytes_cb_refcnt, 1);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(wolfssl_linuxkm_register_random_bytes_handlers);
|
||||
+
|
||||
+int wolfssl_linuxkm_unregister_random_bytes_handlers(void)
|
||||
+{
|
||||
+ int current_random_bytes_cb_refcnt;
|
||||
+ int n_tries;
|
||||
+
|
||||
+ if (atomic_long_read(&random_bytes_cb_owner) == 0)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ /* we're racing the kernel at large to try to catch random_bytes_cb_refcnt
|
||||
+ * with no callers in flight -- retry and relax up to 100 times.
|
||||
+ */
|
||||
+ for (n_tries = 0; n_tries < 100; ++n_tries) {
|
||||
+ current_random_bytes_cb_refcnt = atomic_cmpxchg(&random_bytes_cb_refcnt, 1, 0);
|
||||
+ if (current_random_bytes_cb_refcnt == 1)
|
||||
+ break;
|
||||
+ if (current_random_bytes_cb_refcnt < 0) {
|
||||
+ pr_err("BUG: random_bytes_cb_refcnt is %d in %s.",
|
||||
+ current_random_bytes_cb_refcnt, __func__);
|
||||
+ break;
|
||||
+ }
|
||||
+ if (msleep_interruptible(10) != 0)
|
||||
+ return -EINTR;
|
||||
+ }
|
||||
+ if (current_random_bytes_cb_refcnt != 1) {
|
||||
+ pr_warn("WARNING: %s called with random_bytes_cb_refcnt == %d", __func__,
|
||||
+ current_random_bytes_cb_refcnt);
|
||||
+ return -EBUSY;
|
||||
+ }
|
||||
+
|
||||
+ _get_random_bytes_cb = NULL;
|
||||
+ get_random_bytes_user_cb = NULL;
|
||||
+ crng_ready_cb = NULL;
|
||||
+ mix_pool_bytes_cb = NULL;
|
||||
+ credit_init_bits_cb = NULL;
|
||||
+ crng_reseed_cb = NULL;
|
||||
+
|
||||
+ module_put((struct module *)atomic_long_read(&random_bytes_cb_owner));
|
||||
+ barrier();
|
||||
+ atomic_long_set(&random_bytes_cb_owner, (long)NULL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(wolfssl_linuxkm_unregister_random_bytes_handlers);
|
||||
+
|
||||
+static __always_inline int reserve_random_bytes_cb(void)
|
||||
+{
|
||||
+ int current_random_bytes_cb_refcnt =
|
||||
+ atomic_read_acquire(&random_bytes_cb_refcnt);
|
||||
+
|
||||
+ if (current_random_bytes_cb_refcnt == 0)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ if (current_random_bytes_cb_refcnt < 0) {
|
||||
+ pr_err("BUG: random_bytes_cb_refcnt is %d in %s.",
|
||||
+ current_random_bytes_cb_refcnt, __func__);
|
||||
+ return -EFAULT;
|
||||
+ }
|
||||
+
|
||||
+ for (;;) {
|
||||
+ int orig_random_bytes_cb_refcnt =
|
||||
+ atomic_cmpxchg(
|
||||
+ &random_bytes_cb_refcnt,
|
||||
+ current_random_bytes_cb_refcnt,
|
||||
+ current_random_bytes_cb_refcnt + 1);
|
||||
+ if (orig_random_bytes_cb_refcnt == current_random_bytes_cb_refcnt)
|
||||
+ return 0;
|
||||
+ else if (orig_random_bytes_cb_refcnt == 0)
|
||||
+ return -ENODEV;
|
||||
+ current_random_bytes_cb_refcnt = orig_random_bytes_cb_refcnt;
|
||||
+ }
|
||||
+
|
||||
+ __builtin_unreachable();
|
||||
+}
|
||||
+
|
||||
+static __always_inline void release_random_bytes_cb(void)
|
||||
+{
|
||||
+ atomic_dec(&random_bytes_cb_refcnt);
|
||||
+}
|
||||
+
|
||||
+static inline int call__get_random_bytes_cb(void *buf, size_t len)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ if (_get_random_bytes_cb == NULL)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ ret = reserve_random_bytes_cb();
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = _get_random_bytes_cb(buf, len);
|
||||
+
|
||||
+ release_random_bytes_cb();
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static inline ssize_t call_get_random_bytes_user_cb(struct iov_iter *iter)
|
||||
+{
|
||||
+ ssize_t ret;
|
||||
+
|
||||
+ if (get_random_bytes_user_cb == NULL)
|
||||
+ return -ECANCELED;
|
||||
+
|
||||
+ ret = (ssize_t)reserve_random_bytes_cb();
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = get_random_bytes_user_cb(iter);
|
||||
+
|
||||
+ release_random_bytes_cb();
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static inline bool call_crng_ready_cb(void)
|
||||
+{
|
||||
+ bool ret;
|
||||
+
|
||||
+ /* Null crng_ready_cb signifies that the DRBG is always ready, i.e. that if
|
||||
+ * called, it will always have or obtain sufficient entropy to fulfill the
|
||||
+ * call.
|
||||
+ */
|
||||
+ if (crng_ready_cb == NULL)
|
||||
+ return 1;
|
||||
+
|
||||
+ if (reserve_random_bytes_cb() != 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ ret = crng_ready_cb();
|
||||
+
|
||||
+ release_random_bytes_cb();
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static inline int call_mix_pool_bytes_cb(const void *buf, size_t len)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ if (mix_pool_bytes_cb == NULL)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ ret = reserve_random_bytes_cb();
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = mix_pool_bytes_cb(buf, len);
|
||||
+
|
||||
+ release_random_bytes_cb();
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static inline int call_credit_init_bits_cb(size_t bits)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ if (credit_init_bits_cb == NULL)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ ret = reserve_random_bytes_cb();
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = credit_init_bits_cb(bits);
|
||||
+
|
||||
+ release_random_bytes_cb();
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static inline int call_crng_reseed_cb(void)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ if (crng_reseed_cb == NULL)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ ret = reserve_random_bytes_cb();
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = crng_reseed_cb();
|
||||
+
|
||||
+ release_random_bytes_cb();
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+#endif /* WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS */
|
||||
+
|
||||
/*********************************************************************
|
||||
*
|
||||
* Initialization and readiness waiting.
|
||||
@@ -87,7 +346,16 @@ static enum {
|
||||
CRNG_READY = 2 /* Fully initialized with POOL_READY_BITS collected */
|
||||
} crng_init __read_mostly = CRNG_EMPTY;
|
||||
static DEFINE_STATIC_KEY_FALSE(crng_is_ready);
|
||||
+
|
||||
#define crng_ready() (static_branch_likely(&crng_is_ready) || crng_init >= CRNG_READY)
|
||||
+#ifdef WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS
|
||||
+ #define crng_ready_by_cb() (atomic_read(&random_bytes_cb_refcnt) && call_crng_ready_cb())
|
||||
+ #define crng_ready_maybe_cb() (atomic_read(&random_bytes_cb_refcnt) ? \
|
||||
+ (call_crng_ready_cb() || crng_ready()) : crng_ready())
|
||||
+#else
|
||||
+ #define crng_ready_maybe_cb() crng_ready()
|
||||
+#endif
|
||||
+
|
||||
/* Various types of waiters for crng_init->CRNG_READY transition. */
|
||||
static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
|
||||
static struct fasync_struct *fasync;
|
||||
@@ -111,7 +379,7 @@ MODULE_PARM_DESC(ratelimit_disable, "Dis
|
||||
*/
|
||||
bool rng_is_initialized(void)
|
||||
{
|
||||
- return crng_ready();
|
||||
+ return crng_ready_maybe_cb();
|
||||
}
|
||||
EXPORT_SYMBOL(rng_is_initialized);
|
||||
|
||||
@@ -135,11 +403,11 @@ static void try_to_generate_entropy(void
|
||||
*/
|
||||
int wait_for_random_bytes(void)
|
||||
{
|
||||
- while (!crng_ready()) {
|
||||
+ while (!crng_ready_maybe_cb()) {
|
||||
int ret;
|
||||
|
||||
try_to_generate_entropy();
|
||||
- ret = wait_event_interruptible_timeout(crng_init_wait, crng_ready(), HZ);
|
||||
+ ret = wait_event_interruptible_timeout(crng_init_wait, crng_ready_maybe_cb(), HZ);
|
||||
if (ret)
|
||||
return ret > 0 ? 0 : ret;
|
||||
}
|
||||
@@ -159,7 +427,7 @@ int __cold execute_with_initialized_rng(
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&random_ready_notifier.lock, flags);
|
||||
- if (crng_ready())
|
||||
+ if (crng_ready_maybe_cb())
|
||||
nb->notifier_call(nb, 0, NULL);
|
||||
else
|
||||
ret = raw_notifier_chain_register((struct raw_notifier_head *)&random_ready_notifier.head, nb);
|
||||
@@ -395,6 +663,14 @@ static void _get_random_bytes(void *buf,
|
||||
if (!len)
|
||||
return;
|
||||
|
||||
+#ifdef WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS
|
||||
+ /* If call__get_random_bytes_cb() doesn't succeed, flow continues to
|
||||
+ * the native implementation. _get_random_bytes() must succeed.
|
||||
+ */
|
||||
+ if (call__get_random_bytes_cb(buf, len) == 0)
|
||||
+ return;
|
||||
+#endif
|
||||
+
|
||||
first_block_len = min_t(size_t, 32, len);
|
||||
crng_make_state(&chacha_state, buf, first_block_len);
|
||||
len -= first_block_len;
|
||||
@@ -440,6 +716,18 @@ static ssize_t get_random_bytes_user(str
|
||||
if (unlikely(!iov_iter_count(iter)))
|
||||
return 0;
|
||||
|
||||
+#ifdef WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS
|
||||
+ {
|
||||
+ ssize_t cb_ret = call_get_random_bytes_user_cb(iter);
|
||||
+ /* If the callback returns -ECANCELED, that signals that iter is
|
||||
+ * still intact, and flow can safely continue to the native
|
||||
+ * implementation.
|
||||
+ */
|
||||
+ if (cb_ret != -ECANCELED)
|
||||
+ return cb_ret;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Immediately overwrite the ChaCha key at index 4 with random
|
||||
* bytes, in case userspace causes copy_to_iter() below to sleep
|
||||
@@ -515,7 +803,7 @@ type get_random_ ##type(void) \
|
||||
struct batch_ ##type *batch; \
|
||||
unsigned long next_gen; \
|
||||
\
|
||||
- if (!crng_ready()) { \
|
||||
+ if (!crng_ready_maybe_cb()) { \
|
||||
_get_random_bytes(&ret, sizeof(ret)); \
|
||||
return ret; \
|
||||
} \
|
||||
@@ -651,6 +939,11 @@ static void mix_pool_bytes(const void *b
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
+#ifdef WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS
|
||||
+ (void)call_mix_pool_bytes_cb(buf, len);
|
||||
+ /* continue to mix into native pool too. */
|
||||
+#endif
|
||||
+
|
||||
spin_lock_irqsave(&input_pool.lock, flags);
|
||||
_mix_pool_bytes(buf, len);
|
||||
spin_unlock_irqrestore(&input_pool.lock, flags);
|
||||
@@ -710,7 +1003,13 @@ static void extract_entropy(void *buf, s
|
||||
memzero_explicit(&block, sizeof(block));
|
||||
}
|
||||
|
||||
-#define credit_init_bits(bits) if (!crng_ready()) _credit_init_bits(bits)
|
||||
+#ifdef WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS
|
||||
+ #define credit_init_bits(bits) do { (void)call_credit_init_bits_cb(bits); \
|
||||
+ if (!crng_ready()) \
|
||||
+ _credit_init_bits(bits); } while (0)
|
||||
+#else
|
||||
+ #define credit_init_bits(bits) do { if (!crng_ready()) _credit_init_bits(bits); } while (0)
|
||||
+#endif
|
||||
|
||||
static void __cold _credit_init_bits(size_t bits)
|
||||
{
|
||||
@@ -1396,7 +1695,7 @@ SYSCALL_DEFINE3(getrandom, char __user *
|
||||
if ((flags & (GRND_INSECURE | GRND_RANDOM)) == (GRND_INSECURE | GRND_RANDOM))
|
||||
return -EINVAL;
|
||||
|
||||
- if (!crng_ready() && !(flags & GRND_INSECURE)) {
|
||||
+ if (!crng_ready_maybe_cb() && !(flags & GRND_INSECURE)) {
|
||||
if (flags & GRND_NONBLOCK)
|
||||
return -EAGAIN;
|
||||
ret = wait_for_random_bytes();
|
||||
@@ -1412,6 +1711,10 @@ SYSCALL_DEFINE3(getrandom, char __user *
|
||||
|
||||
static __poll_t random_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
+#ifdef WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS
|
||||
+ if (crng_ready_by_cb())
|
||||
+ return EPOLLIN | EPOLLRDNORM;
|
||||
+#endif
|
||||
poll_wait(file, &crng_init_wait, wait);
|
||||
return crng_ready() ? EPOLLIN | EPOLLRDNORM : EPOLLOUT | EPOLLWRNORM;
|
||||
}
|
||||
@@ -1457,10 +1760,10 @@ static ssize_t urandom_read_iter(struct
|
||||
* Opportunistically attempt to initialize the RNG on platforms that
|
||||
* have fast cycle counters, but don't (for now) require it to succeed.
|
||||
*/
|
||||
- if (!crng_ready())
|
||||
+ if (!crng_ready_maybe_cb())
|
||||
try_to_generate_entropy();
|
||||
|
||||
- if (!crng_ready()) {
|
||||
+ if (!crng_ready_maybe_cb()) {
|
||||
if (!ratelimit_disable && maxwarn <= 0)
|
||||
ratelimit_state_inc_miss(&urandom_warning);
|
||||
else if (ratelimit_disable || __ratelimit(&urandom_warning)) {
|
||||
@@ -1477,7 +1780,7 @@ static ssize_t random_read_iter(struct k
|
||||
{
|
||||
int ret;
|
||||
|
||||
- if (!crng_ready() &&
|
||||
+ if (!crng_ready_by_cb() &&
|
||||
((kiocb->ki_flags & (IOCB_NOWAIT | IOCB_NOIO)) ||
|
||||
(kiocb->ki_filp->f_flags & O_NONBLOCK)))
|
||||
return -EAGAIN;
|
||||
@@ -1542,6 +1845,14 @@ static long random_ioctl(struct file *f,
|
||||
case RNDRESEEDCRNG:
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
+#ifdef WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS
|
||||
+ /* continue to reseed native crng too. */
|
||||
+ if (call_crng_reseed_cb() == 0) {
|
||||
+ if (crng_ready())
|
||||
+ crng_reseed(NULL);
|
||||
+ return 0;
|
||||
+ }
|
||||
+#endif
|
||||
if (!crng_ready())
|
||||
return -ENODATA;
|
||||
crng_reseed(NULL);
|
||||
--- linux-next-9999/include/linux/random.h.dist 2026-02-27 20:38:33.018159190 +0000
|
||||
+++ linux-next-9999/include/linux/random.h 2026-02-27 20:39:23.770406607 +0000
|
||||
@@ -139,4 +139,37 @@ int random_online_cpu(unsigned int cpu);
|
||||
extern const struct file_operations random_fops, urandom_fops;
|
||||
#endif
|
||||
|
||||
+#ifndef WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS
|
||||
+ #define WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS 1
|
||||
+#endif
|
||||
+
|
||||
+typedef int (*_get_random_bytes_cb_t)(void *buf, size_t len);
|
||||
+struct iov_iter;
|
||||
+/* kernels >= 5.17.0 use get_random_bytes_user() */
|
||||
+typedef ssize_t (*get_random_bytes_user_cb_t)(struct iov_iter *iter);
|
||||
+/* kernels < 5.17.0 use extract_crng_user(), though some LTS kernels,
|
||||
+ * e.g. 5.10.236, have the 5.17+ architecture backported.
|
||||
+ */
|
||||
+typedef ssize_t (*extract_crng_user_cb_t)(void __user *buf, size_t nbytes);
|
||||
+typedef bool (*crng_ready_cb_t)(void);
|
||||
+typedef int (*mix_pool_bytes_cb_t)(const void *buf, size_t len);
|
||||
+typedef int (*credit_init_bits_cb_t)(size_t bits);
|
||||
+typedef int (*crng_reseed_cb_t)(void);
|
||||
+
|
||||
+struct wolfssl_linuxkm_random_bytes_handlers {
|
||||
+ _get_random_bytes_cb_t _get_random_bytes;
|
||||
+ get_random_bytes_user_cb_t get_random_bytes_user;
|
||||
+ extract_crng_user_cb_t extract_crng_user;
|
||||
+ crng_ready_cb_t crng_ready;
|
||||
+ mix_pool_bytes_cb_t mix_pool_bytes;
|
||||
+ credit_init_bits_cb_t credit_init_bits;
|
||||
+ crng_reseed_cb_t crng_reseed;
|
||||
+};
|
||||
+
|
||||
+int wolfssl_linuxkm_register_random_bytes_handlers(
|
||||
+ struct module *new_random_bytes_cb_owner,
|
||||
+ const struct wolfssl_linuxkm_random_bytes_handlers *handlers);
|
||||
+
|
||||
+int wolfssl_linuxkm_unregister_random_bytes_handlers(void);
|
||||
+
|
||||
#endif /* _LINUX_RANDOM_H */
|
||||
Reference in New Issue
Block a user