Skip to content

Commit fe33bb9

Browse files
committed
linuxkm/lkcapi_sha_glue.c:
* in get_drbg(), call local_bh_disable() for the crypto_default_rng, and in put_drbg(), call local_bh_enable() if needed. * re-gate migrate_disable() and migrate_enable() so they're called for any SMP kernel >= 5.7, regardless of CONFIG_PREEMPT_COUNT. * in get_drbg_n(), if the caller can't sleep, return immediately if the requested DRBG is busy, to avoid priority inversions and deadlocks.
1 parent b69ce5a commit fe33bb9

File tree

1 file changed

+13
-12
lines changed

1 file changed

+13
-12
lines changed

linuxkm/lkcapi_sha_glue.c

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,17 +1073,17 @@ static inline struct wc_rng_inst *get_drbg(struct crypto_rng *tfm) {
10731073
return NULL;
10741074
}
10751075

1076-
#if defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_COUNT) && \
1077-
(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
10781076
if (tfm == crypto_default_rng) {
1077+
#if defined(CONFIG_SMP) && (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
10791078
migrate_disable(); /* this actually makes irq_count() nonzero, so that
10801079
* DISABLE_VECTOR_REGISTERS() is superfluous, but
10811080
* don't depend on that.
10821081
*/
1082+
#endif
1083+
local_bh_disable();
10831084
new_lock_value = 2;
10841085
}
10851086
else
1086-
#endif
10871087
{
10881088
new_lock_value = 1;
10891089
}
@@ -1104,7 +1104,9 @@ static inline struct wc_rng_inst *get_drbg(struct crypto_rng *tfm) {
11041104
}
11051105

11061106
/* get_drbg_n() is used by bulk seed, mix-in, and reseed operations. It expects
1107-
* the caller to be able to wait until the requested DRBG is available.
1107+
* the caller to be able to wait until the requested DRBG is available. If the
1108+
* caller can't sleep and the requested DRBG is busy, it returns immediately --
1109+
* this avoids priority inversions and deadlocks.
11081110
*/
11091111
static inline struct wc_rng_inst *get_drbg_n(struct wc_linuxkm_drbg_ctx *ctx, int n) {
11101112
int can_sleep = (preempt_count() == 0);
@@ -1119,23 +1121,22 @@ static inline struct wc_rng_inst *get_drbg_n(struct wc_linuxkm_drbg_ctx *ctx, in
11191121
cond_resched();
11201122
}
11211123
else
1122-
cpu_relax();
1124+
return NULL;
11231125
}
11241126

11251127
__builtin_unreachable();
11261128
}
11271129

11281130
static inline void put_drbg(struct wc_rng_inst *drbg) {
1129-
#if defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_COUNT) && \
1130-
(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
11311131
int migration_disabled = (drbg->lock == 2);
1132-
#endif
11331132
__atomic_store_n(&(drbg->lock),0,__ATOMIC_RELEASE);
1134-
#if defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_COUNT) && \
1135-
(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
1136-
if (migration_disabled)
1133+
1134+
if (migration_disabled) {
1135+
local_bh_enable();
1136+
#if defined(CONFIG_SMP) && (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
11371137
migrate_enable();
1138-
#endif
1138+
#endif
1139+
}
11391140
}
11401141

11411142
static int wc_linuxkm_drbg_generate(struct crypto_rng *tfm,

0 commit comments

Comments
 (0)