diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-11-28 16:39:25 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-02-04 01:34:15 -0500 |
commit | 1d10eb2f156f5fc83cf6c7ce60441592e66eadb3 (patch) | |
tree | b330398099f3da04395326250a747399495dc906 /crypto | |
parent | 31a25fae85956e3a9c778141d29e5e803fb0b124 (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.c | 40 | ||||
-rw-r--r-- | crypto/algif_hash.c | 45 | ||||
-rw-r--r-- | crypto/algif_skcipher.c | 74 |
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 | ||
341 | int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len, | 341 | int 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; | |
382 | out: | ||
383 | return err; | ||
384 | } | 366 | } |
385 | EXPORT_SYMBOL_GPL(af_alg_make_sg); | 367 | EXPORT_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 | ||
479 | free: | 473 | free: |
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; |