Module Name: src Committed By: knakahara Date: Fri Apr 7 12:15:51 UTC 2017
Modified Files: src/sys/opencrypto: cryptodev.c cryptodev.h Log Message: fix race among crypto_done(), cryptoret(), and {cryptodev_op(), cryptodev_key()}. crypto_op() waited to be set CRYPTO_F_DONE with crp->crp_cv. However, there is context switch chances between being set CRYPTO_F_DONE in crypto_done() and done cv_signal(crp->crp_cv) in cryptodev_cb(), that is, cryptodev_op() thread can run to cv_destroy(crp->crp_cv) before cryptoret() thread is waken up. As a result, cryptodev_cb() can call invalid(destroyed) cv_signal(crp->crp_cv). Furthermore, below two implementations cause other races. - waiting CRYPTO_F_DONE with crp->crp_cv - context witch chances between set CRYPTO_F_DONE and cv_signal(crp->crp_cv) So, use other flag(CRYPTO_F_DQRETQ) for cryptodev_op() and cryptodev_key(), and then call cv_signal(crp->crp_cv) immediately after set CRYPTO_F_DQRETQ. Tested concurrent over 20 processes with software and hardware drivers. To generate a diff of this commit: cvs rdiff -u -r1.86 -r1.87 src/sys/opencrypto/cryptodev.c cvs rdiff -u -r1.29 -r1.30 src/sys/opencrypto/cryptodev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/opencrypto/cryptodev.c diff -u src/sys/opencrypto/cryptodev.c:1.86 src/sys/opencrypto/cryptodev.c:1.87 --- src/sys/opencrypto/cryptodev.c:1.86 Wed Apr 5 08:51:04 2017 +++ src/sys/opencrypto/cryptodev.c Fri Apr 7 12:15:51 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: cryptodev.c,v 1.86 2017/04/05 08:51:04 knakahara Exp $ */ +/* $NetBSD: cryptodev.c,v 1.87 2017/04/07 12:15:51 knakahara Exp $ */ /* $FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.4.2.4 2003/06/03 00:09:02 sam Exp $ */ /* $OpenBSD: cryptodev.c,v 1.53 2002/07/10 22:21:30 mickey Exp $ */ @@ -64,7 +64,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cryptodev.c,v 1.86 2017/04/05 08:51:04 knakahara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cryptodev.c,v 1.87 2017/04/07 12:15:51 knakahara Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -663,7 +663,7 @@ eagain: goto bail; } - while (!(crp->crp_flags & CRYPTO_F_DONE)) { + while (!(crp->crp_flags & CRYPTO_F_DQRETQ)) { DPRINTF(("cryptodev_op[%d]: sleeping on cv %p for crp %p\n", (uint32_t)cse->sid, &crp->crp_cv, crp)); cv_wait(&crp->crp_cv, &crypto_mtx); /* XXX cv_wait_sig? */ @@ -744,6 +744,7 @@ cryptodev_cb(void *op) mutex_enter(&crypto_mtx); } if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) { + crp->crp_flags |= CRYPTO_F_DQRETQ; cv_signal(&crp->crp_cv); } mutex_exit(&crypto_mtx); @@ -780,6 +781,7 @@ cryptodevkey_cb(void *op) struct cryptkop *krp = op; mutex_enter(&crypto_mtx); + krp->krp_flags |= CRYPTO_F_DQRETQ; cv_signal(&krp->krp_cv); mutex_exit(&crypto_mtx); return 0; @@ -890,7 +892,7 @@ cryptodev_key(struct crypt_kop *kop) } mutex_enter(&crypto_mtx); - while (!(krp->krp_flags & CRYPTO_F_DONE)) { + while (!(krp->krp_flags & CRYPTO_F_DQRETQ)) { cv_wait(&krp->krp_cv, &crypto_mtx); /* XXX cv_wait_sig? */ } if (krp->krp_flags & CRYPTO_F_ONRETQ) { Index: src/sys/opencrypto/cryptodev.h diff -u src/sys/opencrypto/cryptodev.h:1.29 src/sys/opencrypto/cryptodev.h:1.30 --- src/sys/opencrypto/cryptodev.h:1.29 Mon Mar 6 09:59:05 2017 +++ src/sys/opencrypto/cryptodev.h Fri Apr 7 12:15:51 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: cryptodev.h,v 1.29 2017/03/06 09:59:05 knakahara Exp $ */ +/* $NetBSD: cryptodev.h,v 1.30 2017/04/07 12:15:51 knakahara Exp $ */ /* $FreeBSD: src/sys/opencrypto/cryptodev.h,v 1.2.2.6 2003/07/02 17:04:50 sam Exp $ */ /* $OpenBSD: cryptodev.h,v 1.33 2002/07/17 23:52:39 art Exp $ */ @@ -473,6 +473,7 @@ struct cryptop { #define CRYPTO_F_ONRETQ 0x0080 /* Request is on return queue */ #define CRYPTO_F_USER 0x0100 /* Request is in user context */ #define CRYPTO_F_MORE 0x0200 /* more data to follow */ +#define CRYPTO_F_DQRETQ 0x0400 /* Dequeued from crp_ret_{,k}q */ void * crp_buf; /* Data to be processed */ void * crp_opaque; /* Opaque pointer, passed along */