From: Eric Biggers <ebiggers@google.com> stable inclusion from stable-v5.10.254 commit 488f9c3ab90e333ad5185d9236c1e10898acf041 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/14174 CVE: CVE-2026-31431 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- commit f2804d0eee8ddd57aa79d0b82872b74c21e1b69b upstream. For copying data between two scatterlists, just use memcpy_sglist() instead of the so-called "null skcipher". This is much simpler. Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Eric Biggers <ebiggers@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Conflicts: crypto/Kconfig crypto/algif_aead.c [Context conflicts] Signed-off-by: GONG Ruiqi <gongruiqi1@huawei.com> --- crypto/Kconfig | 1 - crypto/algif_aead.c | 98 ++++++++------------------------------------- 2 files changed, 17 insertions(+), 82 deletions(-) diff --git a/crypto/Kconfig b/crypto/Kconfig index 0ec4767a8856..bcd6ac3d1993 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1794,7 +1794,6 @@ config CRYPTO_USER_API_AEAD depends on NET select CRYPTO_AEAD select CRYPTO_BLKCIPHER - select CRYPTO_NULL select CRYPTO_USER_API help This option enables the user-spaces interface for AEAD diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index 43a861a79209..c4a0b12fa91d 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -31,7 +31,6 @@ #include <crypto/scatterwalk.h> #include <crypto/if_alg.h> #include <crypto/skcipher.h> -#include <crypto/null.h> #include <linux/init.h> #include <linux/list.h> #include <linux/kernel.h> @@ -40,19 +39,13 @@ #include <linux/net.h> #include <net/sock.h> -struct aead_tfm { - struct crypto_aead *aead; - struct crypto_skcipher *null_tfm; -}; - static inline bool aead_sufficient_data(struct sock *sk) { struct alg_sock *ask = alg_sk(sk); struct sock *psk = ask->parent; struct alg_sock *pask = alg_sk(psk); struct af_alg_ctx *ctx = ask->private; - struct aead_tfm *aeadc = pask->private; - struct crypto_aead *tfm = aeadc->aead; + struct crypto_aead *tfm = pask->private; unsigned int as = crypto_aead_authsize(tfm); /* @@ -68,27 +61,12 @@ static int aead_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) struct alg_sock *ask = alg_sk(sk); struct sock *psk = ask->parent; struct alg_sock *pask = alg_sk(psk); - struct aead_tfm *aeadc = pask->private; - struct crypto_aead *tfm = aeadc->aead; + struct crypto_aead *tfm = pask->private; unsigned int ivsize = crypto_aead_ivsize(tfm); return af_alg_sendmsg(sock, msg, size, ivsize); } -static int crypto_aead_copy_sgl(struct crypto_skcipher *null_tfm, - struct scatterlist *src, - struct scatterlist *dst, unsigned int len) -{ - SKCIPHER_REQUEST_ON_STACK(skreq, null_tfm); - - skcipher_request_set_tfm(skreq, null_tfm); - skcipher_request_set_callback(skreq, CRYPTO_TFM_REQ_MAY_BACKLOG, - NULL, NULL); - skcipher_request_set_crypt(skreq, src, dst, len, NULL); - - return crypto_skcipher_encrypt(skreq); -} - static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, int flags) { @@ -97,9 +75,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, struct sock *psk = ask->parent; struct alg_sock *pask = alg_sk(psk); struct af_alg_ctx *ctx = ask->private; - struct aead_tfm *aeadc = pask->private; - struct crypto_aead *tfm = aeadc->aead; - struct crypto_skcipher *null_tfm = aeadc->null_tfm; + struct crypto_aead *tfm = pask->private; unsigned int i, as = crypto_aead_authsize(tfm); struct af_alg_async_req *areq; struct af_alg_tsgl *tsgl, *tmp; @@ -227,10 +203,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, * v v * RX SGL: AAD || PT || Tag */ - err = crypto_aead_copy_sgl(null_tfm, tsgl_src, - areq->first_rsgl.sgl.sg, processed); - if (err) - goto free; + memcpy_sglist(areq->first_rsgl.sgl.sg, tsgl_src, processed); af_alg_pull_tsgl(sk, processed, NULL, 0); } else { /* @@ -244,11 +217,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, * RX SGL: AAD || CT ----+ */ - /* Copy AAD || CT to RX SGL buffer for in-place operation. */ - err = crypto_aead_copy_sgl(null_tfm, tsgl_src, - areq->first_rsgl.sgl.sg, outlen); - if (err) - goto free; + /* Copy AAD || CT to RX SGL buffer for in-place operation. */ + memcpy_sglist(areq->first_rsgl.sgl.sg, tsgl_src, outlen); /* Create TX SGL for tag and chain it to RX SGL. */ areq->tsgl_entries = af_alg_count_tsgl(sk, processed, @@ -383,7 +353,7 @@ static int aead_check_key(struct socket *sock) int err = 0; struct sock *psk; struct alg_sock *pask; - struct aead_tfm *tfm; + struct crypto_aead *tfm; struct sock *sk = sock->sk; struct alg_sock *ask = alg_sk(sk); @@ -397,7 +367,7 @@ static int aead_check_key(struct socket *sock) err = -ENOKEY; lock_sock_nested(psk, SINGLE_DEPTH_NESTING); - if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY) + if (crypto_aead_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) goto unlock; if (!pask->refcnt++) @@ -476,54 +446,22 @@ static struct proto_ops algif_aead_ops_nokey = { static void *aead_bind(const char *name, u32 type, u32 mask) { - struct aead_tfm *tfm; - struct crypto_aead *aead; - struct crypto_skcipher *null_tfm; - - tfm = kzalloc(sizeof(*tfm), GFP_KERNEL); - if (!tfm) - return ERR_PTR(-ENOMEM); - - aead = crypto_alloc_aead(name, type, mask); - if (IS_ERR(aead)) { - kfree(tfm); - return ERR_CAST(aead); - } - - null_tfm = crypto_get_default_null_skcipher(); - if (IS_ERR(null_tfm)) { - crypto_free_aead(aead); - kfree(tfm); - return ERR_CAST(null_tfm); - } - - tfm->aead = aead; - tfm->null_tfm = null_tfm; - - return tfm; + return crypto_alloc_aead(name, type, mask); } static void aead_release(void *private) { - struct aead_tfm *tfm = private; - - crypto_free_aead(tfm->aead); - crypto_put_default_null_skcipher(); - kfree(tfm); + crypto_free_aead(private); } static int aead_setauthsize(void *private, unsigned int authsize) { - struct aead_tfm *tfm = private; - - return crypto_aead_setauthsize(tfm->aead, authsize); + return crypto_aead_setauthsize(private, authsize); } static int aead_setkey(void *private, const u8 *key, unsigned int keylen) { - struct aead_tfm *tfm = private; - - return crypto_aead_setkey(tfm->aead, key, keylen); + return crypto_aead_setkey(private, key, keylen); } static void aead_sock_destruct(struct sock *sk) @@ -532,8 +470,7 @@ static void aead_sock_destruct(struct sock *sk) struct af_alg_ctx *ctx = ask->private; struct sock *psk = ask->parent; struct alg_sock *pask = alg_sk(psk); - struct aead_tfm *aeadc = pask->private; - struct crypto_aead *tfm = aeadc->aead; + struct crypto_aead *tfm = pask->private; unsigned int ivlen = crypto_aead_ivsize(tfm); af_alg_pull_tsgl(sk, ctx->used, NULL, 0); @@ -546,10 +483,9 @@ static int aead_accept_parent_nokey(void *private, struct sock *sk) { struct af_alg_ctx *ctx; struct alg_sock *ask = alg_sk(sk); - struct aead_tfm *tfm = private; - struct crypto_aead *aead = tfm->aead; + struct crypto_aead *tfm = private; unsigned int len = sizeof(*ctx); - unsigned int ivlen = crypto_aead_ivsize(aead); + unsigned int ivlen = crypto_aead_ivsize(tfm); ctx = sock_kmalloc(sk, len, GFP_KERNEL); if (!ctx) @@ -576,9 +512,9 @@ static int aead_accept_parent_nokey(void *private, struct sock *sk) static int aead_accept_parent(void *private, struct sock *sk) { - struct aead_tfm *tfm = private; + struct crypto_aead *tfm = private; - if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY) + if (crypto_aead_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) return -ENOKEY; return aead_accept_parent_nokey(private, sk); -- 2.43.0