Module Name:    src
Committed By:   knakahara
Date:           Mon May 29 09:02:46 UTC 2017

Modified Files:
        src/sys/opencrypto: crypto.c

Log Message:
strictly use crypto_checkdriver(i) instead of using crypto_drivers[i] directly.


To generate a diff of this commit:
cvs rdiff -u -r1.76 -r1.77 src/sys/opencrypto/crypto.c

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/crypto.c
diff -u src/sys/opencrypto/crypto.c:1.76 src/sys/opencrypto/crypto.c:1.77
--- src/sys/opencrypto/crypto.c:1.76	Thu May 25 05:24:57 2017
+++ src/sys/opencrypto/crypto.c	Mon May 29 09:02:46 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: crypto.c,v 1.76 2017/05/25 05:24:57 knakahara Exp $ */
+/*	$NetBSD: crypto.c,v 1.77 2017/05/29 09:02:46 knakahara Exp $ */
 /*	$FreeBSD: src/sys/opencrypto/crypto.c,v 1.4.2.5 2003/02/26 00:14:05 sam Exp $	*/
 /*	$OpenBSD: crypto.c,v 1.41 2002/07/17 23:52:38 art Exp $	*/
 
@@ -53,7 +53,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1.76 2017/05/25 05:24:57 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1.77 2017/05/29 09:02:46 knakahara Exp $");
 
 #include <sys/param.h>
 #include <sys/reboot.h>
@@ -99,6 +99,7 @@ int crypto_ret_q_check(struct cryptop *)
  * each algorithm they support with crypto_register() and crypto_kregister().
  */
 static kmutex_t crypto_drv_mtx;
+/* Don't directly access crypto_drivers[i], use crypto_checkdriver(i). */
 static	struct cryptocap *crypto_drivers;
 static	int crypto_drivers_num;
 static	void *softintr_cookie;
@@ -373,6 +374,8 @@ static	int crypto_destroy(bool);
 static	int crypto_invoke(struct cryptop *crp, int hint);
 static	int crypto_kinvoke(struct cryptkop *krp, int hint);
 
+static struct cryptocap *crypto_checkdriver(u_int32_t);
+
 static struct cryptostats cryptostats;
 #ifdef CRYPTO_TIMING
 static	int crypto_timing = 0;
@@ -432,6 +435,8 @@ crypto_destroy(bool exit_kthread)
 	int i;
 
 	if (exit_kthread) {
+		struct cryptocap *cap = NULL;
+
 		mutex_spin_enter(&crypto_ret_q_mtx);
 
 		/* if we have any in-progress requests, don't unload */
@@ -440,10 +445,14 @@ crypto_destroy(bool exit_kthread)
 			return EBUSY;
 		}
 
-		for (i = 0; i < crypto_drivers_num; i++)
-			if (crypto_drivers[i].cc_sessions != 0)
+		for (i = 0; i < crypto_drivers_num; i++) {
+			cap = crypto_checkdriver(i);
+			if (cap == NULL)
+				continue;
+			if (cap->cc_sessions != 0)
 				break;
-		if (i < crypto_drivers_num) {
+		}
+		if (cap != NULL) {
 			mutex_spin_exit(&crypto_ret_q_mtx);
 			return EBUSY;
 		}
@@ -487,14 +496,12 @@ int
 crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int hard)
 {
 	struct cryptoini *cr;
+	struct cryptocap *cap;
 	u_int32_t hid, lid;
 	int err = EINVAL;
 
 	mutex_enter(&crypto_drv_mtx);
 
-	if (crypto_drivers == NULL)
-		goto done;
-
 	/*
 	 * The algorithm we use here is pretty stupid; just use the
 	 * first driver that supports all the algorithms we need.
@@ -504,26 +511,28 @@ crypto_newsession(u_int64_t *sid, struct
 	 */
 
 	for (hid = 0; hid < crypto_drivers_num; hid++) {
+		cap = crypto_checkdriver(hid);
+		if (cap == NULL)
+			continue;
+
 		/*
 		 * If it's not initialized or has remaining sessions
 		 * referencing it, skip.
 		 */
-		if (crypto_drivers[hid].cc_newsession == NULL ||
-		    (crypto_drivers[hid].cc_flags & CRYPTOCAP_F_CLEANUP))
+		if (cap->cc_newsession == NULL ||
+		    (cap->cc_flags & CRYPTOCAP_F_CLEANUP))
 			continue;
 
 		/* Hardware required -- ignore software drivers. */
-		if (hard > 0 &&
-		    (crypto_drivers[hid].cc_flags & CRYPTOCAP_F_SOFTWARE))
+		if (hard > 0 && (cap->cc_flags & CRYPTOCAP_F_SOFTWARE))
 			continue;
 		/* Software required -- ignore hardware drivers. */
-		if (hard < 0 &&
-		    (crypto_drivers[hid].cc_flags & CRYPTOCAP_F_SOFTWARE) == 0)
+		if (hard < 0 && (cap->cc_flags & CRYPTOCAP_F_SOFTWARE) == 0)
 			continue;
 
 		/* See if all the algorithms are supported. */
 		for (cr = cri; cr; cr = cr->cri_next)
-			if (crypto_drivers[hid].cc_alg[cr->cri_alg] == 0) {
+			if (cap->cc_alg[cr->cri_alg] == 0) {
 				DPRINTF("alg %d not supported\n", cr->cri_alg);
 				break;
 			}
@@ -540,13 +549,12 @@ crypto_newsession(u_int64_t *sid, struct
 
 			/* Call the driver initialization routine. */
 			lid = hid;		/* Pass the driver ID. */
-			err = crypto_drivers[hid].cc_newsession(
-					crypto_drivers[hid].cc_arg, &lid, cri);
+			err = cap->cc_newsession(cap->cc_arg, &lid, cri);
 			if (err == 0) {
 				(*sid) = hid;
 				(*sid) <<= 32;
 				(*sid) |= (lid & 0xffffffff);
-				crypto_drivers[hid].cc_sessions++;
+				(cap->cc_sessions)++;
 			} else {
 				DPRINTF("crypto_drivers[%d].cc_newsession() failed. error=%d\n",
 					hid, err);
@@ -567,32 +575,24 @@ done:
 int
 crypto_freesession(u_int64_t sid)
 {
-	u_int32_t hid;
+	struct cryptocap *cap;
 	int err = 0;
 
 	mutex_enter(&crypto_drv_mtx);
 
-	if (crypto_drivers == NULL) {
-		err = EINVAL;
-		goto done;
-	}
-
 	/* Determine two IDs. */
-	hid = CRYPTO_SESID2HID(sid);
-
-	if (hid >= crypto_drivers_num) {
+	cap = crypto_checkdriver(CRYPTO_SESID2HID(sid));
+	if (cap == NULL) {
 		err = ENOENT;
 		goto done;
 	}
 
-	if (crypto_drivers[hid].cc_sessions)
-		crypto_drivers[hid].cc_sessions--;
+	if (cap->cc_sessions)
+		(cap->cc_sessions)--;
 
 	/* Call the driver cleanup routine, if available. */
-	if (crypto_drivers[hid].cc_freesession) {
-		err = crypto_drivers[hid].cc_freesession(
-				crypto_drivers[hid].cc_arg, sid);
-	}
+	if (cap->cc_freesession)
+		err = cap->cc_freesession(cap->cc_arg, sid);
 	else
 		err = 0;
 
@@ -600,9 +600,8 @@ crypto_freesession(u_int64_t sid)
 	 * If this was the last session of a driver marked as invalid,
 	 * make the entry available for reuse.
 	 */
-	if ((crypto_drivers[hid].cc_flags & CRYPTOCAP_F_CLEANUP) &&
-	    crypto_drivers[hid].cc_sessions == 0)
-		memset(&crypto_drivers[hid], 0, sizeof(struct cryptocap));
+	if ((cap->cc_flags & CRYPTOCAP_F_CLEANUP) && cap->cc_sessions == 0)
+		memset(cap, 0, sizeof(struct cryptocap));
 
 done:
 	mutex_exit(&crypto_drv_mtx);
@@ -617,19 +616,24 @@ int32_t
 crypto_get_driverid(u_int32_t flags)
 {
 	struct cryptocap *newdrv;
+	struct cryptocap *cap = NULL;
 	int i;
 
 	(void)crypto_init();		/* XXX oh, this is foul! */
 
 	mutex_enter(&crypto_drv_mtx);
-	for (i = 0; i < crypto_drivers_num; i++)
-		if (crypto_drivers[i].cc_process == NULL &&
-		    (crypto_drivers[i].cc_flags & CRYPTOCAP_F_CLEANUP) == 0 &&
-		    crypto_drivers[i].cc_sessions == 0)
+	for (i = 0; i < crypto_drivers_num; i++) {
+		cap = crypto_checkdriver(i);
+		if (cap == NULL)
+			continue;
+		if (cap->cc_process == NULL &&
+		    (cap->cc_flags & CRYPTOCAP_F_CLEANUP) == 0 &&
+		    cap->cc_sessions == 0)
 			break;
+	}
 
 	/* Out of entries, allocate some more. */
-	if (i == crypto_drivers_num) {
+	if (cap == NULL) {
 		/* Be careful about wrap-around. */
 		if (2 * crypto_drivers_num <= crypto_drivers_num) {
 			mutex_exit(&crypto_drv_mtx);
@@ -652,11 +656,14 @@ crypto_get_driverid(u_int32_t flags)
 
 		free(crypto_drivers, M_CRYPTO_DATA);
 		crypto_drivers = newdrv;
+
+		cap = crypto_checkdriver(i);
+		KASSERT(cap != NULL);
 	}
 
 	/* NB: state is zero'd on free */
-	crypto_drivers[i].cc_sessions = 1;	/* Mark */
-	crypto_drivers[i].cc_flags = flags;
+	cap->cc_sessions = 1;	/* Mark */
+	cap->cc_flags = flags;
 
 	if (bootverbose)
 		printf("crypto: assign driver %u, flags %u\n", i, flags);
@@ -899,14 +906,11 @@ crypto_unblock(u_int32_t driverid, int w
 int
 crypto_dispatch(struct cryptop *crp)
 {
-	u_int32_t hid;
 	int result;
 	struct cryptocap *cap;
 
 	KASSERT(crp != NULL);
 
-	hid = CRYPTO_SESID2HID(crp->crp_sid);
-
 	DPRINTF("crp %p, alg %d\n", crp, crp->crp_desc->crd_alg);
 
 	cryptostats.cs_ops++;
@@ -935,7 +939,7 @@ crypto_dispatch(struct cryptop *crp)
 
 	mutex_spin_enter(&crypto_q_mtx);
 
-	cap = crypto_checkdriver(hid);
+	cap = crypto_checkdriver(CRYPTO_SESID2HID(crp->crp_sid));
 	/*
 	 * TODO:
 	 * If we can ensure the driver has been valid until the driver is
@@ -982,7 +986,7 @@ crypto_dispatch(struct cryptop *crp)
 		 * the op on the queue.
 		 */
 		mutex_spin_enter(&crypto_q_mtx);
-		crypto_drivers[hid].cc_qblocked = 1;
+		cap->cc_qblocked = 1;
 		TAILQ_INSERT_HEAD(&crp_q, crp, crp_next);
 		cryptostats.cs_blocks++;
 		mutex_spin_exit(&crypto_q_mtx);
@@ -1046,7 +1050,7 @@ crypto_kdispatch(struct cryptkop *krp)
 		 * the op on the queue.
 		 */
 		mutex_spin_enter(&crypto_q_mtx);
-		crypto_drivers[krp->krp_hid].cc_kqblocked = 1;
+		cap->cc_kqblocked = 1;
 		TAILQ_INSERT_HEAD(&crp_kq, krp, krp_next);
 		cryptostats.cs_kblocks++;
 		mutex_spin_exit(&crypto_q_mtx);
@@ -1068,6 +1072,7 @@ crypto_kdispatch(struct cryptkop *krp)
 static int
 crypto_kinvoke(struct cryptkop *krp, int hint)
 {
+	struct cryptocap *cap = NULL;
 	u_int32_t hid;
 	int error;
 
@@ -1082,22 +1087,25 @@ crypto_kinvoke(struct cryptkop *krp, int
 
 	mutex_enter(&crypto_drv_mtx);
 	for (hid = 0; hid < crypto_drivers_num; hid++) {
-		if ((crypto_drivers[hid].cc_flags & CRYPTOCAP_F_SOFTWARE) &&
+		cap = crypto_checkdriver(hid);
+		if (cap == NULL)
+			continue;
+		if ((cap->cc_flags & CRYPTOCAP_F_SOFTWARE) &&
 		    crypto_devallowsoft == 0)
 			continue;
-		if (crypto_drivers[hid].cc_kprocess == NULL)
+		if (cap->cc_kprocess == NULL)
 			continue;
-		if ((crypto_drivers[hid].cc_kalg[krp->krp_op] &
+		if ((cap->cc_kalg[krp->krp_op] &
 		    CRYPTO_ALG_FLAG_SUPPORTED) == 0)
 			continue;
 		break;
 	}
-	if (hid < crypto_drivers_num) {
+	if (cap != NULL) {
 		int (*process)(void *, struct cryptkop *, int);
 		void *arg;
 
-		process = crypto_drivers[hid].cc_kprocess;
-		arg = crypto_drivers[hid].cc_karg;
+		process = cap->cc_kprocess;
+		arg = cap->cc_karg;
 		mutex_exit(&crypto_drv_mtx);
 		krp->krp_hid = hid;
 		error = (*process)(arg, krp, hint);
@@ -1143,7 +1151,7 @@ crypto_tstat(struct cryptotstat *ts, str
 static int
 crypto_invoke(struct cryptop *crp, int hint)
 {
-	u_int32_t hid;
+	struct cryptocap *cap;
 
 	KASSERT(crp != NULL);
 
@@ -1161,14 +1169,13 @@ crypto_invoke(struct cryptop *crp, int h
 		return 0;
 	}
 
-	hid = CRYPTO_SESID2HID(crp->crp_sid);
-
-	if ((crypto_drivers[hid].cc_flags & CRYPTOCAP_F_CLEANUP) == 0) {
+	cap = crypto_checkdriver(CRYPTO_SESID2HID(crp->crp_sid));
+	if (cap != NULL && (cap->cc_flags & CRYPTOCAP_F_CLEANUP) == 0) {
 		int (*process)(void *, struct cryptop *, int);
 		void *arg;
 
-		process = crypto_drivers[hid].cc_process;
-		arg = crypto_drivers[hid].cc_arg;
+		process = cap->cc_process;
+		arg = cap->cc_arg;
 
 		/*
 		 * Invoke the driver to process the request.
@@ -1439,14 +1446,19 @@ crypto_getfeat(int *featp)
 	mutex_enter(&crypto_drv_mtx);
 
 	for (hid = 0; hid < crypto_drivers_num; hid++) {
-		if ((crypto_drivers[hid].cc_flags & CRYPTOCAP_F_SOFTWARE) &&
+		struct cryptocap *cap;
+		cap = crypto_checkdriver(hid);
+		if (cap == NULL)
+			continue;
+
+		if ((cap->cc_flags & CRYPTOCAP_F_SOFTWARE) &&
 		    crypto_devallowsoft == 0) {
 			continue;
 		}
-		if (crypto_drivers[hid].cc_kprocess == NULL)
+		if (cap->cc_kprocess == NULL)
 			continue;
 		for (kalg = 0; kalg < CRK_ALGORITHM_MAX; kalg++)
-			if ((crypto_drivers[hid].cc_kalg[kalg] &
+			if ((cap->cc_kalg[kalg] &
 			    CRYPTO_ALG_FLAG_SUPPORTED) != 0)
 				feat |=  1 << kalg;
 	}
@@ -1534,10 +1546,16 @@ cryptointr(void)
 				 * at the front.  This should be ok; putting
 				 * it at the end does not work.
 				 */
-				/* XXX validate sid again? */
-				crypto_drivers[CRYPTO_SESID2HID(submit->crp_sid)].cc_qblocked = 1;
-				TAILQ_INSERT_HEAD(&crp_q, submit, crp_next);
-				cryptostats.cs_blocks++;
+				/* validate sid again */
+				cap = crypto_checkdriver(CRYPTO_SESID2HID(submit->crp_sid));
+				if (cap == NULL) {
+					/* migrate again, sigh... */
+					TAILQ_INSERT_TAIL(&crp_q, submit, crp_next);
+				} else {
+					cap->cc_qblocked = 1;
+					TAILQ_INSERT_HEAD(&crp_q, submit, crp_next);
+					cryptostats.cs_blocks++;
+				}
 			}
 		}
 
@@ -1567,10 +1585,16 @@ cryptointr(void)
 				 * at the front.  This should be ok; putting
 				 * it at the end does not work.
 				 */
-				/* XXX validate sid again? */
-				crypto_drivers[krp->krp_hid].cc_kqblocked = 1;
-				TAILQ_INSERT_HEAD(&crp_kq, krp, krp_next);
-				cryptostats.cs_kblocks++;
+				/* validate sid again */
+				cap = crypto_checkdriver(krp->krp_hid);
+				if (cap == NULL) {
+					/* migrate again, sigh... */
+					TAILQ_INSERT_TAIL(&crp_kq, krp, krp_next);
+				} else {
+					cap->cc_kqblocked = 1;
+					TAILQ_INSERT_HEAD(&crp_kq, krp, krp_next);
+					cryptostats.cs_kblocks++;
+				}
 			}
 		}
 	} while (submit != NULL || krp != NULL);

Reply via email to