Index: sys/crypto/crypto.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/crypto/crypto.c,v retrieving revision 1.83 diff -u -p -u -p -r1.83 crypto.c --- sys/crypto/crypto.c 30 Jun 2021 12:21:02 -0000 1.83 +++ sys/crypto/crypto.c 16 Jul 2021 22:03:53 -0000 @@ -387,26 +387,33 @@ crypto_unregister(u_int32_t driverid, in int crypto_dispatch(struct cryptop *crp) { - struct taskq *tq = crypto_taskq; - int s; + int error = 0, lock = 1, s; u_int32_t hid; s = splvm(); hid = (crp->crp_sid >> 32) & 0xffffffff; if (hid < crypto_drivers_num) { if (crypto_drivers[hid].cc_flags & CRYPTOCAP_F_MPSAFE) - tq = crypto_taskq_mpsafe; + /* XXXSMP crypto_invoke() is not MP safe */ + lock = 1; } splx(s); - if (tq && !(crp->crp_flags & CRYPTO_F_NOQUEUE)) { + if (crp->crp_flags & CRYPTO_F_NOQUEUE) { + if (lock) + KERNEL_LOCK(); + error = crypto_invoke(crp); + if (lock) + KERNEL_UNLOCK(); + } else { + struct taskq *tq; + + tq = lock ? crypto_taskq : crypto_taskq_mpsafe; task_set(&crp->crp_task, (void (*))crypto_invoke, crp); task_add(tq, &crp->crp_task); - } else { - crypto_invoke(crp); } - return 0; + return error; } /* @@ -424,6 +431,8 @@ crypto_invoke(struct cryptop *crp) if (crp == NULL || crp->crp_callback == NULL) return EINVAL; + KERNEL_ASSERT_LOCKED(); + s = splvm(); if (crp->crp_ndesc < 1 || crypto_drivers == NULL) { crp->crp_etype = EINVAL; @@ -534,12 +543,25 @@ crypto_init(void) void crypto_done(struct cryptop *crp) { + int lock = 1; + crp->crp_flags |= CRYPTO_F_DONE; + + if (crp->crp_flags & CRYPTO_F_MPSAFE) + lock = 0; + if (crp->crp_flags & CRYPTO_F_NOQUEUE) { /* not from the crypto queue, wakeup the userland process */ + if (lock) + KERNEL_LOCK(); crp->crp_callback(crp); + if (lock) + KERNEL_UNLOCK(); } else { + struct taskq *tq; + + tq = lock ? crypto_taskq : crypto_taskq_mpsafe; task_set(&crp->crp_task, (void (*))crp->crp_callback, crp); - task_add(crypto_taskq, &crp->crp_task); + task_add(tq, &crp->crp_task); } } Index: sys/crypto/cryptodev.h =================================================================== RCS file: /mount/openbsd/cvs/src/sys/crypto/cryptodev.h,v retrieving revision 1.73 diff -u -p -u -p -r1.73 cryptodev.h --- sys/crypto/cryptodev.h 9 Jul 2021 20:43:28 -0000 1.73 +++ sys/crypto/cryptodev.h 16 Jul 2021 22:03:53 -0000 @@ -171,6 +171,7 @@ struct cryptop { #define CRYPTO_F_IMBUF 0x0001 /* Input/output are mbuf chains, otherwise contig */ #define CRYPTO_F_IOV 0x0002 /* Input/output are uio */ +#define CRYPTO_F_MPSAFE 0x0004 /* Do not use kernel lock for callback */ #define CRYPTO_F_NOQUEUE 0x0008 /* Don't use crypto queue/thread */ #define CRYPTO_F_DONE 0x0010 /* request completed */ Index: sys/netinet/ip_ah.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/netinet/ip_ah.c,v retrieving revision 1.150 diff -u -p -u -p -r1.150 ip_ah.c --- sys/netinet/ip_ah.c 8 Jul 2021 21:07:19 -0000 1.150 +++ sys/netinet/ip_ah.c 16 Jul 2021 22:03:53 -0000 @@ -684,7 +684,7 @@ ah_input(struct mbuf *m, struct tdb *tdb /* Crypto operation descriptor. */ crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ - crp->crp_flags = CRYPTO_F_IMBUF; + crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_MPSAFE | CRYPTO_F_NOQUEUE; crp->crp_buf = (caddr_t)m; crp->crp_callback = ipsec_input_cb; crp->crp_sid = tdb->tdb_cryptoid; @@ -698,9 +698,7 @@ ah_input(struct mbuf *m, struct tdb *tdb tc->tc_rdomain = tdb->tdb_rdomain; memcpy(&tc->tc_dst, &tdb->tdb_dst, sizeof(union sockaddr_union)); - KERNEL_LOCK(); error = crypto_dispatch(crp); - KERNEL_UNLOCK(); return error; drop: @@ -1131,7 +1129,7 @@ ah_output(struct mbuf *m, struct tdb *td /* Crypto operation descriptor. */ crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ - crp->crp_flags = CRYPTO_F_IMBUF; + crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_MPSAFE | CRYPTO_F_NOQUEUE; crp->crp_buf = (caddr_t)m; crp->crp_callback = ipsec_output_cb; crp->crp_sid = tdb->tdb_cryptoid; @@ -1145,9 +1143,7 @@ ah_output(struct mbuf *m, struct tdb *td tc->tc_rdomain = tdb->tdb_rdomain; memcpy(&tc->tc_dst, &tdb->tdb_dst, sizeof(union sockaddr_union)); - KERNEL_LOCK(); error = crypto_dispatch(crp); - KERNEL_UNLOCK(); return error; drop: Index: sys/netinet/ip_esp.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/netinet/ip_esp.c,v retrieving revision 1.167 diff -u -p -u -p -r1.167 ip_esp.c --- sys/netinet/ip_esp.c 8 Jul 2021 21:07:19 -0000 1.167 +++ sys/netinet/ip_esp.c 16 Jul 2021 22:03:53 -0000 @@ -498,7 +498,7 @@ esp_input(struct mbuf *m, struct tdb *td /* Crypto operation descriptor */ crp->crp_ilen = m->m_pkthdr.len; /* Total input length */ - crp->crp_flags = CRYPTO_F_IMBUF; + crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_MPSAFE | CRYPTO_F_NOQUEUE; crp->crp_buf = (caddr_t)m; crp->crp_callback = ipsec_input_cb; crp->crp_sid = tdb->tdb_cryptoid; @@ -527,9 +527,7 @@ esp_input(struct mbuf *m, struct tdb *td crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); } - KERNEL_LOCK(); error = crypto_dispatch(crp); - KERNEL_UNLOCK(); return error; drop: @@ -980,7 +978,7 @@ esp_output(struct mbuf *m, struct tdb *t /* Crypto operation descriptor. */ crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ - crp->crp_flags = CRYPTO_F_IMBUF; + crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_MPSAFE | CRYPTO_F_NOQUEUE; crp->crp_buf = (caddr_t)m; crp->crp_callback = ipsec_output_cb; crp->crp_opaque = (caddr_t)tc; @@ -1012,9 +1010,7 @@ esp_output(struct mbuf *m, struct tdb *t crda->crd_len = m->m_pkthdr.len - (skip + alen); } - KERNEL_LOCK(); error = crypto_dispatch(crp); - KERNEL_UNLOCK(); return error; drop: Index: sys/netinet/ip_ipcomp.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/netinet/ip_ipcomp.c,v retrieving revision 1.71 diff -u -p -u -p -r1.71 ip_ipcomp.c --- sys/netinet/ip_ipcomp.c 8 Jul 2021 21:07:19 -0000 1.71 +++ sys/netinet/ip_ipcomp.c 16 Jul 2021 22:03:53 -0000 @@ -174,7 +174,7 @@ ipcomp_input(struct mbuf *m, struct tdb /* Crypto operation descriptor */ crp->crp_ilen = m->m_pkthdr.len - (skip + hlen); - crp->crp_flags = CRYPTO_F_IMBUF; + crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_MPSAFE | CRYPTO_F_NOQUEUE; crp->crp_buf = (caddr_t)m; crp->crp_callback = ipsec_input_cb; crp->crp_sid = tdb->tdb_cryptoid; @@ -188,9 +188,7 @@ ipcomp_input(struct mbuf *m, struct tdb tc->tc_rdomain = tdb->tdb_rdomain; tc->tc_dst = tdb->tdb_dst; - KERNEL_LOCK(); error = crypto_dispatch(crp); - KERNEL_UNLOCK(); return error; } @@ -479,15 +477,13 @@ ipcomp_output(struct mbuf *m, struct tdb /* Crypto operation descriptor */ crp->crp_ilen = m->m_pkthdr.len; /* Total input length */ - crp->crp_flags = CRYPTO_F_IMBUF; + crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_MPSAFE | CRYPTO_F_NOQUEUE; crp->crp_buf = (caddr_t)m; crp->crp_callback = ipsec_output_cb; crp->crp_opaque = (caddr_t)tc; crp->crp_sid = tdb->tdb_cryptoid; - KERNEL_LOCK(); error = crypto_dispatch(crp); - KERNEL_UNLOCK(); return error; drop: Index: sys/netinet/ipsec_input.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/netinet/ipsec_input.c,v retrieving revision 1.175 diff -u -p -u -p -r1.175 ipsec_input.c --- sys/netinet/ipsec_input.c 8 Jul 2021 15:13:14 -0000 1.175 +++ sys/netinet/ipsec_input.c 16 Jul 2021 22:03:54 -0000 @@ -380,16 +380,14 @@ ipsec_input_cb(struct cryptop *crp) struct tdb *tdb = NULL; int clen, error; - KERNEL_ASSERT_LOCKED(); - if (m == NULL) { DPRINTF("bogus returned buffer from crypto"); ipsecstat_inc(ipsec_crypto); goto droponly; } + NET_ASSERT_LOCKED(); - NET_LOCK(); tdb = gettdb(tc->tc_rdomain, tc->tc_spi, &tc->tc_dst, tc->tc_proto); if (tdb == NULL) { DPRINTF("TDB is expired while in crypto"); @@ -403,7 +401,6 @@ ipsec_input_cb(struct cryptop *crp) /* Reset the session ID */ if (tdb->tdb_cryptoid != 0) tdb->tdb_cryptoid = crp->crp_sid; - NET_UNLOCK(); crypto_dispatch(crp); return; } @@ -433,7 +430,6 @@ ipsec_input_cb(struct cryptop *crp) __func__, tdb->tdb_sproto); } - NET_UNLOCK(); if (error) { ipsecstat_inc(ipsec_idrops); tdb->tdb_idrops++; @@ -441,7 +437,6 @@ ipsec_input_cb(struct cryptop *crp) return; baddone: - NET_UNLOCK(); droponly: ipsecstat_inc(ipsec_idrops); if (tdb != NULL) Index: sys/netinet/ipsec_output.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/netinet/ipsec_output.c,v retrieving revision 1.82 diff -u -p -u -p -r1.82 ipsec_output.c --- sys/netinet/ipsec_output.c 8 Jul 2021 15:13:14 -0000 1.82 +++ sys/netinet/ipsec_output.c 16 Jul 2021 22:03:54 -0000 @@ -395,15 +395,14 @@ ipsec_output_cb(struct cryptop *crp) struct tdb *tdb = NULL; int error, ilen, olen; - KERNEL_ASSERT_LOCKED(); - if (m == NULL) { DPRINTF("bogus returned buffer from crypto"); ipsecstat_inc(ipsec_crypto); goto droponly; } - NET_LOCK(); + NET_ASSERT_LOCKED(); + tdb = gettdb(tc->tc_rdomain, tc->tc_spi, &tc->tc_dst, tc->tc_proto); if (tdb == NULL) { DPRINTF("TDB is expired while in crypto"); @@ -417,8 +416,12 @@ ipsec_output_cb(struct cryptop *crp) /* Reset the session ID */ if (tdb->tdb_cryptoid != 0) tdb->tdb_cryptoid = crp->crp_sid; - NET_UNLOCK(); - crypto_dispatch(crp); + error = crypto_dispatch(crp); + if (error) { + DPRINTF("crypto dispatch error %d", error); + ipsecstat_inc(ipsec_odrops); + tdb->tdb_odrops++; + } return; } DPRINTF("crypto error %d", crp->crp_etype); @@ -447,7 +450,6 @@ ipsec_output_cb(struct cryptop *crp) __func__, tdb->tdb_sproto); } - NET_UNLOCK(); if (error) { ipsecstat_inc(ipsec_odrops); tdb->tdb_odrops++; @@ -455,7 +457,6 @@ ipsec_output_cb(struct cryptop *crp) return; baddone: - NET_UNLOCK(); droponly: if (tdb != NULL) tdb->tdb_odrops++; @@ -479,6 +480,8 @@ ipsp_process_done(struct mbuf *m, struct struct tdb_ident *tdbi; struct m_tag *mtag; int roff, error; + + NET_ASSERT_LOCKED(); tdb->tdb_last_used = gettime();