From 5cc29fb809b89e958d133513ca63e3ba4b77835a Mon Sep 17 00:00:00 2001 From: almalinux-bot-kernel Date: Thu, 7 May 2026 05:14:11 +0000 Subject: [PATCH] Import of kernel-6.12.0-124.55.1.el10_1 --- ....52.3.el10 => COPYING-6.12.0-124.55.1.el10 | 0 Makefile.rhelver | 2 +- configs/kernel-6.12.0-ppc64le-debug.config | 13 +-- crypto/Kconfig | 2 + crypto/af_alg.c | 6 +- crypto/algif_aead.c | 94 +++++++++++++++---- crypto/algif_skcipher.c | 5 + crypto/authenc.c | 32 ++++++- crypto/authencesn.c | 57 ++++++++++- crypto/scatterwalk.c | 94 ------------------- drivers/net/bonding/bond_main.c | 2 +- drivers/thunderbolt/switch.c | 9 +- drivers/thunderbolt/tb.h | 2 +- drivers/thunderbolt/usb4.c | 12 +-- fs/nfsd/nfs4xdr.c | 9 +- fs/nfsd/state.h | 17 +++- include/crypto/scatterwalk.h | 31 ------ include/net/act_api.h | 1 + net/sched/act_ct.c | 6 ++ net/sched/cls_api.c | 7 ++ redhat/kernel.changelog-10.1 | 25 +++++ uki-addons.sbat | 4 +- uki.sbat | 4 +- 23 files changed, 250 insertions(+), 184 deletions(-) rename COPYING-6.12.0-124.52.3.el10 => COPYING-6.12.0-124.55.1.el10 (100%) diff --git a/COPYING-6.12.0-124.52.3.el10 b/COPYING-6.12.0-124.55.1.el10 similarity index 100% rename from COPYING-6.12.0-124.52.3.el10 rename to COPYING-6.12.0-124.55.1.el10 diff --git a/Makefile.rhelver b/Makefile.rhelver index 0f30424b66..98ed3cfa06 100644 --- a/Makefile.rhelver +++ b/Makefile.rhelver @@ -12,7 +12,7 @@ RHEL_MINOR = 1 # # Use this spot to avoid future merge conflicts. # Do not trim this comment. -RHEL_RELEASE = 124.52.1 +RHEL_RELEASE = 124.55.1 # # RHEL_REBASE_NUM diff --git a/configs/kernel-6.12.0-ppc64le-debug.config b/configs/kernel-6.12.0-ppc64le-debug.config index 17d546e595..17a463f725 100644 --- a/configs/kernel-6.12.0-ppc64le-debug.config +++ b/configs/kernel-6.12.0-ppc64le-debug.config @@ -500,9 +500,6 @@ CONFIG_PPC_TRANSACTIONAL_MEM=y CONFIG_PPC_UV=y # CONFIG_LD_HEAD_STUB_CATCH is not set CONFIG_MPROFILE_KERNEL=y -CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY=y -CONFIG_PPC_FTRACE_OUT_OF_LINE=y -CONFIG_PPC_FTRACE_OUT_OF_LINE_NUM_RESERVE=32768 CONFIG_HOTPLUG_CPU=y CONFIG_INTERRUPT_SANITIZE_REGISTERS=y CONFIG_PPC_QUEUED_SPINLOCKS=y @@ -725,7 +722,6 @@ CONFIG_FUNCTION_ALIGNMENT_4B=y CONFIG_FUNCTION_ALIGNMENT=4 CONFIG_CC_HAS_MIN_FUNCTION_ALIGNMENT=y CONFIG_CC_HAS_SANE_FUNCTION_ALIGNMENT=y -CONFIG_ARCH_WANTS_PRE_LINK_VMLINUX=y # end of General architecture-dependent options CONFIG_RT_MUTEXES=y @@ -5032,7 +5028,6 @@ CONFIG_HID_KUNIT_TEST=m # # HID-BPF support # -CONFIG_HID_BPF=y # end of HID-BPF support CONFIG_I2C_HID=y @@ -7134,8 +7129,6 @@ CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y -CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y -CONFIG_HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS=y CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y @@ -7156,8 +7149,6 @@ CONFIG_FUNCTION_TRACER=y CONFIG_FUNCTION_GRAPH_TRACER=y CONFIG_DYNAMIC_FTRACE=y CONFIG_DYNAMIC_FTRACE_WITH_REGS=y -CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y -CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS=y CONFIG_DYNAMIC_FTRACE_WITH_ARGS=y CONFIG_FPROBE=y CONFIG_FUNCTION_PROFILER=y @@ -7182,7 +7173,7 @@ CONFIG_BPF_EVENTS=y CONFIG_DYNAMIC_EVENTS=y CONFIG_PROBE_EVENTS=y CONFIG_FTRACE_MCOUNT_RECORD=y -CONFIG_FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY=y +CONFIG_FTRACE_MCOUNT_USE_CC=y CONFIG_TRACING_MAP=y CONFIG_SYNTH_EVENTS=y # CONFIG_USER_EVENTS is not set @@ -7208,8 +7199,6 @@ CONFIG_RV_REACTORS=y CONFIG_RV_REACT_PRINTK=y CONFIG_RV_REACT_PANIC=y # CONFIG_SAMPLES is not set -CONFIG_HAVE_SAMPLE_FTRACE_DIRECT=y -CONFIG_HAVE_SAMPLE_FTRACE_DIRECT_MULTI=y CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y CONFIG_STRICT_DEVMEM=y # CONFIG_IO_STRICT_DEVMEM is not set diff --git a/crypto/Kconfig b/crypto/Kconfig index ebeb18e43d..a779cab668 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -222,6 +222,7 @@ config CRYPTO_AUTHENC select CRYPTO_SKCIPHER select CRYPTO_MANAGER select CRYPTO_HASH + select CRYPTO_NULL help Authenc: Combined mode wrapper for IPsec. @@ -1420,6 +1421,7 @@ config CRYPTO_USER_API_AEAD depends on NET select CRYPTO_AEAD select CRYPTO_SKCIPHER + select CRYPTO_NULL select CRYPTO_USER_API help Enable the userspace interface for AEAD cipher algorithms. diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 937f71259d..4c94448e46 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -623,8 +623,10 @@ static int af_alg_alloc_tsgl(struct sock *sk) sg_init_table(sgl->sg, MAX_SGL_ENTS + 1); sgl->cur = 0; - if (sg) + if (sg) { + sg_unmark_end(sg + MAX_SGL_ENTS - 1); sg_chain(sg, MAX_SGL_ENTS + 1, sgl->sg); + } list_add_tail(&sgl->list, &ctx->tsgl_list); } @@ -1220,6 +1222,8 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags, seglen = min_t(size_t, (maxsize - len), msg_data_left(msg)); + /* Never pin more pages than the remaining RX accounting budget. */ + seglen = min_t(size_t, seglen, af_alg_rcvbuf(sk)); if (list_empty(&areq->rsgl_list)) { rsgl = &areq->first_rsgl; diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index c54693d188..fcf86e5c64 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include #include @@ -34,13 +36,19 @@ #include #include +struct aead_tfm { + struct crypto_aead *aead; + struct crypto_sync_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 crypto_aead *tfm = pask->private; + struct aead_tfm *aeadc = pask->private; + struct crypto_aead *tfm = aeadc->aead; unsigned int as = crypto_aead_authsize(tfm); /* @@ -56,12 +64,27 @@ 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 crypto_aead *tfm = pask->private; + struct aead_tfm *aeadc = pask->private; + struct crypto_aead *tfm = aeadc->aead; unsigned int ivsize = crypto_aead_ivsize(tfm); return af_alg_sendmsg(sock, msg, size, ivsize); } +static int crypto_aead_copy_sgl(struct crypto_sync_skcipher *null_tfm, + struct scatterlist *src, + struct scatterlist *dst, unsigned int len) +{ + SYNC_SKCIPHER_REQUEST_ON_STACK(skreq, null_tfm); + + skcipher_request_set_sync_tfm(skreq, null_tfm); + skcipher_request_set_callback(skreq, CRYPTO_TFM_REQ_MAY_SLEEP, + 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) { @@ -70,7 +93,9 @@ 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 crypto_aead *tfm = pask->private; + struct aead_tfm *aeadc = pask->private; + struct crypto_aead *tfm = aeadc->aead; + struct crypto_sync_skcipher *null_tfm = aeadc->null_tfm; unsigned int as = crypto_aead_authsize(tfm); unsigned int ivsize = crypto_aead_ivsize(tfm); struct af_alg_async_req *areq; @@ -150,7 +175,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, if (usedpages < outlen) { size_t less = outlen - usedpages; - if (used < less) { + if (used < less + (ctx->enc ? 0 : as)) { err = -EINVAL; goto free; } @@ -189,7 +214,10 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, /* Use the RX SGL as source (and destination) for crypto op. */ rsgl_src = areq->first_rsgl.sgl.sgt.sgl; - memcpy_sglist(rsgl_src, tsgl_src, ctx->aead_assoclen); + err = crypto_aead_copy_sgl(null_tfm, tsgl_src, rsgl_src, + ctx->aead_assoclen); + if (err) + goto free; /* Initialize the crypto operation */ aead_request_set_crypt(&areq->cra_u.aead_req, tsgl_src, @@ -292,7 +320,7 @@ static int aead_check_key(struct socket *sock) int err = 0; struct sock *psk; struct alg_sock *pask; - struct crypto_aead *tfm; + struct aead_tfm *tfm; struct sock *sk = sock->sk; struct alg_sock *ask = alg_sk(sk); @@ -306,7 +334,7 @@ static int aead_check_key(struct socket *sock) err = -ENOKEY; lock_sock_nested(psk, SINGLE_DEPTH_NESTING); - if (crypto_aead_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) + if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY) goto unlock; atomic_dec(&pask->nokey_refcnt); @@ -367,22 +395,54 @@ static struct proto_ops algif_aead_ops_nokey = { static void *aead_bind(const char *name, u32 type, u32 mask) { - return crypto_alloc_aead(name, type, mask); + struct aead_tfm *tfm; + struct crypto_aead *aead; + struct crypto_sync_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; } static void aead_release(void *private) { - crypto_free_aead(private); + struct aead_tfm *tfm = private; + + crypto_free_aead(tfm->aead); + crypto_put_default_null_skcipher(); + kfree(tfm); } static int aead_setauthsize(void *private, unsigned int authsize) { - return crypto_aead_setauthsize(private, authsize); + struct aead_tfm *tfm = private; + + return crypto_aead_setauthsize(tfm->aead, authsize); } static int aead_setkey(void *private, const u8 *key, unsigned int keylen) { - return crypto_aead_setkey(private, key, keylen); + struct aead_tfm *tfm = private; + + return crypto_aead_setkey(tfm->aead, key, keylen); } static void aead_sock_destruct(struct sock *sk) @@ -391,7 +451,8 @@ 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 crypto_aead *tfm = pask->private; + struct aead_tfm *aeadc = pask->private; + struct crypto_aead *tfm = aeadc->aead; unsigned int ivlen = crypto_aead_ivsize(tfm); af_alg_pull_tsgl(sk, ctx->used, NULL); @@ -404,9 +465,10 @@ static int aead_accept_parent_nokey(void *private, struct sock *sk) { struct af_alg_ctx *ctx; struct alg_sock *ask = alg_sk(sk); - struct crypto_aead *tfm = private; + struct aead_tfm *tfm = private; + struct crypto_aead *aead = tfm->aead; unsigned int len = sizeof(*ctx); - unsigned int ivlen = crypto_aead_ivsize(tfm); + unsigned int ivlen = crypto_aead_ivsize(aead); ctx = sock_kmalloc(sk, len, GFP_KERNEL); if (!ctx) @@ -433,9 +495,9 @@ static int aead_accept_parent_nokey(void *private, struct sock *sk) static int aead_accept_parent(void *private, struct sock *sk) { - struct crypto_aead *tfm = private; + struct aead_tfm *tfm = private; - if (crypto_aead_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) + if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY) return -ENOKEY; return aead_accept_parent_nokey(private, sk); diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index 82735e51be..ba0a17fd95 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -130,6 +130,11 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg, * full block size buffers. */ if (ctx->more || len < ctx->used) { + if (len < bs) { + err = -EINVAL; + goto free; + } + len -= len % bs; cflags |= CRYPTO_SKCIPHER_REQ_NOTFINAL; } diff --git a/crypto/authenc.c b/crypto/authenc.c index 89fb17ef44..3aaf3ab4e3 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ struct authenc_instance_ctx { struct crypto_authenc_ctx { struct crypto_ahash *auth; struct crypto_skcipher *enc; + struct crypto_sync_skcipher *null; }; struct authenc_request_ctx { @@ -168,6 +170,21 @@ out: authenc_request_complete(areq, err); } +static int crypto_authenc_copy_assoc(struct aead_request *req) +{ + struct crypto_aead *authenc = crypto_aead_reqtfm(req); + struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); + SYNC_SKCIPHER_REQUEST_ON_STACK(skreq, ctx->null); + + skcipher_request_set_sync_tfm(skreq, ctx->null); + skcipher_request_set_callback(skreq, aead_request_flags(req), + NULL, NULL); + skcipher_request_set_crypt(skreq, req->src, req->dst, req->assoclen, + NULL); + + return crypto_skcipher_encrypt(skreq); +} + static int crypto_authenc_encrypt(struct aead_request *req) { struct crypto_aead *authenc = crypto_aead_reqtfm(req); @@ -186,7 +203,10 @@ static int crypto_authenc_encrypt(struct aead_request *req) dst = src; if (req->src != req->dst) { - memcpy_sglist(req->dst, req->src, req->assoclen); + err = crypto_authenc_copy_assoc(req); + if (err) + return err; + dst = scatterwalk_ffwd(areq_ctx->dst, req->dst, req->assoclen); } @@ -283,6 +303,7 @@ static int crypto_authenc_init_tfm(struct crypto_aead *tfm) struct crypto_authenc_ctx *ctx = crypto_aead_ctx(tfm); struct crypto_ahash *auth; struct crypto_skcipher *enc; + struct crypto_sync_skcipher *null; int err; auth = crypto_spawn_ahash(&ictx->auth); @@ -294,8 +315,14 @@ static int crypto_authenc_init_tfm(struct crypto_aead *tfm) if (IS_ERR(enc)) goto err_free_ahash; + null = crypto_get_default_null_skcipher(); + err = PTR_ERR(null); + if (IS_ERR(null)) + goto err_free_skcipher; + ctx->auth = auth; ctx->enc = enc; + ctx->null = null; crypto_aead_set_reqsize( tfm, @@ -309,6 +336,8 @@ static int crypto_authenc_init_tfm(struct crypto_aead *tfm) return 0; +err_free_skcipher: + crypto_free_skcipher(enc); err_free_ahash: crypto_free_ahash(auth); return err; @@ -320,6 +349,7 @@ static void crypto_authenc_exit_tfm(struct crypto_aead *tfm) crypto_free_ahash(ctx->auth); crypto_free_skcipher(ctx->enc); + crypto_put_default_null_skcipher(); } static void crypto_authenc_free(struct aead_instance *inst) diff --git a/crypto/authencesn.c b/crypto/authencesn.c index c01cc30879..8b94a34c6a 100644 --- a/crypto/authencesn.c +++ b/crypto/authencesn.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,7 @@ struct crypto_authenc_esn_ctx { unsigned int reqoff; struct crypto_ahash *auth; struct crypto_skcipher *enc; + struct crypto_sync_skcipher *null; }; struct authenc_esn_request_ctx { @@ -156,6 +158,28 @@ static void crypto_authenc_esn_encrypt_done(void *data, int err) authenc_esn_request_complete(areq, err); } +static int crypto_authenc_esn_copy_sg(struct aead_request *req, + struct scatterlist *src, + struct scatterlist *dst, + unsigned int len) +{ + struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); + struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); + SYNC_SKCIPHER_REQUEST_ON_STACK(skreq, ctx->null); + + skcipher_request_set_sync_tfm(skreq, ctx->null); + skcipher_request_set_callback(skreq, aead_request_flags(req), + NULL, NULL); + skcipher_request_set_crypt(skreq, src, dst, len, NULL); + + return crypto_skcipher_encrypt(skreq); +} + +static int crypto_authenc_esn_copy(struct aead_request *req, unsigned int len) +{ + return crypto_authenc_esn_copy_sg(req, req->src, req->dst, len); +} + static int crypto_authenc_esn_encrypt(struct aead_request *req) { struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); @@ -177,7 +201,10 @@ static int crypto_authenc_esn_encrypt(struct aead_request *req) dst = src; if (req->src != req->dst) { - memcpy_sglist(req->dst, req->src, assoclen); + err = crypto_authenc_esn_copy(req, assoclen); + if (err) + return err; + sg_init_table(areq_ctx->dst, 2); dst = scatterwalk_ffwd(areq_ctx->dst, req->dst, assoclen); } @@ -211,6 +238,7 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req, struct scatterlist *dst = req->dst; u8 *ihash = ohash + crypto_ahash_digestsize(auth); u32 tmp[2]; + int err; if (!authsize) goto decrypt; @@ -220,8 +248,11 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req, scatterwalk_map_and_copy(tmp, dst, 4, 4, 0); scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0); scatterwalk_map_and_copy(tmp, dst, 0, 8, 1); - } else - memcpy_sglist(dst, src, assoclen); + } else { + err = crypto_authenc_esn_copy(req, assoclen); + if (err) + return err; + } if (crypto_memneq(ihash, ohash, authsize)) return -EBADMSG; @@ -289,7 +320,10 @@ static int crypto_authenc_esn_decrypt(struct aead_request *req) src = scatterwalk_ffwd(areq_ctx->src, src, 8); dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4); - memcpy_sglist(dst, src, assoclen + cryptlen - 8); + err = crypto_authenc_esn_copy_sg(req, src, dst, + assoclen + cryptlen - 8); + if (err) + return err; dst = req->dst; } @@ -313,6 +347,7 @@ static int crypto_authenc_esn_init_tfm(struct crypto_aead *tfm) struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(tfm); struct crypto_ahash *auth; struct crypto_skcipher *enc; + struct crypto_sync_skcipher *null; int err; auth = crypto_spawn_ahash(&ictx->auth); @@ -324,8 +359,14 @@ static int crypto_authenc_esn_init_tfm(struct crypto_aead *tfm) if (IS_ERR(enc)) goto err_free_ahash; + null = crypto_get_default_null_skcipher(); + err = PTR_ERR(null); + if (IS_ERR(null)) + goto err_free_skcipher; + ctx->auth = auth; ctx->enc = enc; + ctx->null = null; ctx->reqoff = 2 * crypto_ahash_digestsize(auth); @@ -341,6 +382,8 @@ static int crypto_authenc_esn_init_tfm(struct crypto_aead *tfm) return 0; +err_free_skcipher: + crypto_free_skcipher(enc); err_free_ahash: crypto_free_ahash(auth); return err; @@ -352,6 +395,7 @@ static void crypto_authenc_esn_exit_tfm(struct crypto_aead *tfm) crypto_free_ahash(ctx->auth); crypto_free_skcipher(ctx->enc); + crypto_put_default_null_skcipher(); } static void crypto_authenc_esn_free(struct aead_instance *inst) @@ -390,6 +434,11 @@ static int crypto_authenc_esn_create(struct crypto_template *tmpl, auth = crypto_spawn_ahash_alg(&ctx->auth); auth_base = &auth->base; + if (auth->digestsize > 0 && auth->digestsize < 4) { + err = -EINVAL; + goto err_free_inst; + } + err = crypto_grab_skcipher(&ctx->enc, aead_crypto_instance(inst), crypto_attr_alg_name(tb[2]), 0, mask); if (err) diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c index 9f0b270051..16f6ba896f 100644 --- a/crypto/scatterwalk.c +++ b/crypto/scatterwalk.c @@ -69,100 +69,6 @@ void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg, } EXPORT_SYMBOL_GPL(scatterwalk_map_and_copy); -/** - * memcpy_sglist() - Copy data from one scatterlist to another - * @dst: The destination scatterlist. Can be NULL if @nbytes == 0. - * @src: The source scatterlist. Can be NULL if @nbytes == 0. - * @nbytes: Number of bytes to copy - * - * The scatterlists can describe exactly the same memory, in which case this - * function is a no-op. No other overlaps are supported. - * - * Context: Any context - */ -void memcpy_sglist(struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) -{ - unsigned int src_offset, dst_offset; - - if (unlikely(nbytes == 0)) /* in case src and/or dst is NULL */ - return; - - src_offset = src->offset; - dst_offset = dst->offset; - for (;;) { - /* Compute the length to copy this step. */ - unsigned int len = min3(src->offset + src->length - src_offset, - dst->offset + dst->length - dst_offset, - nbytes); - struct page *src_page = sg_page(src); - struct page *dst_page = sg_page(dst); - const void *src_virt; - void *dst_virt; - - if (IS_ENABLED(CONFIG_HIGHMEM)) { - /* HIGHMEM: we may have to actually map the pages. */ - const unsigned int src_oip = offset_in_page(src_offset); - const unsigned int dst_oip = offset_in_page(dst_offset); - const unsigned int limit = PAGE_SIZE; - - /* Further limit len to not cross a page boundary. */ - len = min3(len, limit - src_oip, limit - dst_oip); - - /* Compute the source and destination pages. */ - src_page += src_offset / PAGE_SIZE; - dst_page += dst_offset / PAGE_SIZE; - - if (src_page != dst_page) { - /* Copy between different pages. */ - memcpy_page(dst_page, dst_oip, - src_page, src_oip, len); - flush_dcache_page(dst_page); - } else if (src_oip != dst_oip) { - /* Copy between different parts of same page. */ - dst_virt = kmap_local_page(dst_page); - memcpy(dst_virt + dst_oip, dst_virt + src_oip, - len); - kunmap_local(dst_virt); - flush_dcache_page(dst_page); - } /* Else, it's the same memory. No action needed. */ - } else { - /* - * !HIGHMEM: no mapping needed. Just work in the linear - * buffer of each sg entry. Note that we can cross page - * boundaries, as they are not significant in this case. - */ - src_virt = page_address(src_page) + src_offset; - dst_virt = page_address(dst_page) + dst_offset; - if (src_virt != dst_virt) { - memcpy(dst_virt, src_virt, len); - if (ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE) - __scatterwalk_flush_dcache_pages( - dst_page, dst_offset, len); - } /* Else, it's the same memory. No action needed. */ - } - nbytes -= len; - if (nbytes == 0) /* No more to copy? */ - break; - - /* - * There's more to copy. Advance the offsets by the length - * copied this step, and advance the sg entries as needed. - */ - src_offset += len; - if (src_offset >= src->offset + src->length) { - src = sg_next(src); - src_offset = src->offset; - } - dst_offset += len; - if (dst_offset >= dst->offset + dst->length) { - dst = sg_next(dst); - dst_offset = dst->offset; - } - } -} -EXPORT_SYMBOL_GPL(memcpy_sglist); - struct scatterlist *scatterwalk_ffwd(struct scatterlist dst[2], struct scatterlist *src, unsigned int len) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index d95ae1c281..13efbed589 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -5393,7 +5393,7 @@ static netdev_tx_t bond_xmit_broadcast(struct sk_buff *skb, if (!(bond_slave_is_up(slave) && slave->link == BOND_LINK_UP)) continue; - if (bond_is_last_slave(bond, slave)) { + if (i + 1 == slaves_count) { skb2 = skb; skb_used = true; } else { diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 6a2116cbb0..e9809fb57c 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -3437,7 +3437,7 @@ void tb_sw_set_unplugged(struct tb_switch *sw) } } -static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags) +static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags, bool runtime) { if (flags) tb_sw_dbg(sw, "enabling wakeup: %#x\n", flags); @@ -3445,7 +3445,7 @@ static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags) tb_sw_dbg(sw, "disabling wakeup\n"); if (tb_switch_is_usb4(sw)) - return usb4_switch_set_wake(sw, flags); + return usb4_switch_set_wake(sw, flags, runtime); return tb_lc_set_wake(sw, flags); } @@ -3521,7 +3521,7 @@ int tb_switch_resume(struct tb_switch *sw, bool runtime) tb_switch_check_wakes(sw); /* Disable wakes */ - tb_switch_set_wake(sw, 0); + tb_switch_set_wake(sw, 0, true); err = tb_switch_tmu_init(sw); if (err) @@ -3599,10 +3599,11 @@ void tb_switch_suspend(struct tb_switch *sw, bool runtime) flags |= TB_WAKE_ON_USB4; flags |= TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE | TB_WAKE_ON_DP; } else if (device_may_wakeup(&sw->dev)) { + flags |= TB_WAKE_ON_CONNECT | TB_WAKE_ON_DISCONNECT; flags |= TB_WAKE_ON_USB4 | TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE; } - tb_switch_set_wake(sw, flags); + tb_switch_set_wake(sw, flags, runtime); if (tb_switch_is_usb4(sw)) usb4_switch_set_sleep(sw); diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index b54147a1ba..d14381eb54 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -1304,7 +1304,7 @@ int usb4_switch_read_uid(struct tb_switch *sw, u64 *uid); int usb4_switch_drom_read(struct tb_switch *sw, unsigned int address, void *buf, size_t size); bool usb4_switch_lane_bonding_possible(struct tb_switch *sw); -int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags); +int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags, bool runtime); int usb4_switch_set_sleep(struct tb_switch *sw); int usb4_switch_nvm_sector_size(struct tb_switch *sw); int usb4_switch_nvm_read(struct tb_switch *sw, unsigned int address, void *buf, diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index e51d01671d..cc05211f26 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -403,12 +403,12 @@ bool usb4_switch_lane_bonding_possible(struct tb_switch *sw) * usb4_switch_set_wake() - Enabled/disable wake * @sw: USB4 router * @flags: Wakeup flags (%0 to disable) + * @runtime: Wake is being programmed during system runtime * * Enables/disables router to wake up from sleep. */ -int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) +int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags, bool runtime) { - struct usb4_port *usb4; struct tb_port *port; u64 route = tb_route(sw); u32 val; @@ -438,13 +438,11 @@ int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) val |= PORT_CS_19_WOU4; } else { bool configured = val & PORT_CS_19_PC; - usb4 = port->usb4; + bool wakeup = runtime || device_may_wakeup(&port->usb4->dev); - if (((flags & TB_WAKE_ON_CONNECT) | - device_may_wakeup(&usb4->dev)) && !configured) + if ((flags & TB_WAKE_ON_CONNECT) && wakeup && !configured) val |= PORT_CS_19_WOC; - if (((flags & TB_WAKE_ON_DISCONNECT) | - device_may_wakeup(&usb4->dev)) && configured) + if ((flags & TB_WAKE_ON_DISCONNECT) && wakeup && configured) val |= PORT_CS_19_WOD; if ((flags & TB_WAKE_ON_USB4) && configured) val |= PORT_CS_19_WOU4; diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 9ceeb2d10c..7d768c789d 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -5937,9 +5937,14 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) int len = xdr->buf->len - (op_status_offset + XDR_UNIT); so->so_replay.rp_status = op->status; - so->so_replay.rp_buflen = len; - read_bytes_from_xdr_buf(xdr->buf, op_status_offset + XDR_UNIT, + if (len <= NFSD4_REPLAY_ISIZE) { + so->so_replay.rp_buflen = len; + read_bytes_from_xdr_buf(xdr->buf, + op_status_offset + XDR_UNIT, so->so_replay.rp_buf, len); + } else { + so->so_replay.rp_buflen = 0; + } } status: op->status = nfsd4_map_status(op->status, diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index e6a7620c74..f342247840 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -529,11 +529,18 @@ struct nfs4_client_reclaim { struct xdr_netobj cr_princhash; }; -/* A reasonable value for REPLAY_ISIZE was estimated as follows: - * The OPEN response, typically the largest, requires - * 4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) + 8(verifier) + - * 4(deleg. type) + 8(deleg. stateid) + 4(deleg. recall flag) + - * 20(deleg. space limit) + ~32(deleg. ace) = 112 bytes +/* + * REPLAY_ISIZE is sized for an OPEN response with delegation: + * 4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) + + * 8(verifier) + 4(deleg. type) + 8(deleg. stateid) + + * 4(deleg. recall flag) + 20(deleg. space limit) + + * ~32(deleg. ace) = 112 bytes + * + * Some responses can exceed this. A LOCK denial includes the conflicting + * lock owner, which can be up to 1024 bytes (NFS4_OPAQUE_LIMIT). Responses + * larger than REPLAY_ISIZE are not cached in rp_ibuf; only rp_status is + * saved. Enlarging this constant increases the size of every + * nfs4_stateowner. */ #define NFSD4_REPLAY_ISIZE 112 diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h index 7e7942950c..32fc447317 100644 --- a/include/crypto/scatterwalk.h +++ b/include/crypto/scatterwalk.h @@ -83,34 +83,6 @@ static inline void scatterwalk_pagedone(struct scatter_walk *walk, int out, scatterwalk_start(walk, sg_next(walk->sg)); } -/* - * Flush the dcache of any pages that overlap the region - * [offset, offset + nbytes) relative to base_page. - * - * This should be called only when ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE, to ensure - * that all relevant code (including the call to sg_page() in the caller, if - * applicable) gets fully optimized out when !ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE. - */ -static inline void __scatterwalk_flush_dcache_pages(struct page *base_page, - unsigned int offset, - unsigned int nbytes) -{ - unsigned int num_pages; - - base_page += offset / PAGE_SIZE; - offset %= PAGE_SIZE; - - /* - * This is an overflow-safe version of - * num_pages = DIV_ROUND_UP(offset + nbytes, PAGE_SIZE). - */ - num_pages = nbytes / PAGE_SIZE; - num_pages += DIV_ROUND_UP(offset + (nbytes % PAGE_SIZE), PAGE_SIZE); - - for (unsigned int i = 0; i < num_pages; i++) - flush_dcache_page(base_page + i); -} - static inline void scatterwalk_done(struct scatter_walk *walk, int out, int more) { @@ -122,9 +94,6 @@ static inline void scatterwalk_done(struct scatter_walk *walk, int out, void scatterwalk_copychunks(void *buf, struct scatter_walk *walk, size_t nbytes, int out); -void memcpy_sglist(struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes); - void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg, unsigned int start, unsigned int nbytes, int out); diff --git a/include/net/act_api.h b/include/net/act_api.h index 404df8557f..e7f76ba488 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -68,6 +68,7 @@ struct tc_action { #define TCA_ACT_FLAGS_REPLACE (1U << (TCA_ACT_FLAGS_USER_BITS + 2)) #define TCA_ACT_FLAGS_NO_RTNL (1U << (TCA_ACT_FLAGS_USER_BITS + 3)) #define TCA_ACT_FLAGS_AT_INGRESS (1U << (TCA_ACT_FLAGS_USER_BITS + 4)) +#define TCA_ACT_FLAGS_AT_INGRESS_OR_CLSACT (1U << (TCA_ACT_FLAGS_USER_BITS + 5)) /* Update lastuse only if needed, to avoid dirtying a cache line. * We use a temp variable to avoid fetching jiffies twice. diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c index 2197eb6256..945b64be4c 100644 --- a/net/sched/act_ct.c +++ b/net/sched/act_ct.c @@ -1358,6 +1358,12 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla, return -EINVAL; } + if (bind && !(flags & TCA_ACT_FLAGS_AT_INGRESS_OR_CLSACT)) { + NL_SET_ERR_MSG_MOD(extack, + "Attaching ct to a non ingress/clsact qdisc is unsupported"); + return -EOPNOTSUPP; + } + err = nla_parse_nested(tb, TCA_CT_MAX, nla, ct_policy, extack); if (err < 0) return err; diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 5399a46f58..0d76e69171 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -2228,6 +2228,11 @@ static bool is_qdisc_ingress(__u32 classid) return (TC_H_MIN(classid) == TC_H_MIN(TC_H_MIN_INGRESS)); } +static bool is_ingress_or_clsact(struct tcf_block *block, struct Qdisc *q) +{ + return tcf_block_shared(block) || (q && !!(q->flags & TCQ_F_INGRESS)); +} + static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n, struct netlink_ext_ack *extack) { @@ -2420,6 +2425,8 @@ replay: flags |= TCA_ACT_FLAGS_NO_RTNL; if (is_qdisc_ingress(parent)) flags |= TCA_ACT_FLAGS_AT_INGRESS; + if (is_ingress_or_clsact(block, q)) + flags |= TCA_ACT_FLAGS_AT_INGRESS_OR_CLSACT; err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh, flags, extack); if (err == 0) { diff --git a/redhat/kernel.changelog-10.1 b/redhat/kernel.changelog-10.1 index 4bbf712e85..6f2de287cb 100644 --- a/redhat/kernel.changelog-10.1 +++ b/redhat/kernel.changelog-10.1 @@ -1,3 +1,28 @@ +* Sat May 02 2026 CKI KWF Bot [6.12.0-124.55.1.el10_1] +- crypto: algif_aead - snapshot IV for async AEAD requests (Vladislav Dronov) [RHEL-172211] +- crypto: algif_aead - Fix minimum RX size check for decryption (Vladislav Dronov) [RHEL-172211] +- crypto: authencesn - reject short ahash digests during instance creation (Vladislav Dronov) [RHEL-172211] +- crypto: authencesn - Fix src offset when decrypting in-place (Vladislav Dronov) [RHEL-172211] +- crypto: authencesn - Do not place hiseq at end of dst for out-of-place decryption (Vladislav Dronov) [RHEL-172211] {CVE-2026-31431} +- crypto: authencesn - reject too-short AAD (assoclen<8) to match ESP/ESN spec (Vladislav Dronov) [RHEL-172211] {CVE-2026-23060} +- crypto: af_alg - Fix page reassignment overflow in af_alg_pull_tsgl (Vladislav Dronov) [RHEL-172211] +- crypto: af_alg - limit RX SG extraction by receive buffer budget (Vladislav Dronov) [RHEL-172211] {CVE-2026-31677} +- crypto: algif_aead - Revert to operating out-of-place (Vladislav Dronov) [RHEL-172211] {CVE-2026-31431} +- crypto: af-alg - fix NULL pointer dereference in scatterwalk (Vladislav Dronov) [RHEL-172211] +Resolves: RHEL-172211 + +* Mon Apr 27 2026 CKI KWF Bot [6.12.0-124.54.1.el10_1] +- thunderbolt: Fix wake on connect at runtime (Desnes Nunes) [RHEL-108357] +- thunderbolt: Fix a logic error in wake on connect (Desnes Nunes) [RHEL-108357] +- thunderbolt: Use wake on connect and disconnect over suspend (Desnes Nunes) [RHEL-108357] +- net: bonding: fix use-after-free in bond_xmit_broadcast() (CKI Backport Bot) [RHEL-168071] {CVE-2026-31419} +- net/sched: Only allow act_ct to bind to clsact/ingress qdiscs and shared blocks (CKI Backport Bot) [RHEL-157330] {CVE-2026-23270} +Resolves: RHEL-108357, RHEL-157330, RHEL-168071 + +* Tue Apr 14 2026 CKI KWF Bot [6.12.0-124.53.1.el10_1] +- nfsd: fix heap overflow in NFSv4.0 LOCK replay cache (Scott Mayhew) [RHEL-167019] {CVE-2026-31402} +Resolves: RHEL-167019 + * Sat Apr 11 2026 CKI KWF Bot [6.12.0-124.52.1.el10_1] - md/raid1: fix data lost for writemostly rdev (Nigel Croxon) [RHEL-143660] Resolves: RHEL-143660 diff --git a/uki-addons.sbat b/uki-addons.sbat index a7d30d9d0f..896cdeb82a 100644 --- a/uki-addons.sbat +++ b/uki-addons.sbat @@ -1,3 +1,3 @@ sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md -kernel-uki-virt-addons.centos,1,Red Hat,kernel-uki-virt-addons,6.12.0-124.52.3.el10.x86_64,mailto:secalert@redhat.com -kernel-uki-virt-addons.almalinux,1,AlmaLinux,kernel-uki-virt-addons,6.12.0-124.52.3.el10.x86_64,mailto:security@almalinux.org +kernel-uki-virt-addons.centos,1,Red Hat,kernel-uki-virt-addons,6.12.0-124.55.1.el10.x86_64,mailto:secalert@redhat.com +kernel-uki-virt-addons.almalinux,1,AlmaLinux,kernel-uki-virt-addons,6.12.0-124.55.1.el10.x86_64,mailto:security@almalinux.org diff --git a/uki.sbat b/uki.sbat index 4a9f62e23c..8a5d40dfbb 100644 --- a/uki.sbat +++ b/uki.sbat @@ -1,3 +1,3 @@ sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md -kernel-uki-virt.centos,1,Red Hat,kernel-uki-virt,6.12.0-124.52.3.el10.x86_64,mailto:secalert@redhat.com -kernel-uki-virt.almalinux,1,AlmaLinux,kernel-uki-virt,6.12.0-124.52.3.el10.x86_64,mailto:security@almalinux.org +kernel-uki-virt.centos,1,Red Hat,kernel-uki-virt,6.12.0-124.55.1.el10.x86_64,mailto:secalert@redhat.com +kernel-uki-virt.almalinux,1,AlmaLinux,kernel-uki-virt,6.12.0-124.55.1.el10.x86_64,mailto:security@almalinux.org