Module Name:    src
Committed By:   riastradh
Date:           Sun May 22 11:25:14 UTC 2022

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

Log Message:
opencrypto: Make sid=0 always invalid, but OK to free.

Previously, crypto_newsession could sometimes return 0 as the
driver-specific part of the session id, and 0 as the hid, for sid=0.
But netipsec assumes that it is always safe to free sid=0 from
zero-initialized memory even if crypto_newsession has never
succeeded.  So it was up to every driver in tree to gracefully handle
sid=0, if it happened to get assigned hid=0.  And, as long as the
freesession callback was expected to just return an error code when
given a bogus session id, that worked out fine...because nothing ever
used the error code.

That was a terrible fragile system that should never have been
invented.  Instead, let's just ensure that valid session ids are
nonzero, and make crypto_freesession with sid=0 be a no-op.


To generate a diff of this commit:
cvs rdiff -u -r1.119 -r1.120 src/sys/opencrypto/crypto.c
cvs rdiff -u -r1.43 -r1.44 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/crypto.c
diff -u src/sys/opencrypto/crypto.c:1.119 src/sys/opencrypto/crypto.c:1.120
--- src/sys/opencrypto/crypto.c:1.119	Thu May 19 20:51:59 2022
+++ src/sys/opencrypto/crypto.c	Sun May 22 11:25:14 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: crypto.c,v 1.119 2022/05/19 20:51:59 riastradh Exp $ */
+/*	$NetBSD: crypto.c,v 1.120 2022/05/22 11:25:14 riastradh 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.119 2022/05/19 20:51:59 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1.120 2022/05/22 11:25:14 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/reboot.h>
@@ -800,6 +800,16 @@ crypto_newsession(u_int64_t *sid, struct
 	struct cryptocap *cap;
 	int err = EINVAL;
 
+	/*
+	 * On failure, leave *sid initialized to a sentinel value that
+	 * crypto_freesession will ignore.  This is the same as what
+	 * you get from zero-initialized memory -- some callers (I'm
+	 * looking at you, netipsec!) have paths that lead from
+	 * zero-initialized memory into crypto_freesession without any
+	 * crypto_newsession.
+	 */
+	*sid = 0;
+
 	mutex_enter(&crypto_drv_mtx);
 
 	cap = crypto_select_driver_lock(cri, hard);
@@ -807,6 +817,7 @@ crypto_newsession(u_int64_t *sid, struct
 		u_int32_t hid, lid;
 
 		hid = cap - crypto_drivers;
+		KASSERT(hid < 0xffffff);
 		/*
 		 * Can't do everything in one session.
 		 *
@@ -820,10 +831,11 @@ crypto_newsession(u_int64_t *sid, struct
 		err = cap->cc_newsession(cap->cc_arg, &lid, cri);
 		crypto_driver_lock(cap);
 		if (err == 0) {
-			(*sid) = hid;
+			(*sid) = hid + 1;
 			(*sid) <<= 32;
 			(*sid) |= (lid & 0xffffffff);
-			(cap->cc_sessions)++;
+			KASSERT(*sid != 0);
+			cap->cc_sessions++;
 		} else {
 			DPRINTF("crypto_drivers[%d].cc_newsession() failed. error=%d\n",
 			    hid, err);
@@ -846,6 +858,17 @@ crypto_freesession(u_int64_t sid)
 	struct cryptocap *cap;
 	int err = 0;
 
+	/*
+	 * crypto_newsession never returns 0 as a sid (by virtue of
+	 * never returning 0 as a hid, which is part of the sid).
+	 * However, some callers assume that freeing zero is safe.
+	 * Previously this relied on all drivers to agree that freeing
+	 * invalid sids is a no-op, but that's a terrible API contract
+	 * that we're getting rid of.
+	 */
+	if (sid == 0)
+		return;
+
 	/* Determine two IDs. */
 	cap = crypto_checkdriver_lock(CRYPTO_SESID2HID(sid));
 	if (cap == NULL)

Index: src/sys/opencrypto/cryptodev.h
diff -u src/sys/opencrypto/cryptodev.h:1.43 src/sys/opencrypto/cryptodev.h:1.44
--- src/sys/opencrypto/cryptodev.h:1.43	Thu May 19 20:51:46 2022
+++ src/sys/opencrypto/cryptodev.h	Sun May 22 11:25:14 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: cryptodev.h,v 1.43 2022/05/19 20:51:46 riastradh Exp $ */
+/*	$NetBSD: cryptodev.h,v 1.44 2022/05/22 11:25:14 riastradh 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 $	*/
 
@@ -589,7 +589,7 @@ struct cryptocap {
  * a copy of the driver's capabilities that can be used by client code to
  * optimize operation.
  */
-#define	CRYPTO_SESID2HID(_sid)	(((_sid) >> 32) & 0xffffff)
+#define	CRYPTO_SESID2HID(_sid)	((((_sid) >> 32) & 0xffffff) - 1)
 #define	CRYPTO_SESID2CAPS(_sid)	(((_sid) >> 56) & 0xff)
 #define	CRYPTO_SESID2LID(_sid)	(((u_int32_t) (_sid)) & 0xffffffff)
 

Reply via email to