Skip to content

Commit 0fc0f18

Browse files
committed
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto fixes from Herbert Xu: "This fixes the following issues: - fix chacha20 crash on zero-length input due to unset IV - fix potential race conditions in mcryptd with spinlock - only wait once at top of algif recvmsg to avoid inconsistencies - fix potential use-after-free in algif_aead/algif_skcipher" * 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: crypto: af_alg - fix race accessing cipher request crypto: mcryptd - protect the per-CPU queue with a lock crypto: af_alg - wait for data at beginning of recvmsg crypto: skcipher - set walk.iv for zero-length inputs
2 parents 6ed1675 + d53c513 commit 0fc0f18

File tree

6 files changed

+37
-35
lines changed

6 files changed

+37
-35
lines changed

crypto/af_alg.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,12 +1138,6 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
11381138
if (!af_alg_readable(sk))
11391139
break;
11401140

1141-
if (!ctx->used) {
1142-
err = af_alg_wait_for_data(sk, flags);
1143-
if (err)
1144-
return err;
1145-
}
1146-
11471141
seglen = min_t(size_t, (maxsize - len),
11481142
msg_data_left(msg));
11491143

crypto/algif_aead.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
111111
size_t usedpages = 0; /* [in] RX bufs to be used from user */
112112
size_t processed = 0; /* [in] TX bufs to be consumed */
113113

114+
if (!ctx->used) {
115+
err = af_alg_wait_for_data(sk, flags);
116+
if (err)
117+
return err;
118+
}
119+
114120
/*
115121
* Data length provided by caller via sendmsg/sendpage that has not
116122
* yet been processed.
@@ -285,19 +291,19 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
285291
/* AIO operation */
286292
sock_hold(sk);
287293
areq->iocb = msg->msg_iocb;
294+
295+
/* Remember output size that will be generated. */
296+
areq->outlen = outlen;
297+
288298
aead_request_set_callback(&areq->cra_u.aead_req,
289299
CRYPTO_TFM_REQ_MAY_BACKLOG,
290300
af_alg_async_cb, areq);
291301
err = ctx->enc ? crypto_aead_encrypt(&areq->cra_u.aead_req) :
292302
crypto_aead_decrypt(&areq->cra_u.aead_req);
293303

294304
/* AIO operation in progress */
295-
if (err == -EINPROGRESS || err == -EBUSY) {
296-
/* Remember output size that will be generated. */
297-
areq->outlen = outlen;
298-
305+
if (err == -EINPROGRESS || err == -EBUSY)
299306
return -EIOCBQUEUED;
300-
}
301307

302308
sock_put(sk);
303309
} else {

crypto/algif_skcipher.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
7272
int err = 0;
7373
size_t len = 0;
7474

75+
if (!ctx->used) {
76+
err = af_alg_wait_for_data(sk, flags);
77+
if (err)
78+
return err;
79+
}
80+
7581
/* Allocate cipher request for current operation. */
7682
areq = af_alg_alloc_areq(sk, sizeof(struct af_alg_async_req) +
7783
crypto_skcipher_reqsize(tfm));
@@ -119,6 +125,10 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
119125
/* AIO operation */
120126
sock_hold(sk);
121127
areq->iocb = msg->msg_iocb;
128+
129+
/* Remember output size that will be generated. */
130+
areq->outlen = len;
131+
122132
skcipher_request_set_callback(&areq->cra_u.skcipher_req,
123133
CRYPTO_TFM_REQ_MAY_SLEEP,
124134
af_alg_async_cb, areq);
@@ -127,12 +137,8 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
127137
crypto_skcipher_decrypt(&areq->cra_u.skcipher_req);
128138

129139
/* AIO operation in progress */
130-
if (err == -EINPROGRESS || err == -EBUSY) {
131-
/* Remember output size that will be generated. */
132-
areq->outlen = len;
133-
140+
if (err == -EINPROGRESS || err == -EBUSY)
134141
return -EIOCBQUEUED;
135-
}
136142

137143
sock_put(sk);
138144
} else {

crypto/mcryptd.c

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ static int mcryptd_init_queue(struct mcryptd_queue *queue,
8181
pr_debug("cpu_queue #%d %p\n", cpu, queue->cpu_queue);
8282
crypto_init_queue(&cpu_queue->queue, max_cpu_qlen);
8383
INIT_WORK(&cpu_queue->work, mcryptd_queue_worker);
84+
spin_lock_init(&cpu_queue->q_lock);
8485
}
8586
return 0;
8687
}
@@ -104,15 +105,16 @@ static int mcryptd_enqueue_request(struct mcryptd_queue *queue,
104105
int cpu, err;
105106
struct mcryptd_cpu_queue *cpu_queue;
106107

107-
cpu = get_cpu();
108-
cpu_queue = this_cpu_ptr(queue->cpu_queue);
109-
rctx->tag.cpu = cpu;
108+
cpu_queue = raw_cpu_ptr(queue->cpu_queue);
109+
spin_lock(&cpu_queue->q_lock);
110+
cpu = smp_processor_id();
111+
rctx->tag.cpu = smp_processor_id();
110112

111113
err = crypto_enqueue_request(&cpu_queue->queue, request);
112114
pr_debug("enqueue request: cpu %d cpu_queue %p request %p\n",
113115
cpu, cpu_queue, request);
116+
spin_unlock(&cpu_queue->q_lock);
114117
queue_work_on(cpu, kcrypto_wq, &cpu_queue->work);
115-
put_cpu();
116118

117119
return err;
118120
}
@@ -161,16 +163,11 @@ static void mcryptd_queue_worker(struct work_struct *work)
161163
cpu_queue = container_of(work, struct mcryptd_cpu_queue, work);
162164
i = 0;
163165
while (i < MCRYPTD_BATCH || single_task_running()) {
164-
/*
165-
* preempt_disable/enable is used to prevent
166-
* being preempted by mcryptd_enqueue_request()
167-
*/
168-
local_bh_disable();
169-
preempt_disable();
166+
167+
spin_lock_bh(&cpu_queue->q_lock);
170168
backlog = crypto_get_backlog(&cpu_queue->queue);
171169
req = crypto_dequeue_request(&cpu_queue->queue);
172-
preempt_enable();
173-
local_bh_enable();
170+
spin_unlock_bh(&cpu_queue->q_lock);
174171

175172
if (!req) {
176173
mcryptd_opportunistic_flush();
@@ -185,7 +182,7 @@ static void mcryptd_queue_worker(struct work_struct *work)
185182
++i;
186183
}
187184
if (cpu_queue->queue.qlen)
188-
queue_work(kcrypto_wq, &cpu_queue->work);
185+
queue_work_on(smp_processor_id(), kcrypto_wq, &cpu_queue->work);
189186
}
190187

191188
void mcryptd_flusher(struct work_struct *__work)

crypto/skcipher.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -449,16 +449,15 @@ static int skcipher_walk_skcipher(struct skcipher_walk *walk,
449449

450450
walk->total = req->cryptlen;
451451
walk->nbytes = 0;
452+
walk->iv = req->iv;
453+
walk->oiv = req->iv;
452454

453455
if (unlikely(!walk->total))
454456
return 0;
455457

456458
scatterwalk_start(&walk->in, req->src);
457459
scatterwalk_start(&walk->out, req->dst);
458460

459-
walk->iv = req->iv;
460-
walk->oiv = req->iv;
461-
462461
walk->flags &= ~SKCIPHER_WALK_SLEEP;
463462
walk->flags |= req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
464463
SKCIPHER_WALK_SLEEP : 0;
@@ -510,6 +509,8 @@ static int skcipher_walk_aead_common(struct skcipher_walk *walk,
510509
int err;
511510

512511
walk->nbytes = 0;
512+
walk->iv = req->iv;
513+
walk->oiv = req->iv;
513514

514515
if (unlikely(!walk->total))
515516
return 0;
@@ -525,9 +526,6 @@ static int skcipher_walk_aead_common(struct skcipher_walk *walk,
525526
scatterwalk_done(&walk->in, 0, walk->total);
526527
scatterwalk_done(&walk->out, 0, walk->total);
527528

528-
walk->iv = req->iv;
529-
walk->oiv = req->iv;
530-
531529
if (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP)
532530
walk->flags |= SKCIPHER_WALK_SLEEP;
533531
else

include/crypto/mcryptd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ static inline struct mcryptd_ahash *__mcryptd_ahash_cast(
2727

2828
struct mcryptd_cpu_queue {
2929
struct crypto_queue queue;
30+
spinlock_t q_lock;
3031
struct work_struct work;
3132
};
3233

0 commit comments

Comments
 (0)