Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+37 -35
-6
crypto/af_alg.c
··· 1138 1138 if (!af_alg_readable(sk)) 1139 1139 break; 1140 1140 1141 - if (!ctx->used) { 1142 - err = af_alg_wait_for_data(sk, flags); 1143 - if (err) 1144 - return err; 1145 - } 1146 - 1147 1141 seglen = min_t(size_t, (maxsize - len), 1148 1142 msg_data_left(msg)); 1149 1143
+11 -5
crypto/algif_aead.c
··· 111 111 size_t usedpages = 0; /* [in] RX bufs to be used from user */ 112 112 size_t processed = 0; /* [in] TX bufs to be consumed */ 113 113 114 + if (!ctx->used) { 115 + err = af_alg_wait_for_data(sk, flags); 116 + if (err) 117 + return err; 118 + } 119 + 114 120 /* 115 121 * Data length provided by caller via sendmsg/sendpage that has not 116 122 * yet been processed. ··· 291 285 /* AIO operation */ 292 286 sock_hold(sk); 293 287 areq->iocb = msg->msg_iocb; 288 + 289 + /* Remember output size that will be generated. */ 290 + areq->outlen = outlen; 291 + 294 292 aead_request_set_callback(&areq->cra_u.aead_req, 295 293 CRYPTO_TFM_REQ_MAY_BACKLOG, 296 294 af_alg_async_cb, areq); ··· 302 292 crypto_aead_decrypt(&areq->cra_u.aead_req); 303 293 304 294 /* AIO operation in progress */ 305 - if (err == -EINPROGRESS || err == -EBUSY) { 306 - /* Remember output size that will be generated. */ 307 - areq->outlen = outlen; 308 - 295 + if (err == -EINPROGRESS || err == -EBUSY) 309 296 return -EIOCBQUEUED; 310 - } 311 297 312 298 sock_put(sk); 313 299 } else {
+11 -5
crypto/algif_skcipher.c
··· 72 72 int err = 0; 73 73 size_t len = 0; 74 74 75 + if (!ctx->used) { 76 + err = af_alg_wait_for_data(sk, flags); 77 + if (err) 78 + return err; 79 + } 80 + 75 81 /* Allocate cipher request for current operation. */ 76 82 areq = af_alg_alloc_areq(sk, sizeof(struct af_alg_async_req) + 77 83 crypto_skcipher_reqsize(tfm)); ··· 125 119 /* AIO operation */ 126 120 sock_hold(sk); 127 121 areq->iocb = msg->msg_iocb; 122 + 123 + /* Remember output size that will be generated. */ 124 + areq->outlen = len; 125 + 128 126 skcipher_request_set_callback(&areq->cra_u.skcipher_req, 129 127 CRYPTO_TFM_REQ_MAY_SLEEP, 130 128 af_alg_async_cb, areq); ··· 137 127 crypto_skcipher_decrypt(&areq->cra_u.skcipher_req); 138 128 139 129 /* AIO operation in progress */ 140 - if (err == -EINPROGRESS || err == -EBUSY) { 141 - /* Remember output size that will be generated. */ 142 - areq->outlen = len; 143 - 130 + if (err == -EINPROGRESS || err == -EBUSY) 144 131 return -EIOCBQUEUED; 145 - } 146 132 147 133 sock_put(sk); 148 134 } else {
+10 -13
crypto/mcryptd.c
··· 81 81 pr_debug("cpu_queue #%d %p\n", cpu, queue->cpu_queue); 82 82 crypto_init_queue(&cpu_queue->queue, max_cpu_qlen); 83 83 INIT_WORK(&cpu_queue->work, mcryptd_queue_worker); 84 + spin_lock_init(&cpu_queue->q_lock); 84 85 } 85 86 return 0; 86 87 } ··· 105 104 int cpu, err; 106 105 struct mcryptd_cpu_queue *cpu_queue; 107 106 108 - cpu = get_cpu(); 109 - cpu_queue = this_cpu_ptr(queue->cpu_queue); 110 - rctx->tag.cpu = cpu; 107 + cpu_queue = raw_cpu_ptr(queue->cpu_queue); 108 + spin_lock(&cpu_queue->q_lock); 109 + cpu = smp_processor_id(); 110 + rctx->tag.cpu = smp_processor_id(); 111 111 112 112 err = crypto_enqueue_request(&cpu_queue->queue, request); 113 113 pr_debug("enqueue request: cpu %d cpu_queue %p request %p\n", 114 114 cpu, cpu_queue, request); 115 + spin_unlock(&cpu_queue->q_lock); 115 116 queue_work_on(cpu, kcrypto_wq, &cpu_queue->work); 116 - put_cpu(); 117 117 118 118 return err; 119 119 } ··· 163 161 cpu_queue = container_of(work, struct mcryptd_cpu_queue, work); 164 162 i = 0; 165 163 while (i < MCRYPTD_BATCH || single_task_running()) { 166 - /* 167 - * preempt_disable/enable is used to prevent 168 - * being preempted by mcryptd_enqueue_request() 169 - */ 170 - local_bh_disable(); 171 - preempt_disable(); 164 + 165 + spin_lock_bh(&cpu_queue->q_lock); 172 166 backlog = crypto_get_backlog(&cpu_queue->queue); 173 167 req = crypto_dequeue_request(&cpu_queue->queue); 174 - preempt_enable(); 175 - local_bh_enable(); 168 + spin_unlock_bh(&cpu_queue->q_lock); 176 169 177 170 if (!req) { 178 171 mcryptd_opportunistic_flush(); ··· 182 185 ++i; 183 186 } 184 187 if (cpu_queue->queue.qlen) 185 - queue_work(kcrypto_wq, &cpu_queue->work); 188 + queue_work_on(smp_processor_id(), kcrypto_wq, &cpu_queue->work); 186 189 } 187 190 188 191 void mcryptd_flusher(struct work_struct *__work)
+4 -6
crypto/skcipher.c
··· 449 449 450 450 walk->total = req->cryptlen; 451 451 walk->nbytes = 0; 452 + walk->iv = req->iv; 453 + walk->oiv = req->iv; 452 454 453 455 if (unlikely(!walk->total)) 454 456 return 0; 455 457 456 458 scatterwalk_start(&walk->in, req->src); 457 459 scatterwalk_start(&walk->out, req->dst); 458 - 459 - walk->iv = req->iv; 460 - walk->oiv = req->iv; 461 460 462 461 walk->flags &= ~SKCIPHER_WALK_SLEEP; 463 462 walk->flags |= req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? ··· 509 510 int err; 510 511 511 512 walk->nbytes = 0; 513 + walk->iv = req->iv; 514 + walk->oiv = req->iv; 512 515 513 516 if (unlikely(!walk->total)) 514 517 return 0; ··· 525 524 526 525 scatterwalk_done(&walk->in, 0, walk->total); 527 526 scatterwalk_done(&walk->out, 0, walk->total); 528 - 529 - walk->iv = req->iv; 530 - walk->oiv = req->iv; 531 527 532 528 if (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) 533 529 walk->flags |= SKCIPHER_WALK_SLEEP;
+1
include/crypto/mcryptd.h
··· 27 27 28 28 struct mcryptd_cpu_queue { 29 29 struct crypto_queue queue; 30 + spinlock_t q_lock; 30 31 struct work_struct work; 31 32 }; 32 33