The space allocated to areq is not sufficient to access the member __ctx of struct skcipher_request, as the space occupied by struct arc4_ctx for reading is 1032 bytes, while the requested memory size in skcipher_recvmsg() is: sizeof(struct af_alg_async_req) + crypto_skcipher_reqsize(tfm) = 736 bytes, which does not include the memory required for __ctx of struct skcipher_request. Reported-by: syzbot+8ffb0839a24e9c6bfa76@xxxxxxxxxxxxxxxxxxxxxxxxx Signed-off-by: Edward Adam Davis <eadavis@xxxxxx> --- crypto/algif_skcipher.c | 10 +++++++--- crypto/skcipher.c | 1 - include/crypto/internal/skcipher.h | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index 02cea2149504..b69d361b5515 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -33,6 +33,7 @@ #include <linux/module.h> #include <linux/net.h> #include <net/sock.h> +#include <crypto/internal/skcipher.h> static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) @@ -102,11 +103,12 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg, struct alg_sock *pask = alg_sk(psk); struct af_alg_ctx *ctx = ask->private; struct crypto_skcipher *tfm = pask->private; + struct skcipher_alg *alg = crypto_skcipher_alg(tfm); unsigned int bs = crypto_skcipher_chunksize(tfm); struct af_alg_async_req *areq; unsigned cflags = 0; int err = 0; - size_t len = 0; + size_t len = 0, aqlen; if (!ctx->init || (ctx->more && ctx->used < bs)) { err = af_alg_wait_for_data(sk, flags, bs); @@ -115,8 +117,10 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg, } /* Allocate cipher request for current operation. */ - areq = af_alg_alloc_areq(sk, sizeof(struct af_alg_async_req) + - crypto_skcipher_reqsize(tfm)); + aqlen = sizeof(struct af_alg_async_req) + crypto_skcipher_reqsize(tfm); + if (alg->co.base.cra_type != &crypto_skcipher_type) + aqlen += 1032; + areq = af_alg_alloc_areq(sk, aqlen); if (IS_ERR(areq)) return PTR_ERR(areq); diff --git a/crypto/skcipher.c b/crypto/skcipher.c index bc70e159d27d..0ae4a05a5aa7 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -44,7 +44,6 @@ struct skcipher_walk_buffer { u8 buffer[]; }; -static const struct crypto_type crypto_skcipher_type; static int skcipher_walk_next(struct skcipher_walk *walk); diff --git a/include/crypto/internal/skcipher.h b/include/crypto/internal/skcipher.h index 7ae42afdcf3e..3c05872652f2 100644 --- a/include/crypto/internal/skcipher.h +++ b/include/crypto/internal/skcipher.h @@ -24,6 +24,7 @@ struct aead_request; struct rtattr; +static const struct crypto_type crypto_skcipher_type; struct skcipher_instance { void (*free)(struct skcipher_instance *inst); -- 2.43.0