summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2023-07-04 16:56:24 +0100
committerHerbert Xu <herbert@gondor.apana.org.au>2023-07-05 16:14:24 +0800
commitd3dccb0a487d065ce097e565d9ca8ae85d892a55 (patch)
tree1471b399a51ba40f733abc7d2c818bd3bc8fa5b5
parent5d95ff84e62be914b4a4dabfa814e4096b05b1b0 (diff)
crypto: af_alg - Fix merging of written data into spliced pages
af_alg_sendmsg() takes data-to-be-copied that's provided by write(), send(), sendmsg() and similar into pages that it allocates and will merge new data into the last page in the list, based on the value of ctx->merge. Now that af_alg_sendmsg() accepts MSG_SPLICE_PAGES, it adds spliced pages directly into the list and then incorrectly appends data to them if there's space left because ctx->merge says that it can. This was cleared by af_alg_sendpage(), but that got lost. Fix this by skipping the merge if MSG_SPLICE_PAGES is specified and clearing ctx->merge after MSG_SPLICE_PAGES has added stuff to the list. Fixes: bf63e250c4b1 ("crypto: af_alg: Support MSG_SPLICE_PAGES") Reported-by: Ondrej Mosnáček <omosnacek@gmail.com> Link: https://lore.kernel.org/r/CAAUqJDvFuvms55Td1c=XKv6epfRnnP78438nZQ-JKyuCptGBiQ@mail.gmail.com/ Signed-off-by: David Howells <dhowells@redhat.com> cc: Herbert Xu <herbert@gondor.apana.org.au> cc: Paolo Abeni <pabeni@redhat.com> cc: "David S. Miller" <davem@davemloft.net> cc: Eric Dumazet <edumazet@google.com> cc: Jakub Kicinski <kuba@kernel.org> cc: linux-crypto@vger.kernel.org cc: netdev@vger.kernel.org Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/af_alg.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 6218c773d71c..06b15b9f661c 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -992,7 +992,7 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
ssize_t plen;
/* use the existing memory in an allocated page */
- if (ctx->merge) {
+ if (ctx->merge && !(msg->msg_flags & MSG_SPLICE_PAGES)) {
sgl = list_entry(ctx->tsgl_list.prev,
struct af_alg_tsgl, list);
sg = sgl->sg + sgl->cur - 1;
@@ -1054,6 +1054,7 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
ctx->used += plen;
copied += plen;
size -= plen;
+ ctx->merge = 0;
} else {
do {
struct page *pg;
@@ -1085,12 +1086,12 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
size -= plen;
sgl->cur++;
} while (len && sgl->cur < MAX_SGL_ENTS);
+
+ ctx->merge = plen & (PAGE_SIZE - 1);
}
if (!size)
sg_mark_end(sg + sgl->cur - 1);
-
- ctx->merge = plen & (PAGE_SIZE - 1);
}
err = 0;