Skip to content

Commit dd69d56

Browse files
committed
linuxkm/linuxkm_wc_port.h: in malloc/realloc, use GFP_KERNEL if it's safe to sleep;
linuxkm/lkcapi_sha_glue.c: * in wc_linuxkm_drbg_init_tfm(), sleep if it's safe, and observe a wc_linuxkm_drbg_init_tfm_disable_vector_registers flag; * in wc_crng_reseed(), preemptively execute the reseed if it's safe to sleep; * in wc_linuxkm_drbg_startup(), in LINUXKM_DRBG_GET_RANDOM_BYTES section, add reseed test sequence if defined(DEBUG_DRBG_RESEEDS).
1 parent 0160af0 commit dd69d56

2 files changed

Lines changed: 65 additions & 26 deletions

File tree

linuxkm/linuxkm_wc_port.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,14 +1085,14 @@
10851085
_alloc_sz; \
10861086
})
10871087
#ifdef HAVE_KVMALLOC
1088-
#define malloc(size) kvmalloc_node(WC_LINUXKM_ROUND_UP_P_OF_2(size), GFP_ATOMIC, NUMA_NO_NODE)
1088+
#define malloc(size) kvmalloc_node(WC_LINUXKM_ROUND_UP_P_OF_2(size), (preempt_count() == 0 ? GFP_KERNEL : GFP_ATOMIC), NUMA_NO_NODE)
10891089
#define free(ptr) kvfree(ptr)
10901090
void *lkm_realloc(void *ptr, size_t newsize);
10911091
#define realloc(ptr, newsize) lkm_realloc(ptr, WC_LINUXKM_ROUND_UP_P_OF_2(newsize))
10921092
#else
1093-
#define malloc(size) kmalloc(WC_LINUXKM_ROUND_UP_P_OF_2(size), GFP_ATOMIC)
1093+
#define malloc(size) kmalloc(WC_LINUXKM_ROUND_UP_P_OF_2(size), (preempt_count() == 0 ? GFP_KERNEL : GFP_ATOMIC))
10941094
#define free(ptr) kfree(ptr)
1095-
#define realloc(ptr, newsize) krealloc(ptr, WC_LINUXKM_ROUND_UP_P_OF_2(newsize), GFP_ATOMIC)
1095+
#define realloc(ptr, newsize) krealloc(ptr, WC_LINUXKM_ROUND_UP_P_OF_2(newsize), (preempt_count() == 0 ? GFP_KERNEL : GFP_ATOMIC))
10961096
#endif
10971097

10981098
#ifndef static_assert

linuxkm/lkcapi_sha_glue.c

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -966,11 +966,15 @@ static inline void wc_linuxkm_drbg_ctx_clear(struct wc_linuxkm_drbg_ctx * ctx)
966966
return;
967967
}
968968

969+
static volatile int wc_linuxkm_drbg_init_tfm_disable_vector_registers = 0;
970+
969971
static int wc_linuxkm_drbg_init_tfm(struct crypto_tfm *tfm)
970972
{
971973
struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_tfm_ctx(tfm);
972974
unsigned int i;
973975
int ret;
976+
int need_reenable_vec = 0;
977+
int can_sleep = (preempt_count() == 0);
974978

975979
ctx->rngs = (struct wc_rng_inst *)malloc(sizeof(*ctx->rngs) * nr_cpu_ids);
976980
if (! ctx->rngs)
@@ -979,12 +983,18 @@ static int wc_linuxkm_drbg_init_tfm(struct crypto_tfm *tfm)
979983

980984
for (i = 0; i < nr_cpu_ids; ++i) {
981985
ctx->rngs[i].lock = 0;
986+
if (wc_linuxkm_drbg_init_tfm_disable_vector_registers)
987+
need_reenable_vec = (DISABLE_VECTOR_REGISTERS() == 0);
982988
ret = wc_InitRng(&ctx->rngs[i].rng);
989+
if (need_reenable_vec)
990+
REENABLE_VECTOR_REGISTERS();
983991
if (ret != 0) {
984992
pr_warn_once("WARNING: wc_InitRng returned %d\n",ret);
985993
ret = -EINVAL;
986994
break;
987995
}
996+
if (can_sleep)
997+
cond_resched();
988998
}
989999

9901000
if (ret != 0) {
@@ -1349,7 +1359,7 @@ static ssize_t wc_extract_crng_user(void __user *buf, size_t nbytes) {
13491359

13501360
ForceZero(block, sizeof(block));
13511361

1352-
if (total_copied == 0) {
1362+
if ((total_copied == 0) && (ret == 0)) {
13531363
ret = -ECANCELED;
13541364
}
13551365

@@ -1391,18 +1401,25 @@ static int wc_mix_pool_bytes(const void *buf, size_t len) {
13911401
static int wc_crng_reseed(void) {
13921402
struct wc_linuxkm_drbg_ctx *ctx = get_default_drbg_ctx();
13931403
int n;
1404+
int can_sleep = (preempt_count() == 0);
13941405

13951406
if (! ctx)
13961407
return -EFAULT;
13971408

13981409
for (n = nr_cpu_ids - 1; n >= 0; --n) {
13991410
struct wc_rng_inst *drbg = get_drbg_n(ctx, n);
14001411
((struct DRBG_internal *)drbg->rng.drbg)->reseedCtr = WC_RESEED_INTERVAL;
1401-
/* don't actually reseed now -- running the memory entropy generator for
1402-
* all of the DRBGs can take so long that it triggers "rcu: INFO:
1403-
* rcu_sched self-detected stall on CPU".
1404-
*/
1405-
put_drbg(drbg);
1412+
if (can_sleep) {
1413+
byte scratch[4];
1414+
int need_reenable_vec = (DISABLE_VECTOR_REGISTERS() == 0);
1415+
int ret = wc_RNG_GenerateBlock(&drbg->rng, scratch, (word32)sizeof(scratch));
1416+
if (need_reenable_vec)
1417+
REENABLE_VECTOR_REGISTERS();
1418+
if (ret != 0)
1419+
pr_err("ERROR: wc_crng_reseed() wc_RNG_GenerateBlock() for DRBG #%d returned %d.", n, ret);
1420+
put_drbg(drbg);
1421+
cond_resched();
1422+
}
14061423
}
14071424

14081425
return 0;
@@ -1712,22 +1729,19 @@ static int wc_linuxkm_drbg_startup(void)
17121729
WOLFKM_INSTALL_NOTICE(wc_linuxkm_drbg);
17131730

17141731
#ifdef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
1732+
/* for the default RNG, make sure we don't cache an underlying SHA256
1733+
* method that uses vector insns (forbidden from irq handlers).
1734+
*/
1735+
wc_linuxkm_drbg_init_tfm_disable_vector_registers = 1;
17151736
ret = crypto_del_default_rng();
17161737
if (ret) {
1738+
wc_linuxkm_drbg_init_tfm_disable_vector_registers = 0;
17171739
pr_err("ERROR: crypto_del_default_rng returned %d", ret);
17181740
return ret;
17191741
}
1720-
1721-
/* for the default RNG, make sure we don't cache an underlying SHA256
1722-
* method that uses vector insns (forbidden from irq handlers).
1723-
*/
1724-
ret = DISABLE_VECTOR_REGISTERS();
1725-
if (ret != 0) {
1726-
pr_err("ERROR: DISABLE_VECTOR_REGISTERS() returned %d", ret);
1727-
return -EINVAL;
1728-
}
17291742
ret = crypto_get_default_rng();
1730-
REENABLE_VECTOR_REGISTERS();
1743+
1744+
wc_linuxkm_drbg_init_tfm_disable_vector_registers = 0;
17311745

17321746
if (ret) {
17331747
pr_err("ERROR: crypto_get_default_rng returned %d", ret);
@@ -1747,18 +1761,17 @@ static int wc_linuxkm_drbg_startup(void)
17471761
return -EINVAL;
17481762
}
17491763

1750-
if (strcmp(crypto_tfm_alg_driver_name(&crypto_default_rng->base), wc_linuxkm_drbg.base.cra_driver_name) == 0) {
1751-
crypto_put_default_rng();
1752-
wc_linuxkm_drbg_default_instance_registered = 1;
1753-
pr_info("%s registered as systemwide default stdrng.", wc_linuxkm_drbg.base.cra_driver_name);
1754-
pr_info("libwolfssl: to unload module, first echo 1 > /sys/module/libwolfssl/deinstall_algs");
1755-
}
1756-
else {
1764+
if (crypto_default_rng->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm) {
17571765
pr_err("ERROR: %s NOT registered as systemwide default stdrng -- found \"%s\".", wc_linuxkm_drbg.base.cra_driver_name, crypto_tfm_alg_driver_name(&crypto_default_rng->base));
17581766
crypto_put_default_rng();
17591767
return -EINVAL;
17601768
}
17611769

1770+
crypto_put_default_rng();
1771+
wc_linuxkm_drbg_default_instance_registered = 1;
1772+
pr_info("%s registered as systemwide default stdrng.", wc_linuxkm_drbg.base.cra_driver_name);
1773+
pr_info("libwolfssl: to unload module, first echo 1 > /sys/module/libwolfssl/deinstall_algs");
1774+
17621775
#ifdef LINUXKM_DRBG_GET_RANDOM_BYTES
17631776

17641777
#ifdef WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS
@@ -1801,6 +1814,32 @@ static int wc_linuxkm_drbg_startup(void)
18011814
#error LINUXKM_DRBG_GET_RANDOM_BYTES missing installation calls.
18021815
#endif
18031816

1817+
#ifdef DEBUG_DRBG_RESEEDS
1818+
{
1819+
byte scratch[4];
1820+
ret = wc__get_random_bytes(scratch, sizeof(scratch));
1821+
if (ret != 0) {
1822+
pr_err("ERROR: wc__get_random_bytes() returned %d", ret);
1823+
return -EINVAL;
1824+
}
1825+
ret = wc_mix_pool_bytes(scratch, sizeof(scratch));
1826+
if (ret != 0) {
1827+
pr_err("ERROR: wc_mix_pool_bytes() returned %d", ret);
1828+
return -EINVAL;
1829+
}
1830+
ret = wc_crng_reseed();
1831+
if (ret != 0) {
1832+
pr_err("ERROR: wc_crng_reseed() returned %d", ret);
1833+
return -EINVAL;
1834+
}
1835+
ret = wc__get_random_bytes(scratch, sizeof(scratch));
1836+
if (ret != 0) {
1837+
pr_err("ERROR: wc__get_random_bytes() returned %d", ret);
1838+
return -EINVAL;
1839+
}
1840+
}
1841+
#endif
1842+
18041843
#endif /* LINUXKM_DRBG_GET_RANDOM_BYTES */
18051844

18061845
#endif /* LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT */

0 commit comments

Comments
 (0)