summaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2012-10-21 20:42:28 +0300
committerPaul Gortmaker <paul.gortmaker@windriver.com>2014-02-10 16:11:15 -0500
commit54f421b07dbda67ee57c5e5e90cba4dd65279242 (patch)
treeb830a9a897b2cf14b7f49ef391daf7a4bb6262db /crypto
parent3e7f0a70958c7f5ed9bc684bc6601cf398c8c948 (diff)
crypto: cryptd - disable softirqs in cryptd_queue_worker to prevent data corruption
commit 9efade1b3e981f5064f9db9ca971b4dc7557ae42 upstream. cryptd_queue_worker attempts to prevent simultaneous accesses to crypto workqueue by cryptd_enqueue_request using preempt_disable/preempt_enable. However cryptd_enqueue_request might be called from softirq context, so add local_bh_disable/local_bh_enable to prevent data corruption and panics. Bug report at http://marc.info/?l=linux-crypto-vger&m=134858649616319&w=2 v2: - Disable software interrupts instead of hardware interrupts Reported-by: Gurucharan Shetty <gurucharan.shetty@gmail.com> Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/cryptd.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index ef71318976c7..6e241640219d 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -116,13 +116,18 @@ static void cryptd_queue_worker(struct work_struct *work)
struct crypto_async_request *req, *backlog;
cpu_queue = container_of(work, struct cryptd_cpu_queue, work);
- /* Only handle one request at a time to avoid hogging crypto
- * workqueue. preempt_disable/enable is used to prevent
- * being preempted by cryptd_enqueue_request() */
+ /*
+ * Only handle one request at a time to avoid hogging crypto workqueue.
+ * preempt_disable/enable is used to prevent being preempted by
+ * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent
+ * cryptd_enqueue_request() being accessed from software interrupts.
+ */
+ local_bh_disable();
preempt_disable();
backlog = crypto_get_backlog(&cpu_queue->queue);
req = crypto_dequeue_request(&cpu_queue->queue);
preempt_enable();
+ local_bh_enable();
if (!req)
return;