@@ -1083,8 +1083,11 @@ static inline struct wc_rng_inst *get_drbg_n(struct wc_linuxkm_drbg_ctx *ctx, in
10831083 int expected = 0 ;
10841084 if (likely (__atomic_compare_exchange_n (& ctx -> rngs [n ].lock , & expected , 1 , 0 , __ATOMIC_SEQ_CST , __ATOMIC_ACQUIRE )))
10851085 return & ctx -> rngs [n ];
1086- if (can_sleep )
1086+ if (can_sleep ) {
1087+ if (signal_pending (current ))
1088+ return NULL ;
10871089 cond_resched ();
1090+ }
10881091 else
10891092 cpu_relax ();
10901093 }
@@ -1192,6 +1195,11 @@ static int wc_linuxkm_drbg_seed(struct crypto_rng *tfm,
11921195 for (n = ctx -> n_rngs - 1 ; n >= 0 ; -- n ) {
11931196 struct wc_rng_inst * drbg = get_drbg_n (ctx , n );
11941197
1198+ if (! drbg ) {
1199+ ret = - EINTR ;
1200+ break ;
1201+ }
1202+
11951203 /* perturb the seed with the CPU ID, so that no DRBG has the exact same
11961204 * seed.
11971205 */
@@ -1425,6 +1433,7 @@ static int wc_mix_pool_bytes(const void *buf, size_t len) {
14251433 struct wc_linuxkm_drbg_ctx * ctx ;
14261434 size_t i ;
14271435 int n ;
1436+ int can_sleep = (preempt_count () == 0 );
14281437
14291438 if (len == 0 )
14301439 return 0 ;
@@ -1434,15 +1443,23 @@ static int wc_mix_pool_bytes(const void *buf, size_t len) {
14341443
14351444 for (n = ctx -> n_rngs - 1 ; n >= 0 ; -- n ) {
14361445 struct wc_rng_inst * drbg = get_drbg_n (ctx , n );
1437- int V_offset = 0 ;
1446+ int V_offset ;
14381447
1439- for (i = 0 ; i < len ; ++ i ) {
1448+ if (! drbg )
1449+ return - EINTR ;
1450+
1451+ for (i = 0 , V_offset = 0 ; i < len ; ++ i ) {
14401452 ((struct DRBG_internal * )drbg -> rng .drbg )-> V [V_offset ++ ] += ((byte * )buf )[i ];
14411453 if (V_offset == (int )sizeof ((struct DRBG_internal * )drbg -> rng .drbg )-> V )
14421454 V_offset = 0 ;
14431455 }
14441456
14451457 put_drbg (drbg );
1458+ if (can_sleep ) {
1459+ if (signal_pending (current ))
1460+ return - EINTR ;
1461+ cond_resched ();
1462+ }
14461463 }
14471464
14481465 return 0 ;
@@ -1458,7 +1475,12 @@ static int wc_crng_reseed(void) {
14581475
14591476 for (n = ctx -> n_rngs - 1 ; n >= 0 ; -- n ) {
14601477 struct wc_rng_inst * drbg = get_drbg_n (ctx , n );
1478+
1479+ if (! drbg )
1480+ return - EINTR ;
1481+
14611482 ((struct DRBG_internal * )drbg -> rng .drbg )-> reseedCtr = WC_RESEED_INTERVAL ;
1483+
14621484 if (can_sleep ) {
14631485 byte scratch [4 ];
14641486 int need_reenable_vec = (DISABLE_VECTOR_REGISTERS () == 0 );
@@ -1468,8 +1490,13 @@ static int wc_crng_reseed(void) {
14681490 if (ret != 0 )
14691491 pr_err ("ERROR: wc_crng_reseed() wc_RNG_GenerateBlock() for DRBG #%d returned %d." , n , ret );
14701492 put_drbg (drbg );
1493+ if (signal_pending (current ))
1494+ return - EINTR ;
14711495 cond_resched ();
14721496 }
1497+ else {
1498+ put_drbg (drbg );
1499+ }
14731500 }
14741501
14751502 return 0 ;
0 commit comments