Commit c1abe6f5 authored by David Howells's avatar David Howells Committed by Paolo Abeni

crypto: af_alg: Use extract_iter_to_sg() to create scatterlists

Use extract_iter_to_sg() to decant the destination iterator into a
scatterlist in af_alg_get_rsgl().  af_alg_make_sg() can then be removed.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
cc: Herbert Xu <herbert@gondor.apana.org.au>
cc: "David S. Miller" <davem@davemloft.net>
cc: Eric Dumazet <edumazet@google.com>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Jens Axboe <axboe@kernel.dk>
cc: Matthew Wilcox <willy@infradead.org>
cc: linux-crypto@vger.kernel.org
cc: netdev@vger.kernel.org
Acked-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent f9e7a5fa
...@@ -531,45 +531,11 @@ static const struct net_proto_family alg_family = { ...@@ -531,45 +531,11 @@ static const struct net_proto_family alg_family = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
int af_alg_make_sg(struct af_alg_sgl *sgl, struct iov_iter *iter, int len)
{
struct page **pages = sgl->pages;
size_t off;
ssize_t n;
int npages, i;
n = iov_iter_extract_pages(iter, &pages, len, ALG_MAX_PAGES, 0, &off);
if (n < 0)
return n;
sgl->need_unpin = iov_iter_extract_will_pin(iter);
npages = DIV_ROUND_UP(off + n, PAGE_SIZE);
if (WARN_ON(npages == 0))
return -EINVAL;
/* Add one extra for linking */
sg_init_table(sgl->sg, npages + 1);
for (i = 0, len = n; i < npages; i++) {
int plen = min_t(int, len, PAGE_SIZE - off);
sg_set_page(sgl->sg + i, sgl->pages[i], plen, off);
off = 0;
len -= plen;
}
sg_mark_end(sgl->sg + npages - 1);
sgl->npages = npages;
return n;
}
EXPORT_SYMBOL_GPL(af_alg_make_sg);
static void af_alg_link_sg(struct af_alg_sgl *sgl_prev, static void af_alg_link_sg(struct af_alg_sgl *sgl_prev,
struct af_alg_sgl *sgl_new) struct af_alg_sgl *sgl_new)
{ {
sg_unmark_end(sgl_prev->sg + sgl_prev->npages - 1); sg_unmark_end(sgl_prev->sgt.sgl + sgl_prev->sgt.nents - 1);
sg_chain(sgl_prev->sg, sgl_prev->npages + 1, sgl_new->sg); sg_chain(sgl_prev->sgt.sgl, sgl_prev->sgt.nents + 1, sgl_new->sgt.sgl);
} }
void af_alg_free_sg(struct af_alg_sgl *sgl) void af_alg_free_sg(struct af_alg_sgl *sgl)
...@@ -577,8 +543,8 @@ void af_alg_free_sg(struct af_alg_sgl *sgl) ...@@ -577,8 +543,8 @@ void af_alg_free_sg(struct af_alg_sgl *sgl)
int i; int i;
if (sgl->need_unpin) if (sgl->need_unpin)
for (i = 0; i < sgl->npages; i++) for (i = 0; i < sgl->sgt.nents; i++)
unpin_user_page(sgl->pages[i]); unpin_user_page(sg_page(&sgl->sgt.sgl[i]));
} }
EXPORT_SYMBOL_GPL(af_alg_free_sg); EXPORT_SYMBOL_GPL(af_alg_free_sg);
...@@ -1292,8 +1258,8 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags, ...@@ -1292,8 +1258,8 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
while (maxsize > len && msg_data_left(msg)) { while (maxsize > len && msg_data_left(msg)) {
struct af_alg_rsgl *rsgl; struct af_alg_rsgl *rsgl;
ssize_t err;
size_t seglen; size_t seglen;
int err;
/* limit the amount of readable buffers */ /* limit the amount of readable buffers */
if (!af_alg_readable(sk)) if (!af_alg_readable(sk))
...@@ -1310,16 +1276,23 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags, ...@@ -1310,16 +1276,23 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
return -ENOMEM; return -ENOMEM;
} }
rsgl->sgl.npages = 0; rsgl->sgl.sgt.sgl = rsgl->sgl.sgl;
rsgl->sgl.sgt.nents = 0;
rsgl->sgl.sgt.orig_nents = 0;
list_add_tail(&rsgl->list, &areq->rsgl_list); list_add_tail(&rsgl->list, &areq->rsgl_list);
/* make one iovec available as scatterlist */ sg_init_table(rsgl->sgl.sgt.sgl, ALG_MAX_PAGES);
err = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, seglen); err = extract_iter_to_sg(&msg->msg_iter, seglen, &rsgl->sgl.sgt,
ALG_MAX_PAGES, 0);
if (err < 0) { if (err < 0) {
rsgl->sg_num_bytes = 0; rsgl->sg_num_bytes = 0;
return err; return err;
} }
sg_mark_end(rsgl->sgl.sgt.sgl + rsgl->sgl.sgt.nents - 1);
rsgl->sgl.need_unpin =
iov_iter_extract_will_pin(&msg->msg_iter);
/* chain the new scatterlist with previous one */ /* chain the new scatterlist with previous one */
if (areq->last_rsgl) if (areq->last_rsgl)
af_alg_link_sg(&areq->last_rsgl->sgl, &rsgl->sgl); af_alg_link_sg(&areq->last_rsgl->sgl, &rsgl->sgl);
......
...@@ -210,7 +210,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, ...@@ -210,7 +210,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
*/ */
/* Use the RX SGL as source (and destination) for crypto op. */ /* Use the RX SGL as source (and destination) for crypto op. */
rsgl_src = areq->first_rsgl.sgl.sg; rsgl_src = areq->first_rsgl.sgl.sgt.sgl;
if (ctx->enc) { if (ctx->enc) {
/* /*
...@@ -224,7 +224,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, ...@@ -224,7 +224,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
* RX SGL: AAD || PT || Tag * RX SGL: AAD || PT || Tag
*/ */
err = crypto_aead_copy_sgl(null_tfm, tsgl_src, err = crypto_aead_copy_sgl(null_tfm, tsgl_src,
areq->first_rsgl.sgl.sg, processed); areq->first_rsgl.sgl.sgt.sgl,
processed);
if (err) if (err)
goto free; goto free;
af_alg_pull_tsgl(sk, processed, NULL, 0); af_alg_pull_tsgl(sk, processed, NULL, 0);
...@@ -242,7 +243,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, ...@@ -242,7 +243,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
/* Copy AAD || CT to RX SGL buffer for in-place operation. */ /* Copy AAD || CT to RX SGL buffer for in-place operation. */
err = crypto_aead_copy_sgl(null_tfm, tsgl_src, err = crypto_aead_copy_sgl(null_tfm, tsgl_src,
areq->first_rsgl.sgl.sg, outlen); areq->first_rsgl.sgl.sgt.sgl,
outlen);
if (err) if (err)
goto free; goto free;
...@@ -267,10 +269,10 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, ...@@ -267,10 +269,10 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
if (usedpages) { if (usedpages) {
/* RX SGL present */ /* RX SGL present */
struct af_alg_sgl *sgl_prev = &areq->last_rsgl->sgl; struct af_alg_sgl *sgl_prev = &areq->last_rsgl->sgl;
struct scatterlist *sg = sgl_prev->sgt.sgl;
sg_unmark_end(sgl_prev->sg + sgl_prev->npages - 1); sg_unmark_end(sg + sgl_prev->sgt.nents - 1);
sg_chain(sgl_prev->sg, sgl_prev->npages + 1, sg_chain(sg, sgl_prev->sgt.nents + 1, areq->tsgl);
areq->tsgl);
} else } else
/* no RX SGL present (e.g. authentication only) */ /* no RX SGL present (e.g. authentication only) */
rsgl_src = areq->tsgl; rsgl_src = areq->tsgl;
...@@ -278,7 +280,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, ...@@ -278,7 +280,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
/* Initialize the crypto operation */ /* Initialize the crypto operation */
aead_request_set_crypt(&areq->cra_u.aead_req, rsgl_src, aead_request_set_crypt(&areq->cra_u.aead_req, rsgl_src,
areq->first_rsgl.sgl.sg, used, ctx->iv); areq->first_rsgl.sgl.sgt.sgl, used, ctx->iv);
aead_request_set_ad(&areq->cra_u.aead_req, ctx->aead_assoclen); aead_request_set_ad(&areq->cra_u.aead_req, ctx->aead_assoclen);
aead_request_set_tfm(&areq->cra_u.aead_req, tfm); aead_request_set_tfm(&areq->cra_u.aead_req, tfm);
......
...@@ -91,13 +91,21 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg, ...@@ -91,13 +91,21 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
if (len > limit) if (len > limit)
len = limit; len = limit;
len = af_alg_make_sg(&ctx->sgl, &msg->msg_iter, len); ctx->sgl.sgt.sgl = ctx->sgl.sgl;
ctx->sgl.sgt.nents = 0;
ctx->sgl.sgt.orig_nents = 0;
len = extract_iter_to_sg(&msg->msg_iter, len, &ctx->sgl.sgt,
ALG_MAX_PAGES, 0);
if (len < 0) { if (len < 0) {
err = copied ? 0 : len; err = copied ? 0 : len;
goto unlock; goto unlock;
} }
sg_mark_end(ctx->sgl.sgt.sgl + ctx->sgl.sgt.nents);
ctx->sgl.need_unpin = iov_iter_extract_will_pin(&msg->msg_iter);
ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, NULL, len); ahash_request_set_crypt(&ctx->req, ctx->sgl.sgt.sgl, NULL, len);
err = crypto_wait_req(crypto_ahash_update(&ctx->req), err = crypto_wait_req(crypto_ahash_update(&ctx->req),
&ctx->wait); &ctx->wait);
...@@ -141,8 +149,8 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page, ...@@ -141,8 +149,8 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page,
flags |= MSG_MORE; flags |= MSG_MORE;
lock_sock(sk); lock_sock(sk);
sg_init_table(ctx->sgl.sg, 1); sg_init_table(ctx->sgl.sgl, 1);
sg_set_page(ctx->sgl.sg, page, size, offset); sg_set_page(ctx->sgl.sgl, page, size, offset);
if (!(flags & MSG_MORE)) { if (!(flags & MSG_MORE)) {
err = hash_alloc_result(sk, ctx); err = hash_alloc_result(sk, ctx);
...@@ -151,7 +159,7 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page, ...@@ -151,7 +159,7 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page,
} else if (!ctx->more) } else if (!ctx->more)
hash_free_result(sk, ctx); hash_free_result(sk, ctx);
ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, ctx->result, size); ahash_request_set_crypt(&ctx->req, ctx->sgl.sgl, ctx->result, size);
if (!(flags & MSG_MORE)) { if (!(flags & MSG_MORE)) {
if (ctx->more) if (ctx->more)
......
...@@ -105,7 +105,7 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg, ...@@ -105,7 +105,7 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
/* Initialize the crypto operation */ /* Initialize the crypto operation */
skcipher_request_set_tfm(&areq->cra_u.skcipher_req, tfm); skcipher_request_set_tfm(&areq->cra_u.skcipher_req, tfm);
skcipher_request_set_crypt(&areq->cra_u.skcipher_req, areq->tsgl, skcipher_request_set_crypt(&areq->cra_u.skcipher_req, areq->tsgl,
areq->first_rsgl.sgl.sg, len, ctx->iv); areq->first_rsgl.sgl.sgt.sgl, len, ctx->iv);
if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) { if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
/* AIO operation */ /* AIO operation */
......
...@@ -56,9 +56,8 @@ struct af_alg_type { ...@@ -56,9 +56,8 @@ struct af_alg_type {
}; };
struct af_alg_sgl { struct af_alg_sgl {
struct scatterlist sg[ALG_MAX_PAGES + 1]; struct sg_table sgt;
struct page *pages[ALG_MAX_PAGES]; struct scatterlist sgl[ALG_MAX_PAGES + 1];
unsigned int npages;
bool need_unpin; bool need_unpin;
}; };
...@@ -164,7 +163,6 @@ int af_alg_release(struct socket *sock); ...@@ -164,7 +163,6 @@ int af_alg_release(struct socket *sock);
void af_alg_release_parent(struct sock *sk); void af_alg_release_parent(struct sock *sk);
int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern); int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern);
int af_alg_make_sg(struct af_alg_sgl *sgl, struct iov_iter *iter, int len);
void af_alg_free_sg(struct af_alg_sgl *sgl); void af_alg_free_sg(struct af_alg_sgl *sgl);
static inline struct alg_sock *alg_sk(struct sock *sk) static inline struct alg_sock *alg_sk(struct sock *sk)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment