aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-11-28 16:39:25 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2015-02-04 01:34:15 -0500
commit1d10eb2f156f5fc83cf6c7ce60441592e66eadb3 (patch)
treeb330398099f3da04395326250a747399495dc906 /crypto
parent31a25fae85956e3a9c778141d29e5e803fb0b124 (diff)
crypto: switch af_alg_make_sg() to iov_iter
With that, all ->sendmsg() instances are converted to iov_iter primitives and are agnostic wrt the kind of iov_iter they are working with. So's the last remaining ->recvmsg() instance that wasn't kind-agnostic yet. All ->sendmsg() and ->recvmsg() advance ->msg_iter by the amount actually copied and none of them modifies the underlying iovec, etc. Cc: linux-crypto@vger.kernel.org Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/af_alg.c40
-rw-r--r--crypto/algif_hash.c45
-rw-r--r--crypto/algif_skcipher.c74
3 files changed, 61 insertions, 98 deletions
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 4665b79c729a..eb78fe8a60c8 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -338,49 +338,31 @@ static const struct net_proto_family alg_family = {
338 .owner = THIS_MODULE, 338 .owner = THIS_MODULE,
339}; 339};
340 340
341int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len, 341int af_alg_make_sg(struct af_alg_sgl *sgl, struct iov_iter *iter, int len)
342 int write)
343{ 342{
344 unsigned long from = (unsigned long)addr; 343 size_t off;
345 unsigned long npages; 344 ssize_t n;
346 unsigned off; 345 int npages, i;
347 int err;
348 int i;
349
350 err = -EFAULT;
351 if (!access_ok(write ? VERIFY_READ : VERIFY_WRITE, addr, len))
352 goto out;
353
354 off = from & ~PAGE_MASK;
355 npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
356 if (npages > ALG_MAX_PAGES)
357 npages = ALG_MAX_PAGES;
358 346
359 err = get_user_pages_fast(from, npages, write, sgl->pages); 347 n = iov_iter_get_pages(iter, sgl->pages, len, ALG_MAX_PAGES, &off);
360 if (err < 0) 348 if (n < 0)
361 goto out; 349 return n;
362 350
363 npages = err; 351 npages = PAGE_ALIGN(off + n);
364 err = -EINVAL;
365 if (WARN_ON(npages == 0)) 352 if (WARN_ON(npages == 0))
366 goto out; 353 return -EINVAL;
367
368 err = 0;
369 354
370 sg_init_table(sgl->sg, npages); 355 sg_init_table(sgl->sg, npages);
371 356
372 for (i = 0; i < npages; i++) { 357 for (i = 0, len = n; i < npages; i++) {
373 int plen = min_t(int, len, PAGE_SIZE - off); 358 int plen = min_t(int, len, PAGE_SIZE - off);
374 359
375 sg_set_page(sgl->sg + i, sgl->pages[i], plen, off); 360 sg_set_page(sgl->sg + i, sgl->pages[i], plen, off);
376 361
377 off = 0; 362 off = 0;
378 len -= plen; 363 len -= plen;
379 err += plen;
380 } 364 }
381 365 return n;
382out:
383 return err;
384} 366}
385EXPORT_SYMBOL_GPL(af_alg_make_sg); 367EXPORT_SYMBOL_GPL(af_alg_make_sg);
386 368
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
index 01f56eb7816e..01da360bdb55 100644
--- a/crypto/algif_hash.c
+++ b/crypto/algif_hash.c
@@ -41,8 +41,6 @@ static int hash_sendmsg(struct kiocb *unused, struct socket *sock,
41 struct sock *sk = sock->sk; 41 struct sock *sk = sock->sk;
42 struct alg_sock *ask = alg_sk(sk); 42 struct alg_sock *ask = alg_sk(sk);
43 struct hash_ctx *ctx = ask->private; 43 struct hash_ctx *ctx = ask->private;
44 unsigned long iovlen;
45 const struct iovec *iov;
46 long copied = 0; 44 long copied = 0;
47 int err; 45 int err;
48 46
@@ -58,37 +56,28 @@ static int hash_sendmsg(struct kiocb *unused, struct socket *sock,
58 56
59 ctx->more = 0; 57 ctx->more = 0;
60 58
61 for (iov = msg->msg_iter.iov, iovlen = msg->msg_iter.nr_segs; iovlen > 0; 59 while (iov_iter_count(&msg->msg_iter)) {
62 iovlen--, iov++) { 60 int len = iov_iter_count(&msg->msg_iter);
63 unsigned long seglen = iov->iov_len;
64 char __user *from = iov->iov_base;
65 61
66 while (seglen) { 62 if (len > limit)
67 int len = min_t(unsigned long, seglen, limit); 63 len = limit;
68 int newlen;
69 64
70 newlen = af_alg_make_sg(&ctx->sgl, from, len, 0); 65 len = af_alg_make_sg(&ctx->sgl, &msg->msg_iter, len);
71 if (newlen < 0) { 66 if (len < 0) {
72 err = copied ? 0 : newlen; 67 err = copied ? 0 : len;
73 goto unlock; 68 goto unlock;
74 } 69 }
75
76 ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, NULL,
77 newlen);
78
79 err = af_alg_wait_for_completion(
80 crypto_ahash_update(&ctx->req),
81 &ctx->completion);
82 70
83 af_alg_free_sg(&ctx->sgl); 71 ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, NULL, len);
84 72
85 if (err) 73 err = af_alg_wait_for_completion(crypto_ahash_update(&ctx->req),
86 goto unlock; 74 &ctx->completion);
75 af_alg_free_sg(&ctx->sgl);
76 if (err)
77 goto unlock;
87 78
88 seglen -= newlen; 79 copied += len;
89 from += newlen; 80 iov_iter_advance(&msg->msg_iter, len);
90 copied += newlen;
91 }
92 } 81 }
93 82
94 err = 0; 83 err = 0;
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index c12207c8dde9..37110fd68adf 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -426,67 +426,59 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
426 &ctx->req)); 426 &ctx->req));
427 struct skcipher_sg_list *sgl; 427 struct skcipher_sg_list *sgl;
428 struct scatterlist *sg; 428 struct scatterlist *sg;
429 unsigned long iovlen;
430 const struct iovec *iov;
431 int err = -EAGAIN; 429 int err = -EAGAIN;
432 int used; 430 int used;
433 long copied = 0; 431 long copied = 0;
434 432
435 lock_sock(sk); 433 lock_sock(sk);
436 for (iov = msg->msg_iter.iov, iovlen = msg->msg_iter.nr_segs; iovlen > 0; 434 while (iov_iter_count(&msg->msg_iter)) {
437 iovlen--, iov++) { 435 sgl = list_first_entry(&ctx->tsgl,
438 unsigned long seglen = iov->iov_len; 436 struct skcipher_sg_list, list);
439 char __user *from = iov->iov_base; 437 sg = sgl->sg;
440
441 while (seglen) {
442 sgl = list_first_entry(&ctx->tsgl,
443 struct skcipher_sg_list, list);
444 sg = sgl->sg;
445
446 while (!sg->length)
447 sg++;
448
449 if (!ctx->used) {
450 err = skcipher_wait_for_data(sk, flags);
451 if (err)
452 goto unlock;
453 }
454 438
455 used = min_t(unsigned long, ctx->used, seglen); 439 while (!sg->length)
440 sg++;
456 441
457 used = af_alg_make_sg(&ctx->rsgl, from, used, 1); 442 used = ctx->used;
458 err = used; 443 if (!used) {
459 if (err < 0) 444 err = skcipher_wait_for_data(sk, flags);
445 if (err)
460 goto unlock; 446 goto unlock;
447 }
448
449 used = min_t(unsigned long, used, iov_iter_count(&msg->msg_iter));
450
451 used = af_alg_make_sg(&ctx->rsgl, &msg->msg_iter, used);
452 err = used;
453 if (err < 0)
454 goto unlock;
461 455
462 if (ctx->more || used < ctx->used) 456 if (ctx->more || used < ctx->used)
463 used -= used % bs; 457 used -= used % bs;
464 458
465 err = -EINVAL; 459 err = -EINVAL;
466 if (!used) 460 if (!used)
467 goto free; 461 goto free;
468 462
469 ablkcipher_request_set_crypt(&ctx->req, sg, 463 ablkcipher_request_set_crypt(&ctx->req, sg,
470 ctx->rsgl.sg, used, 464 ctx->rsgl.sg, used,
471 ctx->iv); 465 ctx->iv);
472 466
473 err = af_alg_wait_for_completion( 467 err = af_alg_wait_for_completion(
474 ctx->enc ? 468 ctx->enc ?
475 crypto_ablkcipher_encrypt(&ctx->req) : 469 crypto_ablkcipher_encrypt(&ctx->req) :
476 crypto_ablkcipher_decrypt(&ctx->req), 470 crypto_ablkcipher_decrypt(&ctx->req),
477 &ctx->completion); 471 &ctx->completion);
478 472
479free: 473free:
480 af_alg_free_sg(&ctx->rsgl); 474 af_alg_free_sg(&ctx->rsgl);
481 475
482 if (err) 476 if (err)
483 goto unlock; 477 goto unlock;
484 478
485 copied += used; 479 copied += used;
486 from += used; 480 skcipher_pull_sgl(sk, used);
487 seglen -= used; 481 iov_iter_advance(&msg->msg_iter, used);
488 skcipher_pull_sgl(sk, used);
489 }
490 } 482 }
491 483
492 err = 0; 484 err = 0;