diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2009-09-03 07:47:28 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2009-09-03 07:47:28 +0000 |
commit | f946653af52e63c2b12d989c15719f713e69dc42 (patch) | |
tree | c5330b6158f25b60b48ac1c2feb6290595a4b0b7 /sys/crypto | |
parent | 3ccdbcac647b954dc66ffa0516d03435301bb981 (diff) |
crypto hardware (eg, hifn) establishes its interrupt handler at
IPL_NET. when the hardware finishes some work for the crypto subsystem
and therefore something in the kernel that wanted crypto done, it
calls crypto_done from that interrupt handler.
one of the things that uses crypto is ipsec. when crypto is done
for ipsec it then pushes the packet along the network stack. the
problem is that all the structures inside the network stack are
only protected at splsoftnet. we could be in the middle of modifications
to the pf state table or the pfsync queues when we get a hifn
interrupt and then go stomp on the same structures.
the solution is to defer the completions so they can do the right
spl protections.
this basically reverts r1.46 of src/sys/crypto/crypto.c.
found by naddy@
Diffstat (limited to 'sys/crypto')
-rw-r--r-- | sys/crypto/crypto.c | 19 | ||||
-rw-r--r-- | sys/crypto/cryptodev.h | 7 |
2 files changed, 18 insertions, 8 deletions
diff --git a/sys/crypto/crypto.c b/sys/crypto/crypto.c index 5faf0f645b7..a6445b3e30a 100644 --- a/sys/crypto/crypto.c +++ b/sys/crypto/crypto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: crypto.c,v 1.52 2008/10/30 23:55:22 dlg Exp $ */ +/* $OpenBSD: crypto.c,v 1.53 2009/09/03 07:47:27 dlg Exp $ */ /* * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) * @@ -25,7 +25,6 @@ #include <sys/malloc.h> #include <sys/proc.h> #include <sys/pool.h> -#include <sys/workq.h> #include <crypto/cryptodev.h> @@ -420,7 +419,7 @@ crypto_dispatch(struct cryptop *crp) splx(s); if (crypto_workq) { - workq_add_task(crypto_workq, 0, + workq_queue_task(crypto_workq, &crp->crp_wqt, 0, (workq_fn)crypto_invoke, crp, NULL); } else { crypto_invoke(crp); @@ -432,9 +431,8 @@ crypto_dispatch(struct cryptop *crp) int crypto_kdispatch(struct cryptkop *krp) { - if (crypto_workq) { - workq_add_task(crypto_workq, 0, + workq_queue_task(crypto_workq, &krp->krp_wqt, 0, (workq_fn)crypto_kinvoke, krp, NULL); } else { crypto_kinvoke(krp); @@ -640,7 +638,13 @@ void crypto_done(struct cryptop *crp) { crp->crp_flags |= CRYPTO_F_DONE; - crp->crp_callback(crp); + if (crp->crp_flags & CRYPTO_F_NOQUEUE) { + /* not from the crypto queue, wakeup the userland process */ + crp->crp_callback(crp); + } else { + workq_queue_task(crypto_workq, &crp->crp_wqt, 0, + (workq_fn)crp->crp_callback, crp, NULL); + } } /* @@ -649,7 +653,8 @@ crypto_done(struct cryptop *crp) void crypto_kdone(struct cryptkop *krp) { - krp->krp_callback(krp); + workq_queue_task(crypto_workq, &krp->krp_wqt, 0, + (workq_fn)krp->krp_callback, krp, NULL); } int diff --git a/sys/crypto/cryptodev.h b/sys/crypto/cryptodev.h index 1a0e7d4a51c..1a736c985cc 100644 --- a/sys/crypto/cryptodev.h +++ b/sys/crypto/cryptodev.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cryptodev.h,v 1.47 2008/06/09 16:07:00 djm Exp $ */ +/* $OpenBSD: cryptodev.h,v 1.48 2009/09/03 07:47:27 dlg Exp $ */ /* * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) @@ -53,6 +53,7 @@ #define _CRYPTO_CRYPTO_H_ #include <sys/ioccom.h> +#include <sys/workq.h> /* Some initial values */ #define CRYPTO_DRIVERS_INITIAL 4 @@ -143,6 +144,8 @@ struct cryptodesc { /* Structure describing complete operation */ struct cryptop { + struct workq_task crp_wqt; + u_int64_t crp_sid; /* Session ID */ int crp_ilen; /* Input data total length */ int crp_olen; /* Result total length */ @@ -211,6 +214,8 @@ struct crypt_kop { #define CRF_DH_COMPUTE_KEY (1 << CRK_DH_COMPUTE_KEY) struct cryptkop { + struct workq_task krp_wqt; + u_int krp_op; /* ie. CRK_MOD_EXP or other */ u_int krp_status; /* return status */ u_short krp_iparams; /* # of input parameters */ |