linuxkm/linuxkm_wc_port.h:

* add WOLFSSL_API attribute to wc_linuxkm_sig_ignore_begin(), wc_linuxkm_sig_ignore_end(), wc_linuxkm_check_for_intr_signals(), and wc_linuxkm_relax_long_loop().
* fix WC_CONTAINERIZE_THIS macro wrappers for wc_linuxkm_sig_ignore_begin() and wc_linuxkm_sig_ignore_end() (stray semicolons).

linuxkm/linuxkm_wc_port.h, linuxkm/lkcapi_sha_glue.c, linuxkm/module_hooks.c: add wc_linuxkm_can_block(), and refactor ad hoc `preempt_count() != 0` checks for sleep safety as calls to wc_linuxkm_can_block().

linuxkm/module_hooks.c: fix wc_linuxkm_malloc_usable_size() implementation for kvmalloc() compatibility.
This commit is contained in:
Daniel Pouzzner
2026-06-03 18:18:31 -05:00
parent 70da83972b
commit 396e83a48b
3 changed files with 66 additions and 21 deletions
+14 -11
View File
@@ -167,13 +167,14 @@
#ifndef WC_LINUXKM_INTR_SIGNALS
#define WC_LINUXKM_INTR_SIGNALS { SIGKILL, SIGABRT, SIGHUP, SIGINT }
#endif
extern int wc_linuxkm_sig_ignore_begin(void);
extern int wc_linuxkm_sig_ignore_end(void);
extern int wc_linuxkm_check_for_intr_signals(void);
WOLFSSL_API int wc_linuxkm_can_block(void);
WOLFSSL_API int wc_linuxkm_sig_ignore_begin(void);
WOLFSSL_API int wc_linuxkm_sig_ignore_end(void);
WOLFSSL_API int wc_linuxkm_check_for_intr_signals(void);
#ifndef WC_LINUXKM_MAX_NS_WITHOUT_YIELD
#define WC_LINUXKM_MAX_NS_WITHOUT_YIELD 1000000000
#endif
extern void wc_linuxkm_relax_long_loop(void);
WOLFSSL_API void wc_linuxkm_relax_long_loop(void);
#ifndef WC_SIG_IGNORE_BEGIN
#define WC_SIG_IGNORE_BEGIN() wc_linuxkm_sig_ignore_begin()
@@ -1221,6 +1222,7 @@
typeof(wc_lkm_LockMutex) *wc_lkm_LockMutex;
#endif
typeof(wc_linuxkm_can_block) *wc_linuxkm_can_block;
typeof(wc_linuxkm_sig_ignore_begin) *wc_linuxkm_sig_ignore_begin;
typeof(wc_linuxkm_sig_ignore_end) *wc_linuxkm_sig_ignore_end;
typeof(wc_linuxkm_check_for_intr_signals) *wc_linuxkm_check_for_intr_signals;
@@ -1521,8 +1523,9 @@
wolfssl_spin_unlock_irqrestore_rt((lock), (flags))
#endif
#define wc_linuxkm_sig_ignore_begin WC_PIE_INDIRECT_SYM(wc_linuxkm_sig_ignore_begin);
#define wc_linuxkm_sig_ignore_end WC_PIE_INDIRECT_SYM(wc_linuxkm_sig_ignore_end);
#define wc_linuxkm_can_block WC_PIE_INDIRECT_SYM(wc_linuxkm_can_block)
#define wc_linuxkm_sig_ignore_begin WC_PIE_INDIRECT_SYM(wc_linuxkm_sig_ignore_begin)
#define wc_linuxkm_sig_ignore_end WC_PIE_INDIRECT_SYM(wc_linuxkm_sig_ignore_end)
#define wc_linuxkm_check_for_intr_signals WC_PIE_INDIRECT_SYM(wc_linuxkm_check_for_intr_signals)
#define wc_linuxkm_relax_long_loop WC_PIE_INDIRECT_SYM(wc_linuxkm_relax_long_loop)
@@ -1905,21 +1908,21 @@
#endif
#else /* !WC_LINUXKM_USE_HEAP_WRAPPERS */
#ifdef USE_KVMALLOC
#define malloc(size) kvmalloc_node(WC_LINUXKM_ROUND_UP_P_OF_2(size), (preempt_count() == 0 ? GFP_KERNEL : GFP_ATOMIC), NUMA_NO_NODE)
#define malloc(size) kvmalloc_node(WC_LINUXKM_ROUND_UP_P_OF_2(size), (wc_linuxkm_can_block() ? GFP_KERNEL : GFP_ATOMIC), NUMA_NO_NODE)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 2, 0)
#define free(ptr) (preempt_count() == 0 ? kvfree(ptr) : kvfree_atomic(ptr))
#define free(ptr) (wc_linuxkm_can_block() ? kvfree(ptr) : kvfree_atomic(ptr))
#else
#define free(ptr) kvfree(ptr)
#endif
#ifdef USE_KVREALLOC
#define realloc(ptr, newsize) kvrealloc(ptr, WC_LINUXKM_ROUND_UP_P_OF_2(newsize), (preempt_count() == 0 ? GFP_KERNEL : GFP_ATOMIC))
#define realloc(ptr, newsize) kvrealloc(ptr, WC_LINUXKM_ROUND_UP_P_OF_2(newsize), (wc_linuxkm_can_block() ? GFP_KERNEL : GFP_ATOMIC))
#else
#define realloc(ptr, newsize) ((void)(ptr), (void)(newsize), NULL)
#endif
#else
#define malloc(size) kmalloc(WC_LINUXKM_ROUND_UP_P_OF_2(size), (preempt_count() == 0 ? GFP_KERNEL : GFP_ATOMIC))
#define malloc(size) kmalloc(WC_LINUXKM_ROUND_UP_P_OF_2(size), (wc_linuxkm_can_block() ? GFP_KERNEL : GFP_ATOMIC))
#define free(ptr) kfree(ptr)
#define realloc(ptr, newsize) krealloc(ptr, WC_LINUXKM_ROUND_UP_P_OF_2(newsize), (preempt_count() == 0 ? GFP_KERNEL : GFP_ATOMIC))
#define realloc(ptr, newsize) krealloc(ptr, WC_LINUXKM_ROUND_UP_P_OF_2(newsize), (wc_linuxkm_can_block() ? GFP_KERNEL : GFP_ATOMIC))
#endif
#endif /* !WC_LINUXKM_USE_HEAP_WRAPPERS */
+4 -4
View File
@@ -1009,7 +1009,7 @@ static volatile int wc_linuxkm_rng_initing_default_bank_flag = 0;
static int linuxkm_affinity_lock(void *arg) {
(void)arg;
if (preempt_count() != 0)
if (! wc_linuxkm_can_block())
return ALREADY_E;
#if defined(CONFIG_SMP) && (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
migrate_disable(); /* this actually makes irq_count() nonzero, so that
@@ -1118,7 +1118,7 @@ static struct wc_rng_bank_inst *linuxkm_get_drbg(struct wc_rng_bank *ctx) {
WC_RNG_BANK_FLAG_CAN_WAIT |
WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST;
if (preempt_count() == 0)
if (wc_linuxkm_can_block())
flags |= WC_RNG_BANK_FLAG_AFFINITY_LOCK;
else
flags |= WC_RNG_BANK_FLAG_NO_VECTOR_OPS;
@@ -1487,7 +1487,7 @@ static int wc_mix_pool_bytes(const void *buf, size_t len) {
struct wc_rng_bank *ctx;
size_t i;
int n;
int can_sleep = (preempt_count() == 0);
int can_sleep = wc_linuxkm_can_block();
if (len == 0)
return 0;
@@ -1545,7 +1545,7 @@ static int wc_mix_pool_bytes(const void *buf, size_t len) {
static int wc_crng_reseed(void) {
struct wc_rng_bank *ctx;
int can_sleep = (preempt_count() == 0);
int can_sleep = wc_linuxkm_can_block();
int ret = wc_rng_bank_default_checkout(&ctx);
if (ret) {
+48 -6
View File
@@ -316,6 +316,13 @@ MODULE_PARM_DESC(rodata_dump_path,
#include "linuxkm/lkcapi_glue.c"
#endif
int wc_linuxkm_can_block(void) {
/* We can't use preemptible() for this, because we need an accurate test
* even in !CONFIG_PREEMPT_COUNT configs where preemptible() is always 0.
*/
return (preempt_count() == 0) && (! irqs_disabled());
}
/* for simplicity, we use a global count to suspend signal processing while any
* thread is running fipsEntry(), wolfCrypt_IntegrityTest_fips(),
* linuxkm_lkcapi_register(), or linuxkm_lkcapi_unregister(). This only affects
@@ -336,7 +343,7 @@ int wc_linuxkm_sig_ignore_end(void) {
int wc_linuxkm_check_for_intr_signals(void) {
static const int intr_signals[] = WC_LINUXKM_INTR_SIGNALS;
if (preempt_count() != 0)
if (! wc_linuxkm_can_block())
return 0;
if (signal_pending(current)) {
int i;
@@ -365,7 +372,7 @@ int wc_linuxkm_check_for_intr_signals(void) {
void wc_linuxkm_relax_long_loop(void) {
#if WC_LINUXKM_MAX_NS_WITHOUT_YIELD >= 0
if (preempt_count() == 0) {
if (wc_linuxkm_can_block()) {
#if (WC_LINUXKM_MAX_NS_WITHOUT_YIELD == 0) || !defined(CONFIG_SCHED_INFO)
cond_resched();
#else
@@ -662,6 +669,11 @@ static int wolfssl_init(void)
}
#endif
#if defined(WC_LINUXKM_USE_HEAP_WRAPPERS) && defined(CONFIG_HAVE_KPROBES)
/* cache the function pointer to find_vm_area(). */
(void)wc_linuxkm_malloc_usable_size(NULL);
#endif
#ifdef WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE
#ifdef CONFIG_MODULE_SIG
if (THIS_MODULE->sig_ok == false) {
@@ -1283,13 +1295,13 @@ static const struct wc_reloc_table_segments seg_map = {
void *wc_linuxkm_malloc(size_t size)
{
return kvmalloc_node(WC_LINUXKM_ROUND_UP_P_OF_2(size), (preempt_count() == 0 ? GFP_KERNEL : GFP_ATOMIC), NUMA_NO_NODE);
return kvmalloc_node(WC_LINUXKM_ROUND_UP_P_OF_2(size), (wc_linuxkm_can_block() ? GFP_KERNEL : GFP_ATOMIC), NUMA_NO_NODE);
}
void wc_linuxkm_free(void *ptr)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 2, 0)
if (preempt_count() == 0)
if (wc_linuxkm_can_block())
kvfree(ptr);
else
kvfree_atomic(ptr);
@@ -1300,12 +1312,41 @@ void wc_linuxkm_free(void *ptr)
void *wc_linuxkm_realloc(void *ptr, size_t newsize)
{
return kvrealloc(ptr, WC_LINUXKM_ROUND_UP_P_OF_2(newsize), (preempt_count() == 0 ? GFP_KERNEL : GFP_ATOMIC));
return kvrealloc(ptr, WC_LINUXKM_ROUND_UP_P_OF_2(newsize), (wc_linuxkm_can_block() ? GFP_KERNEL : GFP_ATOMIC));
}
#ifdef CONFIG_HAVE_KPROBES
#include <linux/vmalloc.h>
#endif
size_t wc_linuxkm_malloc_usable_size(void *ptr)
{
return ksize(ptr);
if ((ptr == NULL) || is_vmalloc_addr(ptr)) {
#ifdef CONFIG_HAVE_KPROBES
static typeof(find_vm_area) *find_vm_area_ptr = NULL;
if (find_vm_area_ptr == NULL) {
if (! wc_linuxkm_can_block())
return 0;
find_vm_area_ptr = my_kallsyms_lookup_name("find_vm_area");
}
if (find_vm_area_ptr == NULL)
return 0;
else if (ptr == NULL)
return 0;
else {
struct vm_struct *vm = find_vm_area_ptr(ptr);
if (vm)
return get_vm_area_size(vm);
else
return 0;
}
#else
return 0;
#endif
}
else {
return ksize(ptr);
}
}
#endif /* WC_LINUXKM_USE_HEAP_WRAPPERS */
@@ -1678,6 +1719,7 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) {
#endif
#endif
wolfssl_linuxkm_pie_redirect_table.wc_linuxkm_can_block = wc_linuxkm_can_block;
wolfssl_linuxkm_pie_redirect_table.wc_linuxkm_sig_ignore_begin = wc_linuxkm_sig_ignore_begin;
wolfssl_linuxkm_pie_redirect_table.wc_linuxkm_sig_ignore_end = wc_linuxkm_sig_ignore_end;
wolfssl_linuxkm_pie_redirect_table.wc_linuxkm_check_for_intr_signals = wc_linuxkm_check_for_intr_signals;