Skip to content

Commit 7df8ee4

Browse files
committed
linuxkm/linuxkm_wc_port.h: add default setup for LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT, to make visibility in random.c;
linuxkm/lkcapi_sha_glue.c: revert f7c7ac2 (get_drbg() DISABLE_VECTOR_REGISTERS() for crypto_default_rng) -- compiler/inlining bug makes it break on at least one target, so caller needs to retain responsibility; linuxkm/x86_vector_register_glue.c: in wc_save_vector_registers_x86(), always return WC_ACCEL_INHIBIT_E if already fpu_state & WC_FPU_INHIBITED_FLAG, for safe+correct dynamics on recursive calls.
1 parent 7ef9428 commit 7df8ee4

3 files changed

Lines changed: 31 additions & 33 deletions

File tree

linuxkm/linuxkm_wc_port.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,17 @@
422422
#define WC_AES_XTS_SUPPORT_SIMULTANEOUS_ENC_AND_DEC_KEYS
423423
#endif
424424

425+
/* setup for LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT needs to be here
426+
* to assure that calls to get_random_bytes() in random.c are gated out
427+
* (they would recurse, potentially infinitely).
428+
*/
429+
#if (defined(LINUXKM_LKCAPI_REGISTER_ALL) && \
430+
!defined(LINUXKM_LKCAPI_DONT_REGISTER_HASH_DRBG) && \
431+
!defined(LINUXKM_LKCAPI_DONT_REGISTER_HASH_DRBG_DEFAULT)) && \
432+
!defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT)
433+
#define LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
434+
#endif
435+
425436
#ifndef __PIE__
426437
#include <linux/crypto.h>
427438
#include <linux/scatterlist.h>

linuxkm/lkcapi_sha_glue.c

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -374,10 +374,7 @@
374374
!defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG)
375375
#define LINUXKM_LKCAPI_REGISTER_HASH_DRBG
376376
#endif
377-
#if (defined(LINUXKM_LKCAPI_REGISTER_ALL) && !defined(LINUXKM_LKCAPI_DONT_REGISTER_HASH_DRBG_DEFAULT)) && \
378-
!defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT)
379-
#define LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
380-
#endif
377+
/* setup for LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT is in linuxkm_wc_port.h */
381378
#else
382379
#undef LINUXKM_LKCAPI_REGISTER_HASH_DRBG
383380
#endif
@@ -968,7 +965,6 @@ struct wc_linuxkm_drbg_ctx {
968965
struct wc_rng_inst {
969966
wolfSSL_Atomic_Int lock;
970967
WC_RNG rng;
971-
int disabled_vec_ops;
972968
} *rngs; /* one per CPU ID */
973969
};
974970

@@ -1090,14 +1086,8 @@ static inline struct wc_rng_inst *get_drbg(struct crypto_rng *tfm) {
10901086

10911087
for (;;) {
10921088
int expected = 0;
1093-
if (likely(__atomic_compare_exchange_n(&ctx->rngs[n].lock, &expected, new_lock_value, 0, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE))) {
1094-
struct wc_rng_inst *drbg = &ctx->rngs[n];
1095-
if (tfm == crypto_default_rng)
1096-
drbg->disabled_vec_ops = (DISABLE_VECTOR_REGISTERS() == 0);
1097-
else
1098-
drbg->disabled_vec_ops = 0;
1099-
return drbg;
1100-
}
1089+
if (likely(__atomic_compare_exchange_n(&ctx->rngs[n].lock, &expected, new_lock_value, 0, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE)))
1090+
return &ctx->rngs[n];
11011091
++n;
11021092
if (n >= (int)ctx->n_rngs)
11031093
n = 0;
@@ -1115,11 +1105,8 @@ static inline struct wc_rng_inst *get_drbg_n(struct wc_linuxkm_drbg_ctx *ctx, in
11151105

11161106
for (;;) {
11171107
int expected = 0;
1118-
if (likely(__atomic_compare_exchange_n(&ctx->rngs[n].lock, &expected, 1, 0, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE))) {
1119-
struct wc_rng_inst *drbg = &ctx->rngs[n];
1120-
drbg->disabled_vec_ops = 0;
1121-
return drbg;
1122-
}
1108+
if (likely(__atomic_compare_exchange_n(&ctx->rngs[n].lock, &expected, 1, 0, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE)))
1109+
return &ctx->rngs[n];
11231110
if (can_sleep) {
11241111
if (signal_pending(current))
11251112
return NULL;
@@ -1137,10 +1124,6 @@ static inline void put_drbg(struct wc_rng_inst *drbg) {
11371124
(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
11381125
int migration_disabled = (drbg->lock == 2);
11391126
#endif
1140-
if (drbg->disabled_vec_ops) {
1141-
REENABLE_VECTOR_REGISTERS();
1142-
drbg->disabled_vec_ops = 0;
1143-
}
11441127
__atomic_store_n(&(drbg->lock),0,__ATOMIC_RELEASE);
11451128
#if defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_COUNT) && \
11461129
(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
@@ -1154,13 +1137,19 @@ static int wc_linuxkm_drbg_generate(struct crypto_rng *tfm,
11541137
u8 *dst, unsigned int dlen)
11551138
{
11561139
int ret, retried = 0;
1140+
int need_fpu_restore;
11571141
struct wc_rng_inst *drbg = get_drbg(tfm);
11581142

11591143
if (! drbg) {
11601144
pr_err_once("BUG: get_drbg() failed.");
11611145
return -EFAULT;
11621146
}
11631147

1148+
/* for the default RNG, make sure we don't cache an underlying SHA256
1149+
* method that uses vector insns (forbidden from irq handlers).
1150+
*/
1151+
need_fpu_restore = (tfm == crypto_default_rng) ? (DISABLE_VECTOR_REGISTERS() == 0) : 0;
1152+
11641153
retry:
11651154

11661155
if (slen > 0) {
@@ -1194,6 +1183,8 @@ static int wc_linuxkm_drbg_generate(struct crypto_rng *tfm,
11941183

11951184
out:
11961185

1186+
if (need_fpu_restore)
1187+
REENABLE_VECTOR_REGISTERS();
11971188
put_drbg(drbg);
11981189

11991190
return ret;

linuxkm/x86_vector_register_glue.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -346,24 +346,20 @@ WARN_UNUSED_RESULT int wc_save_vector_registers_x86(enum wc_svr_flags flags)
346346

347347
/* allow for nested calls */
348348
if (pstate && (pstate->fpu_state != 0U)) {
349+
if (pstate->fpu_state & WC_FPU_INHIBITED_FLAG) {
350+
/* don't allow recursive inhibit calls when already inhibited --
351+
* it would add no functionality and require keeping a separate
352+
* count of inhibit recursions.
353+
*/
354+
return WC_ACCEL_INHIBIT_E;
355+
}
349356
if (unlikely((pstate->fpu_state & WC_FPU_COUNT_MASK)
350357
== WC_FPU_COUNT_MASK))
351358
{
352359
pr_err("ERROR: wc_save_vector_registers_x86 recursion register overflow for "
353360
"pid %d on CPU %d.\n", pstate->pid, raw_smp_processor_id());
354361
return BAD_STATE_E;
355362
}
356-
if (pstate->fpu_state & WC_FPU_INHIBITED_FLAG) {
357-
if (flags & WC_SVR_FLAG_INHIBIT) {
358-
/* allow recursive inhibit calls as long as the whole stack of
359-
* them is inhibiting.
360-
*/
361-
++pstate->fpu_state;
362-
return 0;
363-
}
364-
else
365-
return WC_ACCEL_INHIBIT_E;
366-
}
367363
if (flags & WC_SVR_FLAG_INHIBIT) {
368364
++pstate->fpu_state;
369365
pstate->fpu_state |= WC_FPU_INHIBITED_FLAG;

0 commit comments

Comments
 (0)