]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for all trees master
authorSasha Levin <sashal@kernel.org>
Fri, 17 Jul 2026 01:37:11 +0000 (21:37 -0400)
committerSasha Levin <sashal@kernel.org>
Fri, 17 Jul 2026 01:37:11 +0000 (21:37 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
51 files changed:
staging-5.10/crypto-algif_skcipher-force-synchronous-processing-o.patch [new file with mode: 0644]
staging-5.10/sched-fair-only-update-stats-for-allowed-cpus-when-l.patch [new file with mode: 0644]
staging-5.10/series [new file with mode: 0644]
staging-5.10/tools-mm-slabinfo-fix-total_objects-attribute-name.patch [new file with mode: 0644]
staging-5.15/crypto-algif_skcipher-force-synchronous-processing-o.patch [new file with mode: 0644]
staging-5.15/net-dsa-tag_ksz-do-not-rely-on-skb_mac_header-in-tx-.patch [new file with mode: 0644]
staging-5.15/sched-fair-only-update-stats-for-allowed-cpus-when-l.patch [new file with mode: 0644]
staging-5.15/series [new file with mode: 0644]
staging-5.15/tools-mm-slabinfo-fix-total_objects-attribute-name.patch [new file with mode: 0644]
staging-6.1/crypto-algif_skcipher-force-synchronous-processing-o.patch [new file with mode: 0644]
staging-6.1/fs-quota-create-dedicated-workqueue-for-quota_releas.patch [new file with mode: 0644]
staging-6.1/net-dsa-tag_ksz-do-not-rely-on-skb_mac_header-in-tx-.patch [new file with mode: 0644]
staging-6.1/sched-fair-only-update-stats-for-allowed-cpus-when-l.patch [new file with mode: 0644]
staging-6.1/series [new file with mode: 0644]
staging-6.1/smb-server-do-not-require-delete-access-for-non-repl.patch [new file with mode: 0644]
staging-6.1/tools-mm-slabinfo-fix-total_objects-attribute-name.patch [new file with mode: 0644]
staging-6.12/bpf-prefer-dirty-packs-for-ebpf-allocations.patch [new file with mode: 0644]
staging-6.12/bpf-prefer-packs-that-won-t-trigger-an-ibpb-flush-on.patch [new file with mode: 0644]
staging-6.12/bpf-restrict-jit-predictor-flush-to-cbpf.patch [new file with mode: 0644]
staging-6.12/bpf-skip-redundant-ibpb-in-pack-allocator.patch [new file with mode: 0644]
staging-6.12/bpf-support-for-hardening-against-jit-spraying.patch [new file with mode: 0644]
staging-6.12/crypto-algif_skcipher-force-synchronous-processing.patch [new file with mode: 0644]
staging-6.12/iommu-pass-old-domain-to-set_dev_pasid-op.patch [new file with mode: 0644]
staging-6.12/iommu-vt-d-cleanup-intel_context_flush_present.patch [new file with mode: 0644]
staging-6.12/iommu-vt-d-clear-present-bit-before-tearing-down-con.patch [new file with mode: 0644]
staging-6.12/iommu-vt-d-clear-present-bit-before-tearing-down-sca.patch [new file with mode: 0644]
staging-6.12/kvm-arm64-bound-used_lrs-when-flushing-the-pkvm-hyp-.patch [new file with mode: 0644]
staging-6.12/kvm-arm64-clear-__hyp_running_vcpu-when-flushing-the.patch [new file with mode: 0644]
staging-6.12/sched-fair-only-update-stats-for-allowed-cpus-when-l.patch [new file with mode: 0644]
staging-6.12/series [new file with mode: 0644]
staging-6.12/smb-server-do-not-require-delete-access-for-non-repl.patch [new file with mode: 0644]
staging-6.12/tcp-add-preempt_-disable-enable-_nested-in-reqsk_que.patch [new file with mode: 0644]
staging-6.12/timekeeping-register-default-clocksource-before-taki.patch [new file with mode: 0644]
staging-6.12/x86-bugs-enable-ibpb-flush-on-bpf-jit-allocation.patch [new file with mode: 0644]
staging-6.18/crypto-algif_skcipher-force-synchronous-processing.patch [new file with mode: 0644]
staging-6.18/iommu-vt-d-clear-present-bit-before-tearing-down-sca.patch [new file with mode: 0644]
staging-6.18/kvm-arm64-bound-used_lrs-when-flushing-the-pkvm-hyp-.patch [new file with mode: 0644]
staging-6.18/nvme-pci-dma-unmap-the-correct-regions-in-nvme_free_.patch [new file with mode: 0644]
staging-6.18/series [new file with mode: 0644]
staging-6.18/smb-server-do-not-require-delete-access-for-non-repl.patch [new file with mode: 0644]
staging-6.18/tcp-add-preempt_-disable-enable-_nested-in-reqsk_que.patch [new file with mode: 0644]
staging-6.6/block-skip-sync_blockdev-on-surprise-removal-in-bdev.patch [new file with mode: 0644]
staging-6.6/crypto-algif_skcipher-force-synchronous-processing-o.patch [new file with mode: 0644]
staging-6.6/kvm-arm64-bound-used_lrs-when-flushing-the-pkvm-hyp-.patch [new file with mode: 0644]
staging-6.6/kvm-arm64-clear-__hyp_running_vcpu-when-flushing-the.patch [new file with mode: 0644]
staging-6.6/sched-fair-only-update-stats-for-allowed-cpus-when-l.patch [new file with mode: 0644]
staging-6.6/series [new file with mode: 0644]
staging-6.6/smb-server-do-not-require-delete-access-for-non-repl.patch [new file with mode: 0644]
staging-7.1/crypto-algif_skcipher-force-synchronous-processing.patch [new file with mode: 0644]
staging-7.1/iommu-vt-d-clear-present-bit-before-tearing-down-sca.patch [new file with mode: 0644]
staging-7.1/series [new file with mode: 0644]

diff --git a/staging-5.10/crypto-algif_skcipher-force-synchronous-processing-o.patch b/staging-5.10/crypto-algif_skcipher-force-synchronous-processing-o.patch
new file mode 100644 (file)
index 0000000..7b81dc9
--- /dev/null
@@ -0,0 +1,116 @@
+From 26a93606e373b23307c5c531668aa7fb43b7a66d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 02:58:37 +0000
+Subject: crypto: algif_skcipher - force synchronous processing on trees
+ without ctx->state
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+
+The AIO/async path in skcipher_recvmsg() passes the socket-wide ctx->iv
+directly into the skcipher request. After io_submit() the socket lock is
+dropped and the request is processed asynchronously, so a concurrent
+sendmsg(ALG_SET_IV) can overwrite ctx->iv and make the in-flight request
+run under an attacker-controlled IV. For CTR/stream modes this is
+IV/keystream reuse and lets an unprivileged user recover the plaintext of
+a concurrent operation.
+
+Snapshotting ctx->iv into per-request storage for the async path is not
+sufficient. For ciphers with statesize == 0 - which includes cbc and ctr -
+the MSG_MORE inter-chunk IV chaining is carried solely by the in-place
+req->iv writeback, which a snapshot redirects into per-request memory that
+af_alg_free_resources() releases on completion, silently producing wrong
+output. Writing the IV back from the completion callback instead is not
+possible either: that would require lock_sock() there, but the callback can
+run in softirq/atomic context, so it must not sleep.
+
+Make the operation synchronous instead, which removes both the IV race and
+any writeback race. This is equivalent to the upstream resolution, commit
+fcc77d33a34c ("net: Remove support for AIO on sockets"), which removed the
+AIO socket path across net/ entirely and so produces the same end state for
+this file. This patch deviates from that commit deliberately: rather than
+removing AIO socket support tree-wide, which would be far too invasive for
+stable, it removes only the AIO branch in crypto/algif_skcipher.c.
+io_submit() now completes synchronously; AF_ALG async is rarely used in
+practice.
+
+The -EIOCBQUEUED check in skcipher_recvmsg() is now dead but harmless,
+and is left alone to keep the fix minimal.
+
+Tested on 6.6.y: attacker IV injection dropped from 2296/200000 to 0/200000
+after the change; MSG_MORE chunked CTR output bit-identical to single-shot.
+
+Reported-by: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+Fixes: e870456d8e7c ("crypto: algif_skcipher - overhaul memory management")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ crypto/algif_skcipher.c | 49 +++++++++++++++--------------------------
+ 1 file changed, 18 insertions(+), 31 deletions(-)
+
+diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
+index 8b314260929fbb..6a1a71284fe823 100644
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -107,37 +107,24 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
+       skcipher_request_set_crypt(&areq->cra_u.skcipher_req, areq->tsgl,
+                                  areq->first_rsgl.sgl.sg, len, ctx->iv);
+-      if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
+-              /* AIO operation */
+-              sock_hold(sk);
+-              areq->iocb = msg->msg_iocb;
+-
+-              /* Remember output size that will be generated. */
+-              areq->outlen = len;
+-
+-              skcipher_request_set_callback(&areq->cra_u.skcipher_req,
+-                                            CRYPTO_TFM_REQ_MAY_SLEEP,
+-                                            af_alg_async_cb, areq);
+-              err = ctx->enc ?
+-                      crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
+-                      crypto_skcipher_decrypt(&areq->cra_u.skcipher_req);
+-
+-              /* AIO operation in progress */
+-              if (err == -EINPROGRESS)
+-                      return -EIOCBQUEUED;
+-
+-              sock_put(sk);
+-      } else {
+-              /* Synchronous operation */
+-              skcipher_request_set_callback(&areq->cra_u.skcipher_req,
+-                                            CRYPTO_TFM_REQ_MAY_SLEEP |
+-                                            CRYPTO_TFM_REQ_MAY_BACKLOG,
+-                                            crypto_req_done, &ctx->wait);
+-              err = crypto_wait_req(ctx->enc ?
+-                      crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
+-                      crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
+-                                               &ctx->wait);
+-      }
++      /*
++       * Force synchronous processing.  The async (AIO) path passed the
++       * socket-wide ctx->iv into the request, which the worker
++       * dereferenced after the socket lock was dropped, letting a
++       * concurrent sendmsg(ALG_SET_IV) inject an attacker IV.  Mainline
++       * removed the AIO socket path in commit fcc77d33a34c ("net: Remove
++       * support for AIO on sockets"); these stable trees lack the
++       * per-request ctx->state used by newer kernels, so the minimal safe
++       * fix is to always complete synchronously.
++       */
++      skcipher_request_set_callback(&areq->cra_u.skcipher_req,
++                                    CRYPTO_TFM_REQ_MAY_SLEEP |
++                                    CRYPTO_TFM_REQ_MAY_BACKLOG,
++                                    crypto_req_done, &ctx->wait);
++      err = crypto_wait_req(ctx->enc ?
++              crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
++              crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
++                                    &ctx->wait);
+ free:
+-- 
+2.53.0
+
diff --git a/staging-5.10/sched-fair-only-update-stats-for-allowed-cpus-when-l.patch b/staging-5.10/sched-fair-only-update-stats-for-allowed-cpus-when-l.patch
new file mode 100644 (file)
index 0000000..148b4f2
--- /dev/null
@@ -0,0 +1,50 @@
+From dd3f92d0148dbd6d22628831a99b923cfb77b434 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 11 Oct 2025 06:43:22 +0000
+Subject: sched/fair: Only update stats for allowed CPUs when looking for dst
+ group
+
+From: Adam Li <adamli@os.amperecomputing.com>
+
+[ Upstream commit 82d6e01a0699800efd8b048eb584c907ccb47b7a ]
+
+Load imbalance is observed when the workload frequently forks new threads.
+Due to CPU affinity, the workload can run on CPU 0-7 in the first
+group, and only on CPU 8-11 in the second group. CPU 12-15 are always idle.
+
+{ 0 1 2 3 4 5 6 7 } {8 9 10 11 12 13 14 15}
+  * * * * * * * *    * * *  *
+
+When looking for dst group for newly forked threads, in many times
+update_sg_wakeup_stats() reports the second group has more idle CPUs
+than the first group. The scheduler thinks the second group is less
+busy. Then it selects least busy CPUs among CPU 8-11. Therefore CPU 8-11
+can be crowded with newly forked threads, at the same time CPU 0-7
+can be idle.
+
+A task may not use all the CPUs in a schedule group due to CPU affinity.
+Only update schedule group statistics for allowed CPUs.
+
+Signed-off-by: Adam Li <adamli@os.amperecomputing.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sched/fair.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index c11d59bea0ea81..fa85b84fdbc533 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -8969,7 +8969,7 @@ static inline void update_sg_wakeup_stats(struct sched_domain *sd,
+       if (sd->flags & SD_ASYM_CPUCAPACITY)
+               sgs->group_misfit_task_load = 1;
+-      for_each_cpu(i, sched_group_span(group)) {
++      for_each_cpu_and(i, sched_group_span(group), p->cpus_ptr) {
+               struct rq *rq = cpu_rq(i);
+               unsigned int local;
+-- 
+2.53.0
+
diff --git a/staging-5.10/series b/staging-5.10/series
new file mode 100644 (file)
index 0000000..50d9ea5
--- /dev/null
@@ -0,0 +1,3 @@
+sched-fair-only-update-stats-for-allowed-cpus-when-l.patch
+crypto-algif_skcipher-force-synchronous-processing-o.patch
+tools-mm-slabinfo-fix-total_objects-attribute-name.patch
diff --git a/staging-5.10/tools-mm-slabinfo-fix-total_objects-attribute-name.patch b/staging-5.10/tools-mm-slabinfo-fix-total_objects-attribute-name.patch
new file mode 100644 (file)
index 0000000..b77c730
--- /dev/null
@@ -0,0 +1,51 @@
+From 5d08f3ee9a085c77c2662315abaf96203aa7c852 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 16:05:45 +0800
+Subject: tools/mm/slabinfo: fix total_objects attribute name
+
+From: Yichong Chen <chenyichong@uniontech.com>
+
+[ Upstream commit 892a7864730775c3dbee2a39e9ead4fa8d4256e7 ]
+
+SLUB exports the total_objects sysfs attribute, but slabinfo tries to read
+objects_total. As a result, the lookup fails and the field remains zero.
+
+Use the correct attribute name and rename the corresponding structure
+member to match.
+
+Fixes: 205ab99dd103 ("slub: Update statistics handling for variable order slabs")
+Signed-off-by: Yichong Chen <chenyichong@uniontech.com>
+Cc: <stable@vger.kernel.org>
+Reviewed-by: SeongJae Park <sj@kernel.org>
+Link: https://patch.msgid.link/96556748872BB47E+20260612071359.649946-1-chenyichong@uniontech.com
+Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/vm/slabinfo.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/vm/slabinfo.c b/tools/vm/slabinfo.c
+index 3ae985dc24b6d6..5819c4133e0d9c 100644
+--- a/tools/vm/slabinfo.c
++++ b/tools/vm/slabinfo.c
+@@ -33,7 +33,7 @@ struct slabinfo {
+       unsigned int hwcache_align, object_size, objs_per_slab;
+       unsigned int sanity_checks, slab_size, store_user, trace;
+       int order, poison, reclaim_account, red_zone;
+-      unsigned long partial, objects, slabs, objects_partial, objects_total;
++      unsigned long partial, objects, slabs, objects_partial, total_objects;
+       unsigned long alloc_fastpath, alloc_slowpath;
+       unsigned long free_fastpath, free_slowpath;
+       unsigned long free_frozen, free_add_partial, free_remove_partial;
+@@ -1232,7 +1232,7 @@ static void read_slab_dir(void)
+                       slab->object_size = get_obj("object_size");
+                       slab->objects = get_obj("objects");
+                       slab->objects_partial = get_obj("objects_partial");
+-                      slab->objects_total = get_obj("objects_total");
++                      slab->total_objects = get_obj("total_objects");
+                       slab->objs_per_slab = get_obj("objs_per_slab");
+                       slab->order = get_obj("order");
+                       slab->partial = get_obj("partial");
+-- 
+2.53.0
+
diff --git a/staging-5.15/crypto-algif_skcipher-force-synchronous-processing-o.patch b/staging-5.15/crypto-algif_skcipher-force-synchronous-processing-o.patch
new file mode 100644 (file)
index 0000000..1040377
--- /dev/null
@@ -0,0 +1,116 @@
+From b903d0f50b611d24f32f460f354fb80bd49a1f6c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 02:58:37 +0000
+Subject: crypto: algif_skcipher - force synchronous processing on trees
+ without ctx->state
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+
+The AIO/async path in skcipher_recvmsg() passes the socket-wide ctx->iv
+directly into the skcipher request. After io_submit() the socket lock is
+dropped and the request is processed asynchronously, so a concurrent
+sendmsg(ALG_SET_IV) can overwrite ctx->iv and make the in-flight request
+run under an attacker-controlled IV. For CTR/stream modes this is
+IV/keystream reuse and lets an unprivileged user recover the plaintext of
+a concurrent operation.
+
+Snapshotting ctx->iv into per-request storage for the async path is not
+sufficient. For ciphers with statesize == 0 - which includes cbc and ctr -
+the MSG_MORE inter-chunk IV chaining is carried solely by the in-place
+req->iv writeback, which a snapshot redirects into per-request memory that
+af_alg_free_resources() releases on completion, silently producing wrong
+output. Writing the IV back from the completion callback instead is not
+possible either: that would require lock_sock() there, but the callback can
+run in softirq/atomic context, so it must not sleep.
+
+Make the operation synchronous instead, which removes both the IV race and
+any writeback race. This is equivalent to the upstream resolution, commit
+fcc77d33a34c ("net: Remove support for AIO on sockets"), which removed the
+AIO socket path across net/ entirely and so produces the same end state for
+this file. This patch deviates from that commit deliberately: rather than
+removing AIO socket support tree-wide, which would be far too invasive for
+stable, it removes only the AIO branch in crypto/algif_skcipher.c.
+io_submit() now completes synchronously; AF_ALG async is rarely used in
+practice.
+
+The -EIOCBQUEUED check in skcipher_recvmsg() is now dead but harmless,
+and is left alone to keep the fix minimal.
+
+Tested on 6.6.y: attacker IV injection dropped from 2296/200000 to 0/200000
+after the change; MSG_MORE chunked CTR output bit-identical to single-shot.
+
+Reported-by: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+Fixes: e870456d8e7c ("crypto: algif_skcipher - overhaul memory management")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ crypto/algif_skcipher.c | 49 +++++++++++++++--------------------------
+ 1 file changed, 18 insertions(+), 31 deletions(-)
+
+diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
+index 8b314260929fbb..6a1a71284fe823 100644
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -107,37 +107,24 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
+       skcipher_request_set_crypt(&areq->cra_u.skcipher_req, areq->tsgl,
+                                  areq->first_rsgl.sgl.sg, len, ctx->iv);
+-      if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
+-              /* AIO operation */
+-              sock_hold(sk);
+-              areq->iocb = msg->msg_iocb;
+-
+-              /* Remember output size that will be generated. */
+-              areq->outlen = len;
+-
+-              skcipher_request_set_callback(&areq->cra_u.skcipher_req,
+-                                            CRYPTO_TFM_REQ_MAY_SLEEP,
+-                                            af_alg_async_cb, areq);
+-              err = ctx->enc ?
+-                      crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
+-                      crypto_skcipher_decrypt(&areq->cra_u.skcipher_req);
+-
+-              /* AIO operation in progress */
+-              if (err == -EINPROGRESS)
+-                      return -EIOCBQUEUED;
+-
+-              sock_put(sk);
+-      } else {
+-              /* Synchronous operation */
+-              skcipher_request_set_callback(&areq->cra_u.skcipher_req,
+-                                            CRYPTO_TFM_REQ_MAY_SLEEP |
+-                                            CRYPTO_TFM_REQ_MAY_BACKLOG,
+-                                            crypto_req_done, &ctx->wait);
+-              err = crypto_wait_req(ctx->enc ?
+-                      crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
+-                      crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
+-                                               &ctx->wait);
+-      }
++      /*
++       * Force synchronous processing.  The async (AIO) path passed the
++       * socket-wide ctx->iv into the request, which the worker
++       * dereferenced after the socket lock was dropped, letting a
++       * concurrent sendmsg(ALG_SET_IV) inject an attacker IV.  Mainline
++       * removed the AIO socket path in commit fcc77d33a34c ("net: Remove
++       * support for AIO on sockets"); these stable trees lack the
++       * per-request ctx->state used by newer kernels, so the minimal safe
++       * fix is to always complete synchronously.
++       */
++      skcipher_request_set_callback(&areq->cra_u.skcipher_req,
++                                    CRYPTO_TFM_REQ_MAY_SLEEP |
++                                    CRYPTO_TFM_REQ_MAY_BACKLOG,
++                                    crypto_req_done, &ctx->wait);
++      err = crypto_wait_req(ctx->enc ?
++              crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
++              crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
++                                    &ctx->wait);
+ free:
+-- 
+2.53.0
+
diff --git a/staging-5.15/net-dsa-tag_ksz-do-not-rely-on-skb_mac_header-in-tx-.patch b/staging-5.15/net-dsa-tag_ksz-do-not-rely-on-skb_mac_header-in-tx-.patch
new file mode 100644 (file)
index 0000000..2674a8a
--- /dev/null
@@ -0,0 +1,103 @@
+From 58247da1acbee7e96c744639d0b5bb5364797c48 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Apr 2023 01:55:57 +0300
+Subject: net: dsa: tag_ksz: do not rely on skb_mac_header() in TX paths
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit 499b2491d550677b824b828ff431e4ef4d1d3b9d ]
+
+skb_mac_header() will no longer be available in the TX path when
+reverting commit 6d1ccff62780 ("net: reset mac header in
+dev_start_xmit()"). As preparation for that, let's use skb_eth_hdr() to
+get to the Ethernet header's MAC DA instead, helper which assumes this
+header is located at skb->data (assumption which holds true here).
+
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[ sashal: adjusted for missing tail tag PRIO (FIELD_PREP) and PTP tail
+  tag support in 5.15 ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/dsa/tag_ksz.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
+index 00e4f40716dcbd..7c6c76254874aa 100644
+--- a/net/dsa/tag_ksz.c
++++ b/net/dsa/tag_ksz.c
+@@ -51,18 +51,18 @@ static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,
+ static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+       struct dsa_port *dp = dsa_slave_to_port(dev);
++      struct ethhdr *hdr;
+       u8 *tag;
+-      u8 *addr;
+       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+               return NULL;
+       /* Tag encoding */
+       tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
+-      addr = skb_mac_header(skb);
++      hdr = skb_eth_hdr(skb);
+       *tag = 1 << dp->index;
+-      if (is_link_local_ether_addr(addr))
++      if (is_link_local_ether_addr(hdr->h_dest))
+               *tag |= KSZ8795_TAIL_TAG_OVERRIDE;
+       return skb;
+@@ -119,8 +119,8 @@ static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
+                                   struct net_device *dev)
+ {
+       struct dsa_port *dp = dsa_slave_to_port(dev);
++      struct ethhdr *hdr;
+       __be16 *tag;
+-      u8 *addr;
+       u16 val;
+       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+@@ -128,11 +128,11 @@ static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
+       /* Tag encoding */
+       tag = skb_put(skb, KSZ9477_INGRESS_TAG_LEN);
+-      addr = skb_mac_header(skb);
++      hdr = skb_eth_hdr(skb);
+       val = BIT(dp->index);
+-      if (is_link_local_ether_addr(addr))
++      if (is_link_local_ether_addr(hdr->h_dest))
+               val |= KSZ9477_TAIL_TAG_OVERRIDE;
+       *tag = cpu_to_be16(val);
+@@ -178,7 +178,7 @@ static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,
+                                   struct net_device *dev)
+ {
+       struct dsa_port *dp = dsa_slave_to_port(dev);
+-      u8 *addr;
++      struct ethhdr *hdr;
+       u8 *tag;
+       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+@@ -186,11 +186,11 @@ static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,
+       /* Tag encoding */
+       tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
+-      addr = skb_mac_header(skb);
++      hdr = skb_eth_hdr(skb);
+       *tag = BIT(dp->index);
+-      if (is_link_local_ether_addr(addr))
++      if (is_link_local_ether_addr(hdr->h_dest))
+               *tag |= KSZ9893_TAIL_TAG_OVERRIDE;
+       return skb;
+-- 
+2.53.0
+
diff --git a/staging-5.15/sched-fair-only-update-stats-for-allowed-cpus-when-l.patch b/staging-5.15/sched-fair-only-update-stats-for-allowed-cpus-when-l.patch
new file mode 100644 (file)
index 0000000..f346d01
--- /dev/null
@@ -0,0 +1,50 @@
+From d02b761826e9c98329427245a38bb3184a4fb558 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 11 Oct 2025 06:43:22 +0000
+Subject: sched/fair: Only update stats for allowed CPUs when looking for dst
+ group
+
+From: Adam Li <adamli@os.amperecomputing.com>
+
+[ Upstream commit 82d6e01a0699800efd8b048eb584c907ccb47b7a ]
+
+Load imbalance is observed when the workload frequently forks new threads.
+Due to CPU affinity, the workload can run on CPU 0-7 in the first
+group, and only on CPU 8-11 in the second group. CPU 12-15 are always idle.
+
+{ 0 1 2 3 4 5 6 7 } {8 9 10 11 12 13 14 15}
+  * * * * * * * *    * * *  *
+
+When looking for dst group for newly forked threads, in many times
+update_sg_wakeup_stats() reports the second group has more idle CPUs
+than the first group. The scheduler thinks the second group is less
+busy. Then it selects least busy CPUs among CPU 8-11. Therefore CPU 8-11
+can be crowded with newly forked threads, at the same time CPU 0-7
+can be idle.
+
+A task may not use all the CPUs in a schedule group due to CPU affinity.
+Only update schedule group statistics for allowed CPUs.
+
+Signed-off-by: Adam Li <adamli@os.amperecomputing.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sched/fair.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 87f32cf8aa0291..f2a58e54268ea3 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -9209,7 +9209,7 @@ static inline void update_sg_wakeup_stats(struct sched_domain *sd,
+       if (sd->flags & SD_ASYM_CPUCAPACITY)
+               sgs->group_misfit_task_load = 1;
+-      for_each_cpu(i, sched_group_span(group)) {
++      for_each_cpu_and(i, sched_group_span(group), p->cpus_ptr) {
+               struct rq *rq = cpu_rq(i);
+               unsigned int local;
+-- 
+2.53.0
+
diff --git a/staging-5.15/series b/staging-5.15/series
new file mode 100644 (file)
index 0000000..ebd8a57
--- /dev/null
@@ -0,0 +1,4 @@
+sched-fair-only-update-stats-for-allowed-cpus-when-l.patch
+crypto-algif_skcipher-force-synchronous-processing-o.patch
+tools-mm-slabinfo-fix-total_objects-attribute-name.patch
+net-dsa-tag_ksz-do-not-rely-on-skb_mac_header-in-tx-.patch
diff --git a/staging-5.15/tools-mm-slabinfo-fix-total_objects-attribute-name.patch b/staging-5.15/tools-mm-slabinfo-fix-total_objects-attribute-name.patch
new file mode 100644 (file)
index 0000000..c080d6f
--- /dev/null
@@ -0,0 +1,51 @@
+From 2e8e4dfbbb2aed5f9416dd2810c37e2e412a27c4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 16:11:50 +0800
+Subject: tools/mm/slabinfo: fix total_objects attribute name
+
+From: Yichong Chen <chenyichong@uniontech.com>
+
+[ Upstream commit 892a7864730775c3dbee2a39e9ead4fa8d4256e7 ]
+
+SLUB exports the total_objects sysfs attribute, but slabinfo tries to read
+objects_total. As a result, the lookup fails and the field remains zero.
+
+Use the correct attribute name and rename the corresponding structure
+member to match.
+
+Fixes: 205ab99dd103 ("slub: Update statistics handling for variable order slabs")
+Signed-off-by: Yichong Chen <chenyichong@uniontech.com>
+Cc: <stable@vger.kernel.org>
+Reviewed-by: SeongJae Park <sj@kernel.org>
+Link: https://patch.msgid.link/96556748872BB47E+20260612071359.649946-1-chenyichong@uniontech.com
+Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/vm/slabinfo.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/vm/slabinfo.c b/tools/vm/slabinfo.c
+index 0fffaeedee7672..d26a44e3e68470 100644
+--- a/tools/vm/slabinfo.c
++++ b/tools/vm/slabinfo.c
+@@ -33,7 +33,7 @@ struct slabinfo {
+       unsigned int hwcache_align, object_size, objs_per_slab;
+       unsigned int sanity_checks, slab_size, store_user, trace;
+       int order, poison, reclaim_account, red_zone;
+-      unsigned long partial, objects, slabs, objects_partial, objects_total;
++      unsigned long partial, objects, slabs, objects_partial, total_objects;
+       unsigned long alloc_fastpath, alloc_slowpath;
+       unsigned long free_fastpath, free_slowpath;
+       unsigned long free_frozen, free_add_partial, free_remove_partial;
+@@ -1254,7 +1254,7 @@ static void read_slab_dir(void)
+                       slab->object_size = get_obj("object_size");
+                       slab->objects = get_obj("objects");
+                       slab->objects_partial = get_obj("objects_partial");
+-                      slab->objects_total = get_obj("objects_total");
++                      slab->total_objects = get_obj("total_objects");
+                       slab->objs_per_slab = get_obj("objs_per_slab");
+                       slab->order = get_obj("order");
+                       slab->partial = get_obj("partial");
+-- 
+2.53.0
+
diff --git a/staging-6.1/crypto-algif_skcipher-force-synchronous-processing-o.patch b/staging-6.1/crypto-algif_skcipher-force-synchronous-processing-o.patch
new file mode 100644 (file)
index 0000000..476890e
--- /dev/null
@@ -0,0 +1,116 @@
+From caaa06086f85652bbc262a8bbce924cd2a55a364 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 02:58:37 +0000
+Subject: crypto: algif_skcipher - force synchronous processing on trees
+ without ctx->state
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+
+The AIO/async path in skcipher_recvmsg() passes the socket-wide ctx->iv
+directly into the skcipher request. After io_submit() the socket lock is
+dropped and the request is processed asynchronously, so a concurrent
+sendmsg(ALG_SET_IV) can overwrite ctx->iv and make the in-flight request
+run under an attacker-controlled IV. For CTR/stream modes this is
+IV/keystream reuse and lets an unprivileged user recover the plaintext of
+a concurrent operation.
+
+Snapshotting ctx->iv into per-request storage for the async path is not
+sufficient. For ciphers with statesize == 0 - which includes cbc and ctr -
+the MSG_MORE inter-chunk IV chaining is carried solely by the in-place
+req->iv writeback, which a snapshot redirects into per-request memory that
+af_alg_free_resources() releases on completion, silently producing wrong
+output. Writing the IV back from the completion callback instead is not
+possible either: that would require lock_sock() there, but the callback can
+run in softirq/atomic context, so it must not sleep.
+
+Make the operation synchronous instead, which removes both the IV race and
+any writeback race. This is equivalent to the upstream resolution, commit
+fcc77d33a34c ("net: Remove support for AIO on sockets"), which removed the
+AIO socket path across net/ entirely and so produces the same end state for
+this file. This patch deviates from that commit deliberately: rather than
+removing AIO socket support tree-wide, which would be far too invasive for
+stable, it removes only the AIO branch in crypto/algif_skcipher.c.
+io_submit() now completes synchronously; AF_ALG async is rarely used in
+practice.
+
+The -EIOCBQUEUED check in skcipher_recvmsg() is now dead but harmless,
+and is left alone to keep the fix minimal.
+
+Tested on 6.6.y: attacker IV injection dropped from 2296/200000 to 0/200000
+after the change; MSG_MORE chunked CTR output bit-identical to single-shot.
+
+Reported-by: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+Fixes: e870456d8e7c ("crypto: algif_skcipher - overhaul memory management")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ crypto/algif_skcipher.c | 49 +++++++++++++++--------------------------
+ 1 file changed, 18 insertions(+), 31 deletions(-)
+
+diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
+index 8b314260929fbb..6a1a71284fe823 100644
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -107,37 +107,24 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
+       skcipher_request_set_crypt(&areq->cra_u.skcipher_req, areq->tsgl,
+                                  areq->first_rsgl.sgl.sg, len, ctx->iv);
+-      if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
+-              /* AIO operation */
+-              sock_hold(sk);
+-              areq->iocb = msg->msg_iocb;
+-
+-              /* Remember output size that will be generated. */
+-              areq->outlen = len;
+-
+-              skcipher_request_set_callback(&areq->cra_u.skcipher_req,
+-                                            CRYPTO_TFM_REQ_MAY_SLEEP,
+-                                            af_alg_async_cb, areq);
+-              err = ctx->enc ?
+-                      crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
+-                      crypto_skcipher_decrypt(&areq->cra_u.skcipher_req);
+-
+-              /* AIO operation in progress */
+-              if (err == -EINPROGRESS)
+-                      return -EIOCBQUEUED;
+-
+-              sock_put(sk);
+-      } else {
+-              /* Synchronous operation */
+-              skcipher_request_set_callback(&areq->cra_u.skcipher_req,
+-                                            CRYPTO_TFM_REQ_MAY_SLEEP |
+-                                            CRYPTO_TFM_REQ_MAY_BACKLOG,
+-                                            crypto_req_done, &ctx->wait);
+-              err = crypto_wait_req(ctx->enc ?
+-                      crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
+-                      crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
+-                                               &ctx->wait);
+-      }
++      /*
++       * Force synchronous processing.  The async (AIO) path passed the
++       * socket-wide ctx->iv into the request, which the worker
++       * dereferenced after the socket lock was dropped, letting a
++       * concurrent sendmsg(ALG_SET_IV) inject an attacker IV.  Mainline
++       * removed the AIO socket path in commit fcc77d33a34c ("net: Remove
++       * support for AIO on sockets"); these stable trees lack the
++       * per-request ctx->state used by newer kernels, so the minimal safe
++       * fix is to always complete synchronously.
++       */
++      skcipher_request_set_callback(&areq->cra_u.skcipher_req,
++                                    CRYPTO_TFM_REQ_MAY_SLEEP |
++                                    CRYPTO_TFM_REQ_MAY_BACKLOG,
++                                    crypto_req_done, &ctx->wait);
++      err = crypto_wait_req(ctx->enc ?
++              crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
++              crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
++                                    &ctx->wait);
+ free:
+-- 
+2.53.0
+
diff --git a/staging-6.1/fs-quota-create-dedicated-workqueue-for-quota_releas.patch b/staging-6.1/fs-quota-create-dedicated-workqueue-for-quota_releas.patch
new file mode 100644 (file)
index 0000000..9ca50db
--- /dev/null
@@ -0,0 +1,94 @@
+From 28dcce15dc6018b60aa7350cd62b75cd3fd91a8a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 18:21:37 +0530
+Subject: fs: quota: create dedicated workqueue for quota_release_work
+
+From: Shashank A P <shashank.ap@samsung.com>
+
+commit 72b7ceca857f38a8ca7c5629feffc63769638974 upstream.
+
+There is a kernel panic due to WARN_ONCE when panic_on_warn is set.
+
+This issue occurs when writeback is triggered due to sync call for an
+opened file(ie, writeback reason is WB_REASON_SYNC). When f2fs balance
+is needed at sync path, flush for quota_release_work is triggered.
+By default quota_release_work is queued to "events_unbound" queue which
+does not have WQ_MEM_RECLAIM flag. During f2fs balance "writeback"
+workqueue tries to flush quota_release_work causing kernel panic due to
+MEM_RECLAIM flag mismatch errors.
+
+This patch creates dedicated workqueue with WQ_MEM_RECLAIM flag
+for work quota_release_work.
+
+------------[ cut here ]------------
+WARNING: CPU: 4 PID: 14867 at kernel/workqueue.c:3721 check_flush_dependency+0x13c/0x148
+Call trace:
+ check_flush_dependency+0x13c/0x148
+ __flush_work+0xd0/0x398
+ flush_delayed_work+0x44/0x5c
+ dquot_writeback_dquots+0x54/0x318
+ f2fs_do_quota_sync+0xb8/0x1a8
+ f2fs_write_checkpoint+0x3cc/0x99c
+ f2fs_gc+0x190/0x750
+ f2fs_balance_fs+0x110/0x168
+ f2fs_write_single_data_page+0x474/0x7dc
+ f2fs_write_data_pages+0x7d0/0xd0c
+ do_writepages+0xe0/0x2f4
+ __writeback_single_inode+0x44/0x4ac
+ writeback_sb_inodes+0x30c/0x538
+ wb_writeback+0xf4/0x440
+ wb_workfn+0x128/0x5d4
+ process_scheduled_works+0x1c4/0x45c
+ worker_thread+0x32c/0x3e8
+ kthread+0x11c/0x1b0
+ ret_from_fork+0x10/0x20
+Kernel panic - not syncing: kernel: panic_on_warn set ...
+
+Fixes: ac6f420291b3 ("quota: flush quota_release_work upon quota writeback")
+CC: stable@vger.kernel.org
+Signed-off-by: Shashank A P <shashank.ap@samsung.com>
+Link: https://patch.msgid.link/20250901092905.2115-1-shashank.ap@samsung.com
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/quota/dquot.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
+index 0aa0ed754f2e09..f296872efda9e7 100644
+--- a/fs/quota/dquot.c
++++ b/fs/quota/dquot.c
+@@ -163,6 +163,9 @@ static struct quota_module_name module_names[] = INIT_QUOTA_MODULE_NAMES;
+ /* SLAB cache for dquot structures */
+ static struct kmem_cache *dquot_cachep;
++/* workqueue for work quota_release_work*/
++static struct workqueue_struct *quota_unbound_wq;
++
+ int register_quota_format(struct quota_format_type *fmt)
+ {
+       spin_lock(&dq_list_lock);
+@@ -916,7 +919,7 @@ void dqput(struct dquot *dquot)
+       put_releasing_dquots(dquot);
+       atomic_dec(&dquot->dq_count);
+       spin_unlock(&dq_list_lock);
+-      queue_delayed_work(system_unbound_wq, &quota_release_work, 1);
++      queue_delayed_work(quota_unbound_wq, &quota_release_work, 1);
+ }
+ EXPORT_SYMBOL(dqput);
+@@ -3091,6 +3094,11 @@ static int __init dquot_init(void)
+       if (register_shrinker(&dqcache_shrinker, "dquota-cache"))
+               panic("Cannot register dquot shrinker");
++      quota_unbound_wq = alloc_workqueue("quota_events_unbound",
++                                         WQ_UNBOUND | WQ_MEM_RECLAIM, WQ_MAX_ACTIVE);
++      if (!quota_unbound_wq)
++              panic("Cannot create quota_unbound_wq\n");
++
+       return 0;
+ }
+ fs_initcall(dquot_init);
+-- 
+2.53.0
+
diff --git a/staging-6.1/net-dsa-tag_ksz-do-not-rely-on-skb_mac_header-in-tx-.patch b/staging-6.1/net-dsa-tag_ksz-do-not-rely-on-skb_mac_header-in-tx-.patch
new file mode 100644 (file)
index 0000000..e3b092f
--- /dev/null
@@ -0,0 +1,103 @@
+From 9b9787a1cb4f3666113a93f63344e4ac9f95245a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Apr 2023 01:55:57 +0300
+Subject: net: dsa: tag_ksz: do not rely on skb_mac_header() in TX paths
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit 499b2491d550677b824b828ff431e4ef4d1d3b9d ]
+
+skb_mac_header() will no longer be available in the TX path when
+reverting commit 6d1ccff62780 ("net: reset mac header in
+dev_start_xmit()"). As preparation for that, let's use skb_eth_hdr() to
+get to the Ethernet header's MAC DA instead, helper which assumes this
+header is located at skb->data (assumption which holds true here).
+
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[ sashal: adjusted context in ksz9477_xmit() and ksz9893_xmit() for
+  missing tail tag PRIO support in 6.1 ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/dsa/tag_ksz.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
+index d58bcd16d597d6..459f688cdbf898 100644
+--- a/net/dsa/tag_ksz.c
++++ b/net/dsa/tag_ksz.c
+@@ -50,18 +50,18 @@ static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,
+ static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+       struct dsa_port *dp = dsa_slave_to_port(dev);
++      struct ethhdr *hdr;
+       u8 *tag;
+-      u8 *addr;
+       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+               return NULL;
+       /* Tag encoding */
+       tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
+-      addr = skb_mac_header(skb);
++      hdr = skb_eth_hdr(skb);
+       *tag = 1 << dp->index;
+-      if (is_link_local_ether_addr(addr))
++      if (is_link_local_ether_addr(hdr->h_dest))
+               *tag |= KSZ8795_TAIL_TAG_OVERRIDE;
+       return skb;
+@@ -118,8 +118,8 @@ static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
+                                   struct net_device *dev)
+ {
+       struct dsa_port *dp = dsa_slave_to_port(dev);
++      struct ethhdr *hdr;
+       __be16 *tag;
+-      u8 *addr;
+       u16 val;
+       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+@@ -127,11 +127,11 @@ static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
+       /* Tag encoding */
+       tag = skb_put(skb, KSZ9477_INGRESS_TAG_LEN);
+-      addr = skb_mac_header(skb);
++      hdr = skb_eth_hdr(skb);
+       val = BIT(dp->index);
+-      if (is_link_local_ether_addr(addr))
++      if (is_link_local_ether_addr(hdr->h_dest))
+               val |= KSZ9477_TAIL_TAG_OVERRIDE;
+       *tag = cpu_to_be16(val);
+@@ -177,7 +177,7 @@ static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,
+                                   struct net_device *dev)
+ {
+       struct dsa_port *dp = dsa_slave_to_port(dev);
+-      u8 *addr;
++      struct ethhdr *hdr;
+       u8 *tag;
+       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+@@ -185,11 +185,11 @@ static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,
+       /* Tag encoding */
+       tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
+-      addr = skb_mac_header(skb);
++      hdr = skb_eth_hdr(skb);
+       *tag = BIT(dp->index);
+-      if (is_link_local_ether_addr(addr))
++      if (is_link_local_ether_addr(hdr->h_dest))
+               *tag |= KSZ9893_TAIL_TAG_OVERRIDE;
+       return skb;
+-- 
+2.53.0
+
diff --git a/staging-6.1/sched-fair-only-update-stats-for-allowed-cpus-when-l.patch b/staging-6.1/sched-fair-only-update-stats-for-allowed-cpus-when-l.patch
new file mode 100644 (file)
index 0000000..d53608f
--- /dev/null
@@ -0,0 +1,50 @@
+From 11948d05a7274637803fdfd8fc840da4431e65de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 11 Oct 2025 06:43:22 +0000
+Subject: sched/fair: Only update stats for allowed CPUs when looking for dst
+ group
+
+From: Adam Li <adamli@os.amperecomputing.com>
+
+[ Upstream commit 82d6e01a0699800efd8b048eb584c907ccb47b7a ]
+
+Load imbalance is observed when the workload frequently forks new threads.
+Due to CPU affinity, the workload can run on CPU 0-7 in the first
+group, and only on CPU 8-11 in the second group. CPU 12-15 are always idle.
+
+{ 0 1 2 3 4 5 6 7 } {8 9 10 11 12 13 14 15}
+  * * * * * * * *    * * *  *
+
+When looking for dst group for newly forked threads, in many times
+update_sg_wakeup_stats() reports the second group has more idle CPUs
+than the first group. The scheduler thinks the second group is less
+busy. Then it selects least busy CPUs among CPU 8-11. Therefore CPU 8-11
+can be crowded with newly forked threads, at the same time CPU 0-7
+can be idle.
+
+A task may not use all the CPUs in a schedule group due to CPU affinity.
+Only update schedule group statistics for allowed CPUs.
+
+Signed-off-by: Adam Li <adamli@os.amperecomputing.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sched/fair.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 376d835ca7b45e..23972665264655 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -9550,7 +9550,7 @@ static inline void update_sg_wakeup_stats(struct sched_domain *sd,
+       if (sd->flags & SD_ASYM_CPUCAPACITY)
+               sgs->group_misfit_task_load = 1;
+-      for_each_cpu(i, sched_group_span(group)) {
++      for_each_cpu_and(i, sched_group_span(group), p->cpus_ptr) {
+               struct rq *rq = cpu_rq(i);
+               unsigned int local;
+-- 
+2.53.0
+
diff --git a/staging-6.1/series b/staging-6.1/series
new file mode 100644 (file)
index 0000000..28f3ef7
--- /dev/null
@@ -0,0 +1,6 @@
+smb-server-do-not-require-delete-access-for-non-repl.patch
+sched-fair-only-update-stats-for-allowed-cpus-when-l.patch
+fs-quota-create-dedicated-workqueue-for-quota_releas.patch
+crypto-algif_skcipher-force-synchronous-processing-o.patch
+tools-mm-slabinfo-fix-total_objects-attribute-name.patch
+net-dsa-tag_ksz-do-not-rely-on-skb_mac_header-in-tx-.patch
diff --git a/staging-6.1/smb-server-do-not-require-delete-access-for-non-repl.patch b/staging-6.1/smb-server-do-not-require-delete-access-for-non-repl.patch
new file mode 100644 (file)
index 0000000..7765a4d
--- /dev/null
@@ -0,0 +1,61 @@
+From 50b73d46014528bc824a088f849ff19f4bab469f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 28 Jun 2026 07:42:43 +0000
+Subject: smb/server: do not require delete access for non-replacing links
+
+From: ChenXiaoSong <chenxiaosong@kylinos.cn>
+
+[ Upstream commit 851ed9e09639e0daf79a506ce26097b296ed5518 ]
+
+Reproducer:
+
+  1. server: systemctl start ksmbd
+  2. client: mount -t cifs //${server_ip}/export /mnt
+  3. client: touch /mnt/file; ln /mnt/file /mnt/hardlink
+  4. client err log: ln: failed to create hard link 'hardlink' =>
+     'file': Permission denied
+  5. server err log: ksmbd: no right to delete : 0x80
+
+Fixes: 13f3942f2bf4 ("ksmbd: add per-handle permission check to FILE_LINK_INFORMATION")
+Cc: stable@vger.kernel.org
+Reported-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/server/smb2pdu.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
+index 7bf915e08f909e..09b896739e74cd 100644
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -6060,16 +6060,18 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
+       }
+       case FILE_LINK_INFORMATION:
+       {
+-              if (!(fp->daccess & FILE_DELETE_LE)) {
+-                      pr_err("no right to delete : 0x%x\n", fp->daccess);
+-                      return -EACCES;
+-              }
++              struct smb2_file_link_info *file_info;
+               if (buf_len < sizeof(struct smb2_file_link_info))
+                       return -EINVAL;
+-              return smb2_create_link(work, work->tcon->share_conf,
+-                                      (struct smb2_file_link_info *)buffer,
++              file_info = (struct smb2_file_link_info *)buffer;
++              if (file_info->ReplaceIfExists && !(fp->daccess & FILE_DELETE_LE)) {
++                      pr_err("no right to delete : 0x%x\n", fp->daccess);
++                      return -EACCES;
++              }
++
++              return smb2_create_link(work, work->tcon->share_conf, file_info,
+                                       buf_len, fp->filp,
+                                       work->conn->local_nls);
+       }
+-- 
+2.53.0
+
diff --git a/staging-6.1/tools-mm-slabinfo-fix-total_objects-attribute-name.patch b/staging-6.1/tools-mm-slabinfo-fix-total_objects-attribute-name.patch
new file mode 100644 (file)
index 0000000..b62e6a1
--- /dev/null
@@ -0,0 +1,51 @@
+From c3a89d0b8bad9c68d6a057a4680243f60f72bc04 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 15:59:17 +0800
+Subject: tools/mm/slabinfo: fix total_objects attribute name
+
+From: Yichong Chen <chenyichong@uniontech.com>
+
+[ Upstream commit 892a7864730775c3dbee2a39e9ead4fa8d4256e7 ]
+
+SLUB exports the total_objects sysfs attribute, but slabinfo tries to read
+objects_total. As a result, the lookup fails and the field remains zero.
+
+Use the correct attribute name and rename the corresponding structure
+member to match.
+
+Fixes: 205ab99dd103 ("slub: Update statistics handling for variable order slabs")
+Signed-off-by: Yichong Chen <chenyichong@uniontech.com>
+Cc: <stable@vger.kernel.org>
+Reviewed-by: SeongJae Park <sj@kernel.org>
+Link: https://patch.msgid.link/96556748872BB47E+20260612071359.649946-1-chenyichong@uniontech.com
+Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/vm/slabinfo.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/vm/slabinfo.c b/tools/vm/slabinfo.c
+index 0fffaeedee7672..d26a44e3e68470 100644
+--- a/tools/vm/slabinfo.c
++++ b/tools/vm/slabinfo.c
+@@ -33,7 +33,7 @@ struct slabinfo {
+       unsigned int hwcache_align, object_size, objs_per_slab;
+       unsigned int sanity_checks, slab_size, store_user, trace;
+       int order, poison, reclaim_account, red_zone;
+-      unsigned long partial, objects, slabs, objects_partial, objects_total;
++      unsigned long partial, objects, slabs, objects_partial, total_objects;
+       unsigned long alloc_fastpath, alloc_slowpath;
+       unsigned long free_fastpath, free_slowpath;
+       unsigned long free_frozen, free_add_partial, free_remove_partial;
+@@ -1254,7 +1254,7 @@ static void read_slab_dir(void)
+                       slab->object_size = get_obj("object_size");
+                       slab->objects = get_obj("objects");
+                       slab->objects_partial = get_obj("objects_partial");
+-                      slab->objects_total = get_obj("objects_total");
++                      slab->total_objects = get_obj("total_objects");
+                       slab->objs_per_slab = get_obj("objs_per_slab");
+                       slab->order = get_obj("order");
+                       slab->partial = get_obj("partial");
+-- 
+2.53.0
+
diff --git a/staging-6.12/bpf-prefer-dirty-packs-for-ebpf-allocations.patch b/staging-6.12/bpf-prefer-dirty-packs-for-ebpf-allocations.patch
new file mode 100644 (file)
index 0000000..94370d4
--- /dev/null
@@ -0,0 +1,49 @@
+From 6b85987f6d5b51f6443168cbf6f65d14ae033182 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 14:29:11 -0700
+Subject: bpf: Prefer dirty packs for eBPF allocations
+
+From: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+
+commit b72e29e0f7ee329d89f86db8700c8ea99b4a370a upstream.
+
+The pack allocator only flushes predictors when reusing a dirty pack for
+cBPF, eBPF allocations never trigger a flush. Currently, eBPF picks the
+first free pack, which could be a clean pack. As an optimization, leaving
+a clean pack for cBPF can avoid flushes.
+
+Prefer dirty packs for eBPF and keep clean packs free for cBPF. This
+mirrors the existing cBPF preference for clean packs: each program kind
+prefers the pack that avoids an extra flush, and falls back to the other
+kind only when no preferred pack has room. eBPF reuse of a dirty pack is
+harmless since eBPF being privileged does not flush.
+
+Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/core.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
+index 665f8423b76004..d9131b235f7974 100644
+--- a/kernel/bpf/core.c
++++ b/kernel/bpf/core.c
+@@ -998,10 +998,10 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, bool
+                       goto found_free_area;
+               /*
+                * cBPF reuse of a dirty pack triggers a flush, so prefer a
+-               * clean pack for cBPF. eBPF never flushes, so pick the first
+-               * free pack, dirty or clean.
++               * clean pack for cBPF. eBPF never flushes, so steer it to a
++               * dirty pack and keep clean packs free for cBPF.
+                */
+-              if (!was_classic || !pack->arch_flush_needed)
++              if (was_classic ^ pack->arch_flush_needed)
+                       goto found_free_area;
+               if (!fallback_pack) {
+                       fallback_pack = pack;
+-- 
+2.53.0
+
diff --git a/staging-6.12/bpf-prefer-packs-that-won-t-trigger-an-ibpb-flush-on.patch b/staging-6.12/bpf-prefer-packs-that-won-t-trigger-an-ibpb-flush-on.patch
new file mode 100644 (file)
index 0000000..d403233
--- /dev/null
@@ -0,0 +1,88 @@
+From 80e2b60c3d96b6e053233c63289299add0158931 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 14:28:55 -0700
+Subject: bpf: Prefer packs that won't trigger an IBPB flush on allocation
+
+From: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+
+commit a9b1f19a6a673ba06820898d0f1ad02883ea1639 upstream.
+
+Currently BPF pack allocator picks the chunks from the first available
+pack. While this is okay, it naturally leads to more frequent flushes
+when there are multiple packs in the system that weren't used since the
+last flush.
+
+As an optimization prefer allocating the new programs from packs that
+are unused since last flush. When all packs are dirty, allocation forces
+a flush and marks all packs clean.
+
+Below are some future optimizations ideas:
+
+  1. Currently, the "dirty" tracking is only done at the pack-level.
+     Flush frequency can further be reduced with chunk-level tracking.
+     This requires a new bitmap per-pack to track the dirty state.
+  2. IBPB flush is done on all CPUs, even if only a single CPU ran the
+     BPF program. On a system with hundreds of CPUs this could be a
+     major bottleneck forcing hundreds of IPIs to deliver the flush.
+     The solution is to track the CPUs where a BPF program ran, and
+     issue IBPB only on those CPUs.
+  3. Avoid IBPB when flush is already done at other sources (e.g.
+     context switch).
+
+Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/core.c | 27 ++++++++++++++++++++++++---
+ 1 file changed, 24 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
+index 357af07b9ba480..665f8423b76004 100644
+--- a/kernel/bpf/core.c
++++ b/kernel/bpf/core.c
+@@ -958,8 +958,8 @@ static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_ins
+ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, bool was_classic)
+ {
+       unsigned int nbits = BPF_PROG_SIZE_TO_NBITS(size);
+-      struct bpf_prog_pack *pack;
+-      unsigned long pos;
++      struct bpf_prog_pack *pack, *fallback_pack = NULL;
++      unsigned long pos, fallback_pos = 0;
+       void *ptr = NULL;
+       mutex_lock(&pack_mutex);
+@@ -991,8 +991,29 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, bool
+       list_for_each_entry(pack, &pack_list, list) {
+               pos = bitmap_find_next_zero_area(pack->bitmap, BPF_PROG_CHUNK_COUNT, 0,
+                                                nbits, 0);
+-              if (pos < BPF_PROG_CHUNK_COUNT)
++              if (pos >= BPF_PROG_CHUNK_COUNT)
++                      continue;
++              /* Flush not enabled, use any pack */
++              if (!static_branch_unlikely(&bpf_pred_flush_enabled))
+                       goto found_free_area;
++              /*
++               * cBPF reuse of a dirty pack triggers a flush, so prefer a
++               * clean pack for cBPF. eBPF never flushes, so pick the first
++               * free pack, dirty or clean.
++               */
++              if (!was_classic || !pack->arch_flush_needed)
++                      goto found_free_area;
++              if (!fallback_pack) {
++                      fallback_pack = pack;
++                      fallback_pos = pos;
++              }
++      }
++
++      /* No preferred pack found */
++      if (fallback_pack) {
++              pack = fallback_pack;
++              pos = fallback_pos;
++              goto found_free_area;
+       }
+       pack = alloc_new_pack(bpf_fill_ill_insns);
+-- 
+2.53.0
+
diff --git a/staging-6.12/bpf-restrict-jit-predictor-flush-to-cbpf.patch b/staging-6.12/bpf-restrict-jit-predictor-flush-to-cbpf.patch
new file mode 100644 (file)
index 0000000..42647c2
--- /dev/null
@@ -0,0 +1,212 @@
+From 00660f978885b384a3f033045632df60867b7b09 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 14:28:24 -0700
+Subject: bpf: Restrict JIT predictor flush to cBPF
+
+From: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+
+commit 0bb99f2cfaae6822d734d69722de30af823efdf3 upstream.
+
+Currently predictor flush on memory reuse is done for all BPF JIT
+allocations, but only cBPF programs can be loaded by an unprivileged user.
+eBPF is privileged by default, and flushing predictors for all CPUs on
+every eBPF reuse penalizes the common case for no security benefit.
+
+eBPF allocations can be frequent on busy systems, only flush predictors
+for cBPF programs. Trampoline and dispatcher allocations also skip the
+flush as they are eBPF-only.
+
+  [pawan: backport dropped "was_classic" hunk for arches that do not
+          support pack allocator]
+
+Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/net/bpf_jit_comp.c   |  4 ++--
+ arch/powerpc/net/bpf_jit_comp.c |  2 +-
+ arch/riscv/net/bpf_jit_comp64.c |  2 +-
+ arch/riscv/net/bpf_jit_core.c   |  3 ++-
+ arch/x86/net/bpf_jit_comp.c     |  5 +++--
+ include/linux/filter.h          |  5 +++--
+ kernel/bpf/core.c               | 13 ++++++++-----
+ kernel/bpf/dispatcher.c         |  2 +-
+ 8 files changed, 21 insertions(+), 15 deletions(-)
+
+diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
+index c852749405e0c7..738e56b48f2a21 100644
+--- a/arch/arm64/net/bpf_jit_comp.c
++++ b/arch/arm64/net/bpf_jit_comp.c
+@@ -1881,7 +1881,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
+       image_size = extable_offset + extable_size;
+       ro_header = bpf_jit_binary_pack_alloc(image_size, &ro_image_ptr,
+                                             sizeof(u64), &header, &image_ptr,
+-                                            jit_fill_hole);
++                                            jit_fill_hole, was_classic);
+       if (!ro_header) {
+               prog = orig_prog;
+               goto out_off;
+@@ -2413,7 +2413,7 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
+ void *arch_alloc_bpf_trampoline(unsigned int size)
+ {
+-      return bpf_prog_pack_alloc(size, jit_fill_hole);
++      return bpf_prog_pack_alloc(size, jit_fill_hole, false);
+ }
+ void arch_free_bpf_trampoline(void *image, unsigned int size)
+diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
+index 55c3b64a5f3a40..180175e072adc9 100644
+--- a/arch/powerpc/net/bpf_jit_comp.c
++++ b/arch/powerpc/net/bpf_jit_comp.c
+@@ -174,7 +174,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
+       alloclen = proglen + FUNCTION_DESCR_SIZE + fixup_len + extable_len;
+       fhdr = bpf_jit_binary_pack_alloc(alloclen, &fimage, 4, &hdr, &image,
+-                                            bpf_jit_fill_ill_insns);
++                                       bpf_jit_fill_ill_insns, bpf_prog_was_classic(fp));
+       if (!fhdr) {
+               fp = org_fp;
+               goto out_addrs;
+diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
+index 5895c1b2be203b..43a58e5e123f20 100644
+--- a/arch/riscv/net/bpf_jit_comp64.c
++++ b/arch/riscv/net/bpf_jit_comp64.c
+@@ -1113,7 +1113,7 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
+ void *arch_alloc_bpf_trampoline(unsigned int size)
+ {
+-      return bpf_prog_pack_alloc(size, bpf_fill_ill_insns);
++      return bpf_prog_pack_alloc(size, bpf_fill_ill_insns, false);
+ }
+ void arch_free_bpf_trampoline(void *image, unsigned int size)
+diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c
+index 6de753c667f42a..2f2af89ab4dfe8 100644
+--- a/arch/riscv/net/bpf_jit_core.c
++++ b/arch/riscv/net/bpf_jit_core.c
+@@ -126,7 +126,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
+                               bpf_jit_binary_pack_alloc(prog_size + extable_size,
+                                                         &jit_data->ro_image, sizeof(u32),
+                                                         &jit_data->header, &jit_data->image,
+-                                                        bpf_fill_ill_insns);
++                                                        bpf_fill_ill_insns,
++                                                        bpf_prog_was_classic(prog));
+                       if (!jit_data->ro_header) {
+                               prog = orig_prog;
+                               goto out_offset;
+diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
+index 8cbc26081bdb27..4304596c8fdddd 100644
+--- a/arch/x86/net/bpf_jit_comp.c
++++ b/arch/x86/net/bpf_jit_comp.c
+@@ -3206,7 +3206,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
+ void *arch_alloc_bpf_trampoline(unsigned int size)
+ {
+-      return bpf_prog_pack_alloc(size, jit_fill_hole);
++      return bpf_prog_pack_alloc(size, jit_fill_hole, false);
+ }
+ void arch_free_bpf_trampoline(void *image, unsigned int size)
+@@ -3491,7 +3491,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
+                       /* allocate module memory for x86 insns and extable */
+                       header = bpf_jit_binary_pack_alloc(roundup(proglen, align) + extable_size,
+                                                          &image, align, &rw_header, &rw_image,
+-                                                         jit_fill_hole);
++                                                         jit_fill_hole,
++                                                         bpf_prog_was_classic(prog));
+                       if (!header) {
+                               prog = orig_prog;
+                               goto out_addrs;
+diff --git a/include/linux/filter.h b/include/linux/filter.h
+index 8046cd2a39c6a9..b88a213bcbbe19 100644
+--- a/include/linux/filter.h
++++ b/include/linux/filter.h
+@@ -1262,7 +1262,7 @@ void bpf_jit_free(struct bpf_prog *fp);
+ struct bpf_binary_header *
+ bpf_jit_binary_pack_hdr(const struct bpf_prog *fp);
+-void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns);
++void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, bool was_classic);
+ void bpf_prog_pack_free(void *ptr, u32 size);
+ static inline bool bpf_prog_kallsyms_verify_off(const struct bpf_prog *fp)
+@@ -1276,7 +1276,8 @@ bpf_jit_binary_pack_alloc(unsigned int proglen, u8 **ro_image,
+                         unsigned int alignment,
+                         struct bpf_binary_header **rw_hdr,
+                         u8 **rw_image,
+-                        bpf_jit_fill_hole_t bpf_fill_ill_insns);
++                        bpf_jit_fill_hole_t bpf_fill_ill_insns,
++                        bool was_classic);
+ int bpf_jit_binary_pack_finalize(struct bpf_binary_header *ro_header,
+                                struct bpf_binary_header *rw_header);
+ void bpf_jit_binary_pack_free(struct bpf_binary_header *ro_header,
+diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
+index 5f676320c53beb..29d39092c45778 100644
+--- a/kernel/bpf/core.c
++++ b/kernel/bpf/core.c
+@@ -952,7 +952,7 @@ static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_ins
+       return NULL;
+ }
+-void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)
++void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, bool was_classic)
+ {
+       unsigned int nbits = BPF_PROG_SIZE_TO_NBITS(size);
+       struct bpf_prog_pack *pack;
+@@ -967,7 +967,7 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)
+                * safe because cBPF programs (the unprivileged attack surface)
+                * are bounded well below a pack size.
+                */
+-              if (static_branch_unlikely(&bpf_pred_flush_enabled))
++              if (was_classic && static_branch_unlikely(&bpf_pred_flush_enabled))
+                       pr_warn_once("BPF: Predictors not flushed for allocations greater than BPF_PROG_PACK_SIZE\n");
+               size = round_up(size, PAGE_SIZE);
+               ptr = bpf_jit_alloc_exec(size);
+@@ -999,7 +999,9 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)
+       pos = 0;
+ found_free_area:
+-      static_call_cond(bpf_arch_pred_flush)();
++      /* Flush only for cBPF as it may contain a crafted gadget */
++      if (static_branch_unlikely(&bpf_pred_flush_enabled) && was_classic)
++              static_call_cond(bpf_arch_pred_flush)();
+       bitmap_set(pack->bitmap, pos, nbits);
+       ptr = (void *)(pack->ptr) + (pos << BPF_PROG_CHUNK_SHIFT);
+@@ -1159,7 +1161,8 @@ bpf_jit_binary_pack_alloc(unsigned int proglen, u8 **image_ptr,
+                         unsigned int alignment,
+                         struct bpf_binary_header **rw_header,
+                         u8 **rw_image,
+-                        bpf_jit_fill_hole_t bpf_fill_ill_insns)
++                        bpf_jit_fill_hole_t bpf_fill_ill_insns,
++                        bool was_classic)
+ {
+       struct bpf_binary_header *ro_header;
+       u32 size, hole, start;
+@@ -1172,7 +1175,7 @@ bpf_jit_binary_pack_alloc(unsigned int proglen, u8 **image_ptr,
+       if (bpf_jit_charge_modmem(size))
+               return NULL;
+-      ro_header = bpf_prog_pack_alloc(size, bpf_fill_ill_insns);
++      ro_header = bpf_prog_pack_alloc(size, bpf_fill_ill_insns, was_classic);
+       if (!ro_header) {
+               bpf_jit_uncharge_modmem(size);
+               return NULL;
+diff --git a/kernel/bpf/dispatcher.c b/kernel/bpf/dispatcher.c
+index b77db7413f8c70..ea2d60dc1feeb7 100644
+--- a/kernel/bpf/dispatcher.c
++++ b/kernel/bpf/dispatcher.c
+@@ -145,7 +145,7 @@ void bpf_dispatcher_change_prog(struct bpf_dispatcher *d, struct bpf_prog *from,
+       mutex_lock(&d->mutex);
+       if (!d->image) {
+-              d->image = bpf_prog_pack_alloc(PAGE_SIZE, bpf_jit_fill_hole_with_zero);
++              d->image = bpf_prog_pack_alloc(PAGE_SIZE, bpf_jit_fill_hole_with_zero, false);
+               if (!d->image)
+                       goto out;
+               d->rw_image = bpf_jit_alloc_exec(PAGE_SIZE);
+-- 
+2.53.0
+
diff --git a/staging-6.12/bpf-skip-redundant-ibpb-in-pack-allocator.patch b/staging-6.12/bpf-skip-redundant-ibpb-in-pack-allocator.patch
new file mode 100644 (file)
index 0000000..d2b5123
--- /dev/null
@@ -0,0 +1,81 @@
+From 356eadd0a01700669bf1a2bb0beb98947c247e76 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 14:28:39 -0700
+Subject: bpf: Skip redundant IBPB in pack allocator
+
+From: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+
+commit a23c1c5396a91680703360d1ee28a44657c503c4 upstream.
+
+bpf_prog_pack_alloc() issues IBPB on all CPUs on every cBPF allocation,
+even when reusing chunks from an existing pack where no new memory was
+touched since the last IBPB.
+
+Since IBPB on all CPUs is heavy, Dave Hansen suggested to track allocation
+since last IBPB, and only issue IBPB at reuse for the chunks that have not
+seen an IBPB since they were last freed.
+
+Track per-pack whether an IBPB is needed via arch_flush_needed. Set it when
+allocating a chunk, reset on IBPB flush. On reuse, conditionally issue the
+flush. Since IBPB invalidates all BTB entries, clear the flag on all packs
+after flushing.
+
+Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/core.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
+index 29d39092c45778..357af07b9ba480 100644
+--- a/kernel/bpf/core.c
++++ b/kernel/bpf/core.c
+@@ -885,6 +885,7 @@ int bpf_jit_add_poke_descriptor(struct bpf_prog *prog,
+ struct bpf_prog_pack {
+       struct list_head list;
+       void *ptr;
++      bool arch_flush_needed;
+       unsigned long bitmap[];
+ };
+@@ -938,6 +939,8 @@ static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_ins
+       bpf_fill_ill_insns(pack->ptr, BPF_PROG_PACK_SIZE);
+       bitmap_zero(pack->bitmap, BPF_PROG_PACK_SIZE / BPF_PROG_CHUNK_SIZE);
++      if (static_branch_unlikely(&bpf_pred_flush_enabled))
++              pack->arch_flush_needed = true;
+       set_vm_flush_reset_perms(pack->ptr);
+       err = set_memory_rox((unsigned long)pack->ptr,
+                            BPF_PROG_PACK_SIZE / PAGE_SIZE);
+@@ -1000,8 +1003,15 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, bool
+ found_free_area:
+       /* Flush only for cBPF as it may contain a crafted gadget */
+-      if (static_branch_unlikely(&bpf_pred_flush_enabled) && was_classic)
++      if (static_branch_unlikely(&bpf_pred_flush_enabled) &&
++          pack->arch_flush_needed &&
++          was_classic) {
++              struct bpf_prog_pack *p;
++
+               static_call_cond(bpf_arch_pred_flush)();
++              list_for_each_entry(p, &pack_list, list)
++                      p->arch_flush_needed = false;
++      }
+       bitmap_set(pack->bitmap, pos, nbits);
+       ptr = (void *)(pack->ptr) + (pos << BPF_PROG_CHUNK_SHIFT);
+@@ -1039,6 +1049,9 @@ void bpf_prog_pack_free(void *ptr, u32 size)
+                 "bpf_prog_pack bug: missing bpf_arch_text_invalidate?\n");
+       bitmap_clear(pack->bitmap, pos, nbits);
++
++      if (static_branch_unlikely(&bpf_pred_flush_enabled))
++              pack->arch_flush_needed = true;
+       if (bitmap_find_next_zero_area(pack->bitmap, BPF_PROG_CHUNK_COUNT, 0,
+                                      BPF_PROG_CHUNK_COUNT, 0) == 0) {
+               list_del(&pack->list);
+-- 
+2.53.0
+
diff --git a/staging-6.12/bpf-support-for-hardening-against-jit-spraying.patch b/staging-6.12/bpf-support-for-hardening-against-jit-spraying.patch
new file mode 100644 (file)
index 0000000..52ce669
--- /dev/null
@@ -0,0 +1,120 @@
+From 2ba2e0e742c02563c5286e7f5eb8db5c34218027 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 14:27:54 -0700
+Subject: bpf: Support for hardening against JIT spraying
+
+From: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+
+commit 96cce16e26dd02a8678f1e87f88a4b5cdb63b995 upstream.
+
+The BPF JIT allocator packs many small programs into larger executable
+allocations and reuses space within those allocations as programs are
+loaded and freed. When fresh code is written into space that a previous
+program occupied, an indirect jump into the new program can reuse a branch
+prediction left behind by the old one.
+
+Flush the indirect branch predictors before reusing JIT memory so that
+indirect jumps into a newly written program don't reuse predictions from an
+old program that occupied the same space.
+
+Introduce bpf_arch_pred_flush_enabled static key and bpf_arch_pred_flush
+static call for flushing the branch predictors on JIT memory reuse.
+Architectures that need a flush, can update it to a predictor flush
+function. By default, its a NOP and does not emit any CALL.
+
+Allocations larger than a pack are not covered by this flush. That is safe
+because cBPF programs (the unprivileged attack surface) are bounded well
+below a pack size. Issue a warning if this assumption is ever violated
+while the flush is active.
+
+Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/filter.h | 10 ++++++++++
+ kernel/bpf/core.c      | 19 +++++++++++++++++++
+ 2 files changed, 29 insertions(+)
+
+diff --git a/include/linux/filter.h b/include/linux/filter.h
+index a91f2babf4253d..8046cd2a39c6a9 100644
+--- a/include/linux/filter.h
++++ b/include/linux/filter.h
+@@ -22,6 +22,7 @@
+ #include <linux/vmalloc.h>
+ #include <linux/sockptr.h>
+ #include <crypto/sha1.h>
++#include <linux/static_call.h>
+ #include <linux/u64_stats_sync.h>
+ #include <net/sch_generic.h>
+@@ -1238,6 +1239,15 @@ extern long bpf_jit_limit_max;
+ typedef void (*bpf_jit_fill_hole_t)(void *area, unsigned int size);
++/*
++ * Flush the indirect branch predictors before reusing JIT memory, so that
++ * indirect jumps into a newly written program don't reuse predictions left
++ * behind by an old program that occupied the same space.
++ */
++void bpf_arch_pred_flush(void);
++DECLARE_STATIC_CALL(bpf_arch_pred_flush, bpf_arch_pred_flush);
++DECLARE_STATIC_KEY_FALSE(bpf_pred_flush_enabled);
++
+ void bpf_jit_fill_hole_with_zero(void *area, unsigned int size);
+ struct bpf_binary_header *
+diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
+index 517710c89fa505..5f676320c53beb 100644
+--- a/kernel/bpf/core.c
++++ b/kernel/bpf/core.c
+@@ -38,6 +38,7 @@
+ #include <linux/bpf_mem_alloc.h>
+ #include <linux/memcontrol.h>
+ #include <linux/execmem.h>
++#include <linux/static_call.h>
+ #include <asm/barrier.h>
+ #include <linux/unaligned.h>
+@@ -892,6 +893,15 @@ void bpf_jit_fill_hole_with_zero(void *area, unsigned int size)
+       memset(area, 0, size);
+ }
++DEFINE_STATIC_CALL_NULL(bpf_arch_pred_flush, bpf_arch_pred_flush);
++
++/*
++ * Enabled once bpf_arch_pred_flush points at a real flush routine. Lets the
++ * pack allocator test "is a predictor flush wired up at all" with a cheap
++ * static branch instead of repeatedly querying the static call target.
++ */
++DEFINE_STATIC_KEY_FALSE(bpf_pred_flush_enabled);
++
+ #define BPF_PROG_SIZE_TO_NBITS(size)  (round_up(size, BPF_PROG_CHUNK_SIZE) / BPF_PROG_CHUNK_SIZE)
+ static DEFINE_MUTEX(pack_mutex);
+@@ -951,6 +961,14 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)
+       mutex_lock(&pack_mutex);
+       if (size > BPF_PROG_PACK_SIZE) {
++              /*
++               * Allocations larger than a pack get their own pages, and
++               * predictors are not flushed for such allocation. This is only
++               * safe because cBPF programs (the unprivileged attack surface)
++               * are bounded well below a pack size.
++               */
++              if (static_branch_unlikely(&bpf_pred_flush_enabled))
++                      pr_warn_once("BPF: Predictors not flushed for allocations greater than BPF_PROG_PACK_SIZE\n");
+               size = round_up(size, PAGE_SIZE);
+               ptr = bpf_jit_alloc_exec(size);
+               if (ptr) {
+@@ -981,6 +999,7 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)
+       pos = 0;
+ found_free_area:
++      static_call_cond(bpf_arch_pred_flush)();
+       bitmap_set(pack->bitmap, pos, nbits);
+       ptr = (void *)(pack->ptr) + (pos << BPF_PROG_CHUNK_SHIFT);
+-- 
+2.53.0
+
diff --git a/staging-6.12/crypto-algif_skcipher-force-synchronous-processing.patch b/staging-6.12/crypto-algif_skcipher-force-synchronous-processing.patch
new file mode 100644 (file)
index 0000000..60544b2
--- /dev/null
@@ -0,0 +1,159 @@
+From f8fc4098208ede0a7aefd5cf4fbc489da12a2d96 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 02:58:36 +0000
+Subject: crypto: algif_skcipher - force synchronous processing
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+
+The AIO/async path in skcipher_recvmsg() passes the socket-wide ctx->iv
+directly into the skcipher request. After io_submit() the socket lock is
+dropped and the request is processed asynchronously by a worker (e.g.
+cryptd), which dereferences ctx->iv only later.
+
+A concurrent sendmsg(ALG_SET_IV) on the same socket can overwrite ctx->iv
+inside this window, so the in-flight request runs under an
+attacker-controlled IV. For CTR and other stream modes this causes
+IV/keystream reuse and allows an unprivileged user to recover the
+plaintext of a concurrent operation.
+
+Snapshotting ctx->iv into per-request storage for the async path is not
+sufficient here. For ciphers with statesize == 0 - which includes cbc
+and ctr - skcipher_prepare_alg() installs skcipher_noimport()/
+skcipher_noexport(), so ctx->state carries nothing and the MSG_MORE
+inter-chunk IV chaining is carried solely by the in-place req->iv
+writeback. A snapshot redirects that writeback into per-request memory
+that af_alg_free_resources() releases on completion, so AIO + MSG_MORE
+with cbc/ctr would silently produce wrong output. Writing the IV back
+from the completion callback instead is not possible either: that would
+require lock_sock() there, but the callback can run in softirq/atomic
+context, so it must not sleep.
+
+Make the operation synchronous instead. ctx->iv is then only ever
+dereferenced under the socket lock held by recvmsg(), which removes the
+race, and the req->iv writeback lands in ctx->iv as before, which keeps
+MSG_MORE chaining intact for statesize == 0 ciphers. The ctx->state
+import/export path is unchanged for ciphers that do have state.
+
+This is equivalent to the upstream resolution: commit fcc77d33a34c
+("net: Remove support for AIO on sockets") removed the AIO socket path
+across net/ entirely, producing the same end state for this file -
+algif_skcipher never processes an AIO request asynchronously. After this
+patch, _skcipher_recvmsg() matches mainline's crypto/algif_skcipher.c as
+it stands today, including the same now-dead -EIOCBQUEUED check. This
+patch deviates from that commit deliberately: rather than removing AIO
+socket support tree-wide, which would be far too invasive for stable, it
+removes only the AIO branch in crypto/algif_skcipher.c. io_submit() now
+completes synchronously, which is valid for the AIO interface; AF_ALG
+async is rarely used in practice.
+
+The -EIOCBQUEUED check in skcipher_recvmsg() is now dead but harmless,
+and is left alone to keep the fix minimal.
+
+Fixes: e870456d8e7c ("crypto: algif_skcipher - overhaul memory management")
+Cc: <stable@vger.kernel.org>
+Reported-by: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+Signed-off-by: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ crypto/algif_skcipher.c | 75 +++++++++++++----------------------------
+ 1 file changed, 24 insertions(+), 51 deletions(-)
+
+diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
+index ba0a17fd95aca2..35ebc3e0201b04 100644
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -79,20 +79,6 @@ static int algif_skcipher_export(struct sock *sk, struct skcipher_request *req)
+       return err;
+ }
+-static void algif_skcipher_done(void *data, int err)
+-{
+-      struct af_alg_async_req *areq = data;
+-      struct sock *sk = areq->sk;
+-
+-      if (err)
+-              goto out;
+-
+-      err = algif_skcipher_export(sk, &areq->cra_u.skcipher_req);
+-
+-out:
+-      af_alg_async_cb(data, err);
+-}
+-
+ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
+                            size_t ignored, int flags)
+ {
+@@ -171,43 +157,30 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
+               cflags |= CRYPTO_SKCIPHER_REQ_CONT;
+       }
+-      if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
+-              /* AIO operation */
+-              sock_hold(sk);
+-              areq->iocb = msg->msg_iocb;
+-
+-              /* Remember output size that will be generated. */
+-              areq->outlen = len;
+-
+-              skcipher_request_set_callback(&areq->cra_u.skcipher_req,
+-                                            cflags |
+-                                            CRYPTO_TFM_REQ_MAY_SLEEP,
+-                                            algif_skcipher_done, areq);
+-              err = ctx->enc ?
+-                      crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
+-                      crypto_skcipher_decrypt(&areq->cra_u.skcipher_req);
+-
+-              /* AIO operation in progress */
+-              if (err == -EINPROGRESS)
+-                      return -EIOCBQUEUED;
+-
+-              sock_put(sk);
+-      } else {
+-              /* Synchronous operation */
+-              skcipher_request_set_callback(&areq->cra_u.skcipher_req,
+-                                            cflags |
+-                                            CRYPTO_TFM_REQ_MAY_SLEEP |
+-                                            CRYPTO_TFM_REQ_MAY_BACKLOG,
+-                                            crypto_req_done, &ctx->wait);
+-              err = crypto_wait_req(ctx->enc ?
+-                      crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
+-                      crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
+-                                               &ctx->wait);
+-
+-              if (!err)
+-                      err = algif_skcipher_export(
+-                              sk, &areq->cra_u.skcipher_req);
+-      }
++      /*
++       * Force synchronous processing.  The async (AIO) path passed the
++       * socket-wide ctx->iv into the request, which the worker
++       * dereferenced after the socket lock had been dropped, letting a
++       * concurrent sendmsg(ALG_SET_IV) inject an attacker IV.  Mainline
++       * removed the AIO socket path in commit fcc77d33a34c ("net: Remove
++       * support for AIO on sockets"); the minimal stable fix is to always
++       * complete synchronously, so ctx->iv is only ever dereferenced under
++       * the socket lock.  This also keeps the IV chaining intact: for
++       * ciphers with statesize == 0 (e.g. ctr, cbc) the chained IV is
++       * carried by the req->iv writeback into ctx->iv, which is only
++       * consistent on the synchronous path.
++       */
++      skcipher_request_set_callback(&areq->cra_u.skcipher_req,
++                                    cflags |
++                                    CRYPTO_TFM_REQ_MAY_SLEEP |
++                                    CRYPTO_TFM_REQ_MAY_BACKLOG,
++                                    crypto_req_done, &ctx->wait);
++      err = crypto_wait_req(ctx->enc ?
++              crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
++              crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
++                               &ctx->wait);
++      if (!err)
++              err = algif_skcipher_export(sk, &areq->cra_u.skcipher_req);
+ free:
+       af_alg_free_resources(areq);
+-- 
+2.53.0
+
diff --git a/staging-6.12/iommu-pass-old-domain-to-set_dev_pasid-op.patch b/staging-6.12/iommu-pass-old-domain-to-set_dev_pasid-op.patch
new file mode 100644 (file)
index 0000000..dbcd0e6
--- /dev/null
@@ -0,0 +1,164 @@
+From 376d5ee5a20ac6c45f29572a06e1ab48695755c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Nov 2024 10:13:52 +0800
+Subject: iommu: Pass old domain to set_dev_pasid op
+
+From: Yi Liu <yi.l.liu@intel.com>
+
+[ Upstream commit b45a3777ceabbe08ab7a6e97f258191c07cbab8d ]
+
+To support domain replacement for pasid, the underlying iommu driver needs
+to know the old domain hence be able to clean up the existing attachment.
+It would be much convenient for iommu layer to pass down the old domain.
+Otherwise, iommu drivers would need to track domain for pasids by
+themselves, this would duplicate code among the iommu drivers. Or iommu
+drivers would rely group->pasid_array to get domain, which may not always
+the correct one.
+
+Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
+Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
+Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
+Reviewed-by: Vasant Hegde <vasant.hegde@amd.com>
+Signed-off-by: Yi Liu <yi.l.liu@intel.com>
+Link: https://lore.kernel.org/r/20241107122234.7424-2-yi.l.liu@intel.com
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Stable-dep-of: f46452c3df7a ("iommu/vt-d: Clear Present bit before tearing down scalable-mode context entry")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/amd/amd_iommu.h                   | 3 ++-
+ drivers/iommu/amd/pasid.c                       | 3 ++-
+ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 3 ++-
+ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c     | 3 ++-
+ drivers/iommu/intel/iommu.c                     | 6 ++++--
+ drivers/iommu/intel/svm.c                       | 3 ++-
+ drivers/iommu/iommu.c                           | 3 ++-
+ include/linux/iommu.h                           | 2 +-
+ 8 files changed, 17 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
+index 6fac9ee8dd3ed0..27eedfb47d8b69 100644
+--- a/drivers/iommu/amd/amd_iommu.h
++++ b/drivers/iommu/amd/amd_iommu.h
+@@ -52,7 +52,8 @@ struct iommu_domain *amd_iommu_domain_alloc_sva(struct device *dev,
+                                               struct mm_struct *mm);
+ void amd_iommu_domain_free(struct iommu_domain *dom);
+ int iommu_sva_set_dev_pasid(struct iommu_domain *domain,
+-                          struct device *dev, ioasid_t pasid);
++                          struct device *dev, ioasid_t pasid,
++                          struct iommu_domain *old);
+ void amd_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid,
+                               struct iommu_domain *domain);
+diff --git a/drivers/iommu/amd/pasid.c b/drivers/iommu/amd/pasid.c
+index 0657b9373be547..d1dfc745f55e3e 100644
+--- a/drivers/iommu/amd/pasid.c
++++ b/drivers/iommu/amd/pasid.c
+@@ -100,7 +100,8 @@ static const struct mmu_notifier_ops sva_mn = {
+ };
+ int iommu_sva_set_dev_pasid(struct iommu_domain *domain,
+-                          struct device *dev, ioasid_t pasid)
++                          struct device *dev, ioasid_t pasid,
++                          struct iommu_domain *old)
+ {
+       struct pdom_dev_data *pdom_dev_data;
+       struct protection_domain *sva_pdom = to_pdomain(domain);
+diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+index 32f3e91a7d7f5d..6cb2fbf4303746 100644
+--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
++++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+@@ -332,7 +332,8 @@ void arm_smmu_sva_notifier_synchronize(void)
+ }
+ static int arm_smmu_sva_set_dev_pasid(struct iommu_domain *domain,
+-                                    struct device *dev, ioasid_t id)
++                                    struct device *dev, ioasid_t id,
++                                    struct iommu_domain *old)
+ {
+       struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
+       struct arm_smmu_master *master = dev_iommu_priv_get(dev);
+diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+index 04e0058daab815..ebc25e5a8f55e6 100644
+--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
++++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+@@ -2879,7 +2879,8 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
+ }
+ static int arm_smmu_s1_set_dev_pasid(struct iommu_domain *domain,
+-                                    struct device *dev, ioasid_t id)
++                                   struct device *dev, ioasid_t id,
++                                   struct iommu_domain *old)
+ {
+       struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
+       struct arm_smmu_master *master = dev_iommu_priv_get(dev);
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index 18022d17c492b6..3455e75c59c4be 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -4338,7 +4338,8 @@ static void intel_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid,
+ }
+ static int intel_iommu_set_dev_pasid(struct iommu_domain *domain,
+-                                   struct device *dev, ioasid_t pasid)
++                                   struct device *dev, ioasid_t pasid,
++                                   struct iommu_domain *old)
+ {
+       struct device_domain_info *info = dev_iommu_priv_get(dev);
+       struct dmar_domain *dmar_domain = to_dmar_domain(domain);
+@@ -4624,7 +4625,8 @@ static int identity_domain_attach_dev(struct iommu_domain *domain, struct device
+ }
+ static int identity_domain_set_dev_pasid(struct iommu_domain *domain,
+-                                       struct device *dev, ioasid_t pasid)
++                                       struct device *dev, ioasid_t pasid,
++                                       struct iommu_domain *old)
+ {
+       struct device_domain_info *info = dev_iommu_priv_get(dev);
+       struct intel_iommu *iommu = info->iommu;
+diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
+index 3cc43a958b4dc7..4a2bd65614ad2d 100644
+--- a/drivers/iommu/intel/svm.c
++++ b/drivers/iommu/intel/svm.c
+@@ -111,7 +111,8 @@ static const struct mmu_notifier_ops intel_mmuops = {
+ };
+ static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
+-                                 struct device *dev, ioasid_t pasid)
++                                 struct device *dev, ioasid_t pasid,
++                                 struct iommu_domain *old)
+ {
+       struct device_domain_info *info = dev_iommu_priv_get(dev);
+       struct dmar_domain *dmar_domain = to_dmar_domain(domain);
+diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
+index 62e1d637250318..fdebfe5380bac2 100644
+--- a/drivers/iommu/iommu.c
++++ b/drivers/iommu/iommu.c
+@@ -3342,7 +3342,8 @@ static int __iommu_set_group_pasid(struct iommu_domain *domain,
+       for_each_group_device(group, device) {
+               if (device->dev->iommu->max_pasids > 0) {
+-                      ret = domain->ops->set_dev_pasid(domain, device->dev, pasid);
++                      ret = domain->ops->set_dev_pasid(domain, device->dev,
++                                                       pasid, NULL);
+                       if (ret)
+                               goto err_revert;
+               }
+diff --git a/include/linux/iommu.h b/include/linux/iommu.h
+index 10f7b1df072361..dc7ceb9406eda7 100644
+--- a/include/linux/iommu.h
++++ b/include/linux/iommu.h
+@@ -642,7 +642,7 @@ struct iommu_ops {
+ struct iommu_domain_ops {
+       int (*attach_dev)(struct iommu_domain *domain, struct device *dev);
+       int (*set_dev_pasid)(struct iommu_domain *domain, struct device *dev,
+-                           ioasid_t pasid);
++                           ioasid_t pasid, struct iommu_domain *old);
+       int (*map_pages)(struct iommu_domain *domain, unsigned long iova,
+                        phys_addr_t paddr, size_t pgsize, size_t pgcount,
+-- 
+2.53.0
+
diff --git a/staging-6.12/iommu-vt-d-cleanup-intel_context_flush_present.patch b/staging-6.12/iommu-vt-d-cleanup-intel_context_flush_present.patch
new file mode 100644 (file)
index 0000000..c9340b2
--- /dev/null
@@ -0,0 +1,137 @@
+From 4a7f5aee99c7913457dfb9f1673a313c3521ca1d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Mar 2025 10:47:49 +0800
+Subject: iommu/vt-d: Cleanup intel_context_flush_present()
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+[ Upstream commit 4c293add5874038dc82ef579663dd86744d8e872 ]
+
+The intel_context_flush_present() is called in places where either the
+scalable mode is disabled, or scalable mode is enabled but all PASID
+entries are known to be non-present. In these cases, the flush_domains
+path within intel_context_flush_present() will never execute. This dead
+code is therefore removed.
+
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Tested-by: Zhangfei Gao <zhangfei.gao@linaro.org>
+Link: https://lore.kernel.org/r/20250228092631.3425464-7-baolu.lu@linux.intel.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Stable-dep-of: f46452c3df7a ("iommu/vt-d: Clear Present bit before tearing down scalable-mode context entry")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/iommu.c |  4 ++--
+ drivers/iommu/intel/iommu.h |  5 ++---
+ drivers/iommu/intel/pasid.c | 41 +++++++------------------------------
+ 3 files changed, 11 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index 3455e75c59c4be..a1ec11c90a8b4c 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -1917,7 +1917,7 @@ static void domain_context_clear_one(struct device_domain_info *info, u8 bus, u8
+       context_clear_present(context);
+       __iommu_flush_cache(iommu, context, sizeof(*context));
+       spin_unlock(&iommu->lock);
+-      intel_context_flush_present(info, context, did, true);
++      intel_context_flush_no_pasid(info, context, did);
+       context_clear_entry(context);
+       __iommu_flush_cache(iommu, context, sizeof(*context));
+ }
+@@ -4153,7 +4153,7 @@ static int context_flip_pri(struct device_domain_info *info, bool enable)
+       if (!ecap_coherent(iommu->ecap))
+               clflush_cache_range(context, sizeof(*context));
+-      intel_context_flush_present(info, context, did, true);
++      intel_context_flush_no_pasid(info, context, did);
+       spin_unlock(&iommu->lock);
+       return 0;
+diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
+index e46eb1d3fba29d..8a91a8d5661418 100644
+--- a/drivers/iommu/intel/iommu.h
++++ b/drivers/iommu/intel/iommu.h
+@@ -1296,9 +1296,8 @@ void cache_tag_flush_all(struct dmar_domain *domain);
+ void cache_tag_flush_range_np(struct dmar_domain *domain, unsigned long start,
+                             unsigned long end);
+-void intel_context_flush_present(struct device_domain_info *info,
+-                               struct context_entry *context,
+-                               u16 did, bool affect_domains);
++void intel_context_flush_no_pasid(struct device_domain_info *info,
++                                struct context_entry *context, u16 did);
+ int intel_iommu_enable_prq(struct intel_iommu *iommu);
+ int intel_iommu_finish_prq(struct intel_iommu *iommu);
+diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
+index 5e63b5d4577f75..0e0c6cf2d3f4d3 100644
+--- a/drivers/iommu/intel/pasid.c
++++ b/drivers/iommu/intel/pasid.c
+@@ -717,7 +717,7 @@ static void device_pasid_table_teardown(struct device *dev, u8 bus, u8 devfn)
+       context_clear_entry(context);
+       __iommu_flush_cache(iommu, context, sizeof(*context));
+       spin_unlock(&iommu->lock);
+-      intel_context_flush_present(info, context, did, false);
++      intel_context_flush_no_pasid(info, context, did);
+ }
+ static int pci_pasid_table_teardown(struct pci_dev *pdev, u16 alias, void *data)
+@@ -913,17 +913,15 @@ static void __context_flush_dev_iotlb(struct device_domain_info *info)
+ /*
+  * Cache invalidations after change in a context table entry that was present
+- * according to the Spec 6.5.3.3 (Guidance to Software for Invalidations). If
+- * IOMMU is in scalable mode and all PASID table entries of the device were
+- * non-present, set flush_domains to false. Otherwise, true.
++ * according to the Spec 6.5.3.3 (Guidance to Software for Invalidations).
++ * This helper can only be used when IOMMU is working in the legacy mode or
++ * IOMMU is in scalable mode but all PASID table entries of the device are
++ * non-present.
+  */
+-void intel_context_flush_present(struct device_domain_info *info,
+-                               struct context_entry *context,
+-                               u16 did, bool flush_domains)
++void intel_context_flush_no_pasid(struct device_domain_info *info,
++                                struct context_entry *context, u16 did)
+ {
+       struct intel_iommu *iommu = info->iommu;
+-      struct pasid_entry *pte;
+-      int i;
+       /*
+        * Device-selective context-cache invalidation. The Domain-ID field
+@@ -946,30 +944,5 @@ void intel_context_flush_present(struct device_domain_info *info,
+               return;
+       }
+-      /*
+-       * For scalable mode:
+-       * - Domain-selective PASID-cache invalidation to affected domains
+-       * - Domain-selective IOTLB invalidation to affected domains
+-       * - Global Device-TLB invalidation to affected functions
+-       */
+-      if (flush_domains) {
+-              /*
+-               * If the IOMMU is running in scalable mode and there might
+-               * be potential PASID translations, the caller should hold
+-               * the lock to ensure that context changes and cache flushes
+-               * are atomic.
+-               */
+-              assert_spin_locked(&iommu->lock);
+-              for (i = 0; i < info->pasid_table->max_pasid; i++) {
+-                      pte = intel_pasid_get_entry(info->dev, i);
+-                      if (!pte || !pasid_pte_is_present(pte))
+-                              continue;
+-
+-                      did = pasid_get_domain_id(pte);
+-                      qi_flush_pasid_cache(iommu, did, QI_PC_ALL_PASIDS, 0);
+-                      iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
+-              }
+-      }
+-
+       __context_flush_dev_iotlb(info);
+ }
+-- 
+2.53.0
+
diff --git a/staging-6.12/iommu-vt-d-clear-present-bit-before-tearing-down-con.patch b/staging-6.12/iommu-vt-d-clear-present-bit-before-tearing-down-con.patch
new file mode 100644 (file)
index 0000000..3083aa6
--- /dev/null
@@ -0,0 +1,129 @@
+From 3f3d57050d84437f0bc5d160b470169a81485ddb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 01:21:23 +0300
+Subject: iommu/vt-d: Clear Present bit before tearing down context entry
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+[ Upstream commit c1e4f1dccbe9d7656d1c6872ebeadb5992d0aaa2 ]
+
+When tearing down a context entry, the current implementation zeros the
+entire 128-bit entry using multiple 64-bit writes. This creates a window
+where the hardware can fetch a "torn" entry — where some fields are
+already zeroed while the 'Present' bit is still set — leading to
+unpredictable behavior or spurious faults.
+
+While x86 provides strong write ordering, the compiler may reorder writes
+to the two 64-bit halves of the context entry. Even without compiler
+reordering, the hardware fetch is not guaranteed to be atomic with
+respect to multiple CPU writes.
+
+Align with the "Guidance to Software for Invalidations" in the VT-d spec
+(Section 6.5.3.3) by implementing the recommended ownership handshake:
+
+1. Clear only the 'Present' (P) bit of the context entry first to
+   signal the transition of ownership from hardware to software.
+2. Use dma_wmb() to ensure the cleared bit is visible to the IOMMU.
+3. Perform the required cache and context-cache invalidation to ensure
+   hardware no longer has cached references to the entry.
+4. Fully zero out the entry only after the invalidation is complete.
+
+Also, add a dma_wmb() to context_set_present() to ensure the entry
+is fully initialized before the 'Present' bit becomes visible.
+
+Fixes: ba39592764ed2 ("Intel IOMMU: Intel IOMMU driver")
+Reported-by: Dmytro Maluka <dmaluka@chromium.org>
+Closes: https://lore.kernel.org/all/aTG7gc7I5wExai3S@google.com/
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Reviewed-by: Dmytro Maluka <dmaluka@chromium.org>
+Reviewed-by: Samiullah Khawaja <skhawaja@google.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/20260120061816.2132558-3-baolu.lu@linux.intel.com
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Konstantin Andreev <andreev@swemel.ru>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/iommu.c |  4 +++-
+ drivers/iommu/intel/iommu.h | 21 ++++++++++++++++++++-
+ drivers/iommu/intel/pasid.c |  5 ++++-
+ 3 files changed, 27 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index cce5a19b5d330e..18022d17c492b6 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -1914,10 +1914,12 @@ static void domain_context_clear_one(struct device_domain_info *info, u8 bus, u8
+       }
+       did = context_domain_id(context);
+-      context_clear_entry(context);
++      context_clear_present(context);
+       __iommu_flush_cache(iommu, context, sizeof(*context));
+       spin_unlock(&iommu->lock);
+       intel_context_flush_present(info, context, did, true);
++      context_clear_entry(context);
++      __iommu_flush_cache(iommu, context, sizeof(*context));
+ }
+ static int domain_setup_first_level(struct intel_iommu *iommu,
+diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
+index b33d8888d7ebd7..e46eb1d3fba29d 100644
+--- a/drivers/iommu/intel/iommu.h
++++ b/drivers/iommu/intel/iommu.h
+@@ -958,7 +958,26 @@ static inline unsigned long virt_to_dma_pfn(void *p)
+ static inline void context_set_present(struct context_entry *context)
+ {
+-      context->lo |= 1;
++      u64 val;
++
++      dma_wmb();
++      val = READ_ONCE(context->lo) | 1;
++      WRITE_ONCE(context->lo, val);
++}
++
++/*
++ * Clear the Present (P) bit (bit 0) of a context table entry. This initiates
++ * the transition of the entry's ownership from hardware to software. The
++ * caller is responsible for fulfilling the invalidation handshake recommended
++ * by the VT-d spec, Section 6.5.3.3 (Guidance to Software for Invalidations).
++ */
++static inline void context_clear_present(struct context_entry *context)
++{
++      u64 val;
++
++      val = READ_ONCE(context->lo) & GENMASK_ULL(63, 1);
++      WRITE_ONCE(context->lo, val);
++      dma_wmb();
+ }
+ static inline void context_set_fault_enable(struct context_entry *context)
+diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
+index 74be6b547fc0c2..5e63b5d4577f75 100644
+--- a/drivers/iommu/intel/pasid.c
++++ b/drivers/iommu/intel/pasid.c
+@@ -804,7 +804,7 @@ static int device_pasid_table_setup(struct device *dev, u8 bus, u8 devfn)
+       }
+       if (context_copied(iommu, bus, devfn)) {
+-              context_clear_entry(context);
++              context_clear_present(context);
+               __iommu_flush_cache(iommu, context, sizeof(*context));
+               /*
+@@ -824,6 +824,9 @@ static int device_pasid_table_setup(struct device *dev, u8 bus, u8 devfn)
+               iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
+               devtlb_invalidation_with_pasid(iommu, dev, IOMMU_NO_PASID);
++              context_clear_entry(context);
++              __iommu_flush_cache(iommu, context, sizeof(*context));
++
+               /*
+                * At this point, the device is supposed to finish reset at
+                * its driver probe stage, so no in-flight DMA will exist,
+-- 
+2.53.0
+
diff --git a/staging-6.12/iommu-vt-d-clear-present-bit-before-tearing-down-sca.patch b/staging-6.12/iommu-vt-d-clear-present-bit-before-tearing-down-sca.patch
new file mode 100644 (file)
index 0000000..d0583ea
--- /dev/null
@@ -0,0 +1,65 @@
+From 9803b6151a06be785b1620280a2ac976d26ec347 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 14:03:07 +0800
+Subject: iommu/vt-d: Clear Present bit before tearing down scalable-mode
+ context entry
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+[ Upstream commit f46452c3df7a8d8a5addc0926e76ef19ea7da0a0 ]
+
+device_pasid_table_teardown() zeroes the 128-bit scalable-mode context
+entry with context_clear_entry() while the Present bit is still set. This
+creates a window where the hardware can fetch a torn entry, with some
+fields already zeroed while Present is still set, leading to unpredictable
+behavior or spurious faults. The context-cache invalidation is issued only
+after the entry has been zeroed, and intel_pasid_free_table() then frees
+the PASID directory pages, so the IOMMU can keep walking a stale Present=1
+entry that points at freed memory.
+
+While x86 provides strong write ordering, the compiler may reorder the two
+64-bit writes to the entry, and the hardware fetch is not guaranteed to be
+atomic with respect to multiple CPU writes.
+
+Commit c1e4f1dccbe9d ("iommu/vt-d: Clear Present bit before tearing down
+context entry") fixed this exact pattern in domain_context_clear_one() and
+the copied-context path, but device_pasid_table_teardown() was not
+converted.
+
+Align it with the "Guidance to Software for Invalidations" in the VT-d
+spec, Section 6.5.3.3, using the same ownership handshake as the sibling
+fix: clear only the Present bit, flush it to the IOMMU, perform the
+context-cache invalidation, and only then zero the rest of the entry.
+
+Fixes: 81e921fd32161 ("iommu/vt-d: Fix NULL domain on device release")
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Assisted-by: Claude:claude-opus-4-7
+Link: https://lore.kernel.org/r/20260528025557.3209367-1-michael.bommarito@gmail.com
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/pasid.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
+index 0e0c6cf2d3f4d3..93e9b9243d5fdb 100644
+--- a/drivers/iommu/intel/pasid.c
++++ b/drivers/iommu/intel/pasid.c
+@@ -714,10 +714,12 @@ static void device_pasid_table_teardown(struct device *dev, u8 bus, u8 devfn)
+       }
+       did = context_domain_id(context);
+-      context_clear_entry(context);
++      context_clear_present(context);
+       __iommu_flush_cache(iommu, context, sizeof(*context));
+       spin_unlock(&iommu->lock);
+       intel_context_flush_no_pasid(info, context, did);
++      context_clear_entry(context);
++      __iommu_flush_cache(iommu, context, sizeof(*context));
+ }
+ static int pci_pasid_table_teardown(struct pci_dev *pdev, u16 alias, void *data)
+-- 
+2.53.0
+
diff --git a/staging-6.12/kvm-arm64-bound-used_lrs-when-flushing-the-pkvm-hyp-.patch b/staging-6.12/kvm-arm64-bound-used_lrs-when-flushing-the-pkvm-hyp-.patch
new file mode 100644 (file)
index 0000000..c37d894
--- /dev/null
@@ -0,0 +1,94 @@
+From 076ee954e0a39402ceb8eabe65e7790dfda604e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 14:51:57 +0100
+Subject: KVM: arm64: Bound used_lrs when flushing the pKVM hyp vCPU
+
+From: Hyunwoo Kim <imv4bel@gmail.com>
+
+commit 8cc8bbbfab14c22c5551d0dd19b208a44b141c76 upstream.
+
+flush_hyp_vcpu() copies the host vGIC state into the hyp's private vCPU
+on every run. The vGIC list register save and restore use used_lrs as
+their loop bound and expect it to stay within the number of implemented
+list registers. While this is generally the case, flush_hyp_vcpu()
+copies vgic_v3 verbatim and does not enforce this, so a value provided
+by the host is used at EL2 to index vgic_lr[] and access ICH_LR<n>_EL2
+(host -> EL2).
+
+Fix by clamping used_lrs to the number of implemented list registers
+after the copy, as the trusted path already does in
+vgic_flush_lr_state(). The number of implemented list registers is
+constant after init, so it is replicated once from
+kvm_vgic_global_state.nr_lr into hyp_gicv3_nr_lr rather than read on
+every entry.
+
+Cc: stable@vger.kernel.org
+Fixes: be66e67f1750 ("KVM: arm64: Use the pKVM hyp vCPU structure in handle___kvm_vcpu_run()")
+Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
+Reviewed-by: Fuad Tabba <tabba@google.com>
+Tested-by: Fuad Tabba <tabba@google.com>
+Link: https://patch.msgid.link/20260606175614.83273-3-imv4bel@gmail.com
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+[ tabba: adjust context in flush_hyp_vcpu() and kvm_hyp.h ]
+Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/kvm_hyp.h   | 1 +
+ arch/arm64/kvm/arm.c               | 2 ++
+ arch/arm64/kvm/hyp/nvhe/hyp-main.c | 9 +++++++++
+ 3 files changed, 12 insertions(+)
+
+diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
+index c838309e4ec47e..19b8843374d0cf 100644
+--- a/arch/arm64/include/asm/kvm_hyp.h
++++ b/arch/arm64/include/asm/kvm_hyp.h
+@@ -144,5 +144,6 @@ extern u64 kvm_nvhe_sym(id_aa64smfr0_el1_sys_val);
+ extern unsigned long kvm_nvhe_sym(__icache_flags);
+ extern unsigned int kvm_nvhe_sym(kvm_arm_vmid_bits);
+ extern unsigned int kvm_nvhe_sym(kvm_host_sve_max_vl);
++extern unsigned int kvm_nvhe_sym(hyp_gicv3_nr_lr);
+ #endif /* __ARM64_KVM_HYP_H__ */
+diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
+index 3753ef782e98e5..a713f32a6545b1 100644
+--- a/arch/arm64/kvm/arm.c
++++ b/arch/arm64/kvm/arm.c
+@@ -2313,6 +2313,8 @@ static int __init init_subsystems(void)
+       switch (err) {
+       case 0:
+               vgic_present = true;
++              if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
++                      kvm_nvhe_sym(hyp_gicv3_nr_lr) = kvm_vgic_global_state.nr_lr;
+               break;
+       case -ENODEV:
+       case -ENXIO:
+diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+index 75f7e386de75bc..5dbc1878428cc2 100644
+--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
++++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+@@ -22,6 +22,9 @@
+ DEFINE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
++/* Number of implemented GICv3 LRs. Used by flush_hyp_vcpu(). */
++unsigned int hyp_gicv3_nr_lr;
++
+ void __kvm_hyp_host_forward_smc(struct kvm_cpu_context *host_ctxt);
+ static void __hyp_sve_save_guest(struct kvm_vcpu *vcpu)
+@@ -116,6 +119,12 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
+       hyp_vcpu->vcpu.arch.vsesr_el2   = host_vcpu->arch.vsesr_el2;
+       hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3 = host_vcpu->arch.vgic_cpu.vgic_v3;
++
++      /* Bound used_lrs by the number of implemented list registers. */
++      hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs =
++              min_t(unsigned int,
++                    hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs,
++                    hyp_gicv3_nr_lr);
+ }
+ static void sync_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
+-- 
+2.53.0
+
diff --git a/staging-6.12/kvm-arm64-clear-__hyp_running_vcpu-when-flushing-the.patch b/staging-6.12/kvm-arm64-clear-__hyp_running_vcpu-when-flushing-the.patch
new file mode 100644 (file)
index 0000000..525ded3
--- /dev/null
@@ -0,0 +1,50 @@
+From c5ab9545bc3b0516913f832b616501c797bb739d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 14:51:25 +0100
+Subject: KVM: arm64: Clear __hyp_running_vcpu when flushing the pKVM hyp vCPU
+
+From: Hyunwoo Kim <imv4bel@gmail.com>
+
+commit e8042f6e1d7befb2fb6b10a75918642bcd0acf9a upstream.
+
+flush_hyp_vcpu() copies the host vCPU context into the hyp's private
+vCPU on every run. ctxt_to_vcpu() expects a guest context to have a
+NULL __hyp_running_vcpu, which is only ever set on the host context, so
+that it resolves the vCPU via container_of(). While this is generally
+the case, flush_hyp_vcpu() copies the context verbatim and does not
+enforce this, so a value provided by the host is dereferenced at EL2
+(host -> EL2).
+
+Fix by clearing __hyp_running_vcpu after the copy.
+
+Cc: stable@vger.kernel.org
+Fixes: be66e67f1750 ("KVM: arm64: Use the pKVM hyp vCPU structure in handle___kvm_vcpu_run()")
+Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
+Reviewed-by: Fuad Tabba <tabba@google.com>
+Tested-by: Fuad Tabba <tabba@google.com>
+Link: https://patch.msgid.link/20260606175614.83273-2-imv4bel@gmail.com
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+[ tabba: adjust flush_hyp_vcpu() context ]
+Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/kvm/hyp/nvhe/hyp-main.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+index 5dbc1878428cc2..72384712377d16 100644
+--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
++++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+@@ -103,6 +103,9 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
+       hyp_vcpu->vcpu.arch.ctxt        = host_vcpu->arch.ctxt;
++      /* __hyp_running_vcpu must be NULL in a guest context. */
++      hyp_vcpu->vcpu.arch.ctxt.__hyp_running_vcpu = NULL;
++
+       hyp_vcpu->vcpu.arch.sve_state   = kern_hyp_va(host_vcpu->arch.sve_state);
+       /* Limit guest vector length to the maximum supported by the host.  */
+       hyp_vcpu->vcpu.arch.sve_max_vl  = min(host_vcpu->arch.sve_max_vl, kvm_host_sve_max_vl);
+-- 
+2.53.0
+
diff --git a/staging-6.12/sched-fair-only-update-stats-for-allowed-cpus-when-l.patch b/staging-6.12/sched-fair-only-update-stats-for-allowed-cpus-when-l.patch
new file mode 100644 (file)
index 0000000..3a0fd5d
--- /dev/null
@@ -0,0 +1,50 @@
+From 329a10f14b2a1aa66d4d492dc8c42f6decbd319a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 11 Oct 2025 06:43:22 +0000
+Subject: sched/fair: Only update stats for allowed CPUs when looking for dst
+ group
+
+From: Adam Li <adamli@os.amperecomputing.com>
+
+[ Upstream commit 82d6e01a0699800efd8b048eb584c907ccb47b7a ]
+
+Load imbalance is observed when the workload frequently forks new threads.
+Due to CPU affinity, the workload can run on CPU 0-7 in the first
+group, and only on CPU 8-11 in the second group. CPU 12-15 are always idle.
+
+{ 0 1 2 3 4 5 6 7 } {8 9 10 11 12 13 14 15}
+  * * * * * * * *    * * *  *
+
+When looking for dst group for newly forked threads, in many times
+update_sg_wakeup_stats() reports the second group has more idle CPUs
+than the first group. The scheduler thinks the second group is less
+busy. Then it selects least busy CPUs among CPU 8-11. Therefore CPU 8-11
+can be crowded with newly forked threads, at the same time CPU 0-7
+can be idle.
+
+A task may not use all the CPUs in a schedule group due to CPU affinity.
+Only update schedule group statistics for allowed CPUs.
+
+Signed-off-by: Adam Li <adamli@os.amperecomputing.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sched/fair.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index f36512892adf9d..bd1b30ca184f3c 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -10739,7 +10739,7 @@ static inline void update_sg_wakeup_stats(struct sched_domain *sd,
+       if (sd->flags & SD_ASYM_CPUCAPACITY)
+               sgs->group_misfit_task_load = 1;
+-      for_each_cpu(i, sched_group_span(group)) {
++      for_each_cpu_and(i, sched_group_span(group), p->cpus_ptr) {
+               struct rq *rq = cpu_rq(i);
+               unsigned int local;
+-- 
+2.53.0
+
diff --git a/staging-6.12/series b/staging-6.12/series
new file mode 100644 (file)
index 0000000..3974357
--- /dev/null
@@ -0,0 +1,17 @@
+smb-server-do-not-require-delete-access-for-non-repl.patch
+iommu-vt-d-clear-present-bit-before-tearing-down-con.patch
+tcp-add-preempt_-disable-enable-_nested-in-reqsk_que.patch
+bpf-support-for-hardening-against-jit-spraying.patch
+x86-bugs-enable-ibpb-flush-on-bpf-jit-allocation.patch
+bpf-restrict-jit-predictor-flush-to-cbpf.patch
+bpf-skip-redundant-ibpb-in-pack-allocator.patch
+bpf-prefer-packs-that-won-t-trigger-an-ibpb-flush-on.patch
+bpf-prefer-dirty-packs-for-ebpf-allocations.patch
+sched-fair-only-update-stats-for-allowed-cpus-when-l.patch
+crypto-algif_skcipher-force-synchronous-processing.patch
+kvm-arm64-bound-used_lrs-when-flushing-the-pkvm-hyp-.patch
+kvm-arm64-clear-__hyp_running_vcpu-when-flushing-the.patch
+iommu-pass-old-domain-to-set_dev_pasid-op.patch
+iommu-vt-d-cleanup-intel_context_flush_present.patch
+iommu-vt-d-clear-present-bit-before-tearing-down-sca.patch
+timekeeping-register-default-clocksource-before-taki.patch
diff --git a/staging-6.12/smb-server-do-not-require-delete-access-for-non-repl.patch b/staging-6.12/smb-server-do-not-require-delete-access-for-non-repl.patch
new file mode 100644 (file)
index 0000000..c22a405
--- /dev/null
@@ -0,0 +1,61 @@
+From 342442e5d1c59fa35d816a0b82f88b60ad1729bd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 28 Jun 2026 07:42:43 +0000
+Subject: smb/server: do not require delete access for non-replacing links
+
+From: ChenXiaoSong <chenxiaosong@kylinos.cn>
+
+[ Upstream commit 851ed9e09639e0daf79a506ce26097b296ed5518 ]
+
+Reproducer:
+
+  1. server: systemctl start ksmbd
+  2. client: mount -t cifs //${server_ip}/export /mnt
+  3. client: touch /mnt/file; ln /mnt/file /mnt/hardlink
+  4. client err log: ln: failed to create hard link 'hardlink' =>
+     'file': Permission denied
+  5. server err log: ksmbd: no right to delete : 0x80
+
+Fixes: 13f3942f2bf4 ("ksmbd: add per-handle permission check to FILE_LINK_INFORMATION")
+Cc: stable@vger.kernel.org
+Reported-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/server/smb2pdu.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
+index 2fd1fb03c01e21..f1cadc029677e8 100644
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -6526,16 +6526,18 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
+       }
+       case FILE_LINK_INFORMATION:
+       {
+-              if (!(fp->daccess & FILE_DELETE_LE)) {
+-                      pr_err("no right to delete : 0x%x\n", fp->daccess);
+-                      return -EACCES;
+-              }
++              struct smb2_file_link_info *file_info;
+               if (buf_len < sizeof(struct smb2_file_link_info))
+                       return -EINVAL;
+-              return smb2_create_link(work, work->tcon->share_conf,
+-                                      (struct smb2_file_link_info *)buffer,
++              file_info = (struct smb2_file_link_info *)buffer;
++              if (file_info->ReplaceIfExists && !(fp->daccess & FILE_DELETE_LE)) {
++                      pr_err("no right to delete : 0x%x\n", fp->daccess);
++                      return -EACCES;
++              }
++
++              return smb2_create_link(work, work->tcon->share_conf, file_info,
+                                       buf_len, fp->filp,
+                                       work->conn->local_nls);
+       }
+-- 
+2.53.0
+
diff --git a/staging-6.12/tcp-add-preempt_-disable-enable-_nested-in-reqsk_que.patch b/staging-6.12/tcp-add-preempt_-disable-enable-_nested-in-reqsk_que.patch
new file mode 100644 (file)
index 0000000..14e499e
--- /dev/null
@@ -0,0 +1,124 @@
+From 09f2df28c67f9bbe241cbfded731196f8da63ab1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 14:07:04 +0200
+Subject: tcp: Add preempt_{disable,enable}_nested() in reqsk_queue_hash_req().
+
+From: Kuniyuki Iwashima <kuniyu@google.com>
+
+[ Upstream commit e10902df24488ca722303133acfc82490f7d59ad ]
+
+syzbot reported a weird reqsk->rsk_refcnt underflow in
+__inet_csk_reqsk_queue_drop().
+
+The captured reqsk_put() in __inet_csk_reqsk_queue_drop()
+is called only when it successfully removes reqsk from ehash.
+
+Moreover, reqsk_timer_handler() calls another reqsk_put()
+after that.
+
+This indicates that the reqsk was missing both refcnts for
+ehash and the timer itself.
+
+Since all the syzbot reports had PREEMPT_RT enabled, the only
+possible scenario is that reqsk_queue_hash_req() is preempted
+after mod_timer() and before refcount_set(), and then the timer
+triggered after 1s aborts the reqsk due to its listener's close().
+
+Let's wrap mod_timer() and refcount_set() with
+preempt_disable_nested() and preempt_enable_nested().
+
+Note that inet_ehash_insert() holds the normal spin_lock()
+(mutex in PREEMPT_RT), so it must be called outside of
+preempt_disable_nested(), but this is fine.
+
+The lookup path just ignores 0 sk_refcnt entries in ehash
+and tries to create another reqsk, but this will fail at
+inet_ehash_insert().
+
+[0]:
+refcount_t: underflow; use-after-free.
+WARNING: lib/refcount.c:28 at refcount_warn_saturate+0xb2/0x110 lib/refcount.c:28, CPU#0: ktimers/0/16
+Modules linked in:
+CPU: 0 UID: 0 PID: 16 Comm: ktimers/0 Tainted: G             L      syzkaller #0 PREEMPT_{RT,(full)}
+Tainted: [L]=SOFTLOCKUP
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026
+RIP: 0010:refcount_warn_saturate+0xb2/0x110 lib/refcount.c:28
+Code: e4 7d d1 0a 67 48 0f b9 3a eb 4a e8 38 3d 23 fd 48 8d 3d e1 7d d1 0a 67 48 0f b9 3a eb 37 e8 25 3d 23 fd 48 8d 3d de 7d d1 0a <67> 48 0f b9 3a eb 24 e8 12 3d 23 fd 48 8d 3d db 7d d1 0a 67 48 0f
+RSP: 0000:ffffc90000157948 EFLAGS: 00010246
+RAX: ffffffff84a1301b RBX: 0000000000000003 RCX: ffff88801ca98000
+RDX: 0000000000000100 RSI: 0000000000000000 RDI: ffffffff8f72ae00
+RBP: ffffffff99ae3b01 R08: ffff88801ca98000 R09: 0000000000000005
+R10: 0000000000000100 R11: 0000000000000004 R12: ffff8880425ef568
+R13: ffff8880425ef4f8 R14: ffff8880425ef578 R15: 0000000000000000
+FS:  0000000000000000(0000) GS:ffff888126386000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f7b46710e9c CR3: 000000000dbb6000 CR4: 00000000003526f0
+Call Trace:
+ <TASK>
+ __refcount_sub_and_test include/linux/refcount.h:400 [inline]
+ __refcount_dec_and_test include/linux/refcount.h:432 [inline]
+ refcount_dec_and_test include/linux/refcount.h:450 [inline]
+ reqsk_put include/net/request_sock.h:136 [inline]
+ __inet_csk_reqsk_queue_drop+0x3ce/0x440 net/ipv4/inet_connection_sock.c:1007
+ reqsk_timer_handler+0x651/0xdf0 net/ipv4/inet_connection_sock.c:1137
+ call_timer_fn+0x192/0x5e0 kernel/time/timer.c:1748
+ expire_timers kernel/time/timer.c:1799 [inline]
+ __run_timers kernel/time/timer.c:2374 [inline]
+ __run_timer_base+0x6a3/0x9f0 kernel/time/timer.c:2386
+ run_timer_base kernel/time/timer.c:2395 [inline]
+ run_timer_softirq+0x67/0x170 kernel/time/timer.c:2403
+ handle_softirqs+0x1de/0x6d0 kernel/softirq.c:622
+ __do_softirq kernel/softirq.c:656 [inline]
+ run_ktimerd+0x69/0x100 kernel/softirq.c:1151
+ smpboot_thread_fn+0x541/0xa50 kernel/smpboot.c:160
+ kthread+0x388/0x470 kernel/kthread.c:436
+ ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
+ ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
+ </TASK>
+
+Fixes: d2d6422f8bd1 ("x86: Allow to enable PREEMPT_RT.")
+Reported-by: syzbot+e809069bc15f26300526@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/6a1a7bcf.0a9e871e.332604.000b.GAE@google.com/
+Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://patch.msgid.link/20260601182101.3183993-1-kuniyu@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[updated to not require timeout changes from
+ commit 3ce5dd8161ec ("tcp: Remove timeout arg from reqsk_queue_hash_req()")
+ DCCP was retired by commit 2a63dd0edf38 ("net: Retire DCCP socket.") after
+ the release of 6.12, so the shared inet_csk_reqsk_queue_hash_add still
+ requires the timout argument]
+Signed-off-by: Heiko Stuebner <heiko.stuebner@cherry.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/inet_connection_sock.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
+index dd39cabb39001e..5ff45bc854422b 100644
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -1186,6 +1186,9 @@ static bool reqsk_queue_hash_req(struct request_sock *req,
+       /* The timer needs to be setup after a successful insertion. */
+       timer_setup(&req->rsk_timer, reqsk_timer_handler, TIMER_PINNED);
++
++      preempt_disable_nested();
++
+       mod_timer(&req->rsk_timer, jiffies + timeout);
+       /* before letting lookups find us, make sure all req fields
+@@ -1193,6 +1196,9 @@ static bool reqsk_queue_hash_req(struct request_sock *req,
+        */
+       smp_wmb();
+       refcount_set(&req->rsk_refcnt, 2 + 1);
++
++      preempt_enable_nested();
++
+       return true;
+ }
+-- 
+2.53.0
+
diff --git a/staging-6.12/timekeeping-register-default-clocksource-before-taki.patch b/staging-6.12/timekeeping-register-default-clocksource-before-taki.patch
new file mode 100644 (file)
index 0000000..a86ff6c
--- /dev/null
@@ -0,0 +1,70 @@
+From 411a58cd35fbeea473490223dc3377598739e461 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Jun 2026 12:09:14 +0500
+Subject: timekeeping: Register default clocksource before taking tk_core.lock
+
+From: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
+
+[ Upstream commit 8fa30821180a9a19e78e9f4df1c0ba710252801e ]
+
+Commit f24df84cbe05 ("time/jiffies: Register jiffies clocksource before
+usage") moved the jiffies clocksource registration into
+clocksource_default_clock(), so that it is registered lazily on the first
+call. __clocksource_register() acquires clocksource_mutex, but the first
+caller is timekeeping_init(), which invokes clocksource_default_clock()
+while holding tk_core.lock, a raw spinlock.
+
+Acquiring a sleeping mutex while holding a raw spinlock is invalid.
+
+The default clocksource only has to be registered before
+tk_setup_internals() consumes its mult/shift/maxadj. Neither
+clocksource_default_clock(), the ->enable() callback, nor the registration
+itself need tk_core.lock, so fetch and enable the clock before acquiring
+the lock. This preserves the "register before usage" ordering while
+keeping clocksource_mutex out of the raw spinlock section.
+
+clocksource_default_clock() has a second caller,
+clocksource_done_booting(), which invokes it with clocksource_mutex already
+held. That path avoids a recursive lock because timekeeping_init() has
+already run and set cs_jiffies_registered, so the registration is skipped
+there. This change does not alter that; it only fixes the invalid wait
+context in timekeeping_init().
+
+Fixes: f24df84cbe05 ("time/jiffies: Register jiffies clocksource before usage")
+Signed-off-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
+Signed-off-by: Thomas Gleixner <tglx@kernel.org>
+Reported-by: Breno Leitao <leitao@debian.org>
+Reported-by: Oleg Nesterov <oleg@redhat.com>
+Reviewed-by: Breno Leitao <leitao@debian.org>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260616070914.65818-1-mikhail.v.gavrilov@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/timekeeping.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
+index e3896b2be45321..b99171e71e0ac5 100644
+--- a/kernel/time/timekeeping.c
++++ b/kernel/time/timekeeping.c
+@@ -1685,13 +1685,14 @@ void __init timekeeping_init(void)
+        */
+       wall_to_mono = timespec64_sub(boot_offset, wall_time);
++      clock = clocksource_default_clock();
++      if (clock->enable)
++              clock->enable(clock);
++
+       raw_spin_lock_irqsave(&timekeeper_lock, flags);
+       write_seqcount_begin(&tk_core.seq);
+       ntp_init();
+-      clock = clocksource_default_clock();
+-      if (clock->enable)
+-              clock->enable(clock);
+       tk_setup_internals(tk, clock);
+       tk_set_xtime(tk, &wall_time);
+-- 
+2.53.0
+
diff --git a/staging-6.12/x86-bugs-enable-ibpb-flush-on-bpf-jit-allocation.patch b/staging-6.12/x86-bugs-enable-ibpb-flush-on-bpf-jit-allocation.patch
new file mode 100644 (file)
index 0000000..5de5280
--- /dev/null
@@ -0,0 +1,147 @@
+From 128505f3e1a24a6693dca064abc9970f2c9265c2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 14:28:09 -0700
+Subject: x86/bugs: Enable IBPB flush on BPF JIT allocation
+
+From: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+
+commit a3af84b0fa00ead01fcd0e28b5d773ff25990a0d upstream.
+
+Enable hardening against JIT spraying when Spectre-v2 mitigations are in
+use. Specifically, issue an IBPB flush on BPF JIT memory reuse. Skip
+enabling the IBPB flush if the BPF dispatcher is already using a retpoline
+sequence.
+
+This hardening applies only when BPF-JIT is in use. Guard the enabling
+under CONFIG_BPF_JIT so that bugs.c still builds with CONFIG_BPF_JIT=n.
+
+  [ pawan: Use entry_ibpb() instead of write_ibpb(). JIT hardening enable
+          moved to spectre_v2_select_mitigation() because there is no
+          spectre_v2_apply_mitigation()]
+
+Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/nospec-branch.h |  4 +++
+ arch/x86/kernel/cpu/bugs.c           | 50 +++++++++++++++++++++++++---
+ 2 files changed, 49 insertions(+), 5 deletions(-)
+
+diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
+index f2cc7754918c0d..2e0812a8ed77af 100644
+--- a/arch/x86/include/asm/nospec-branch.h
++++ b/arch/x86/include/asm/nospec-branch.h
+@@ -405,6 +405,10 @@ extern void srso_alias_return_thunk(void);
+ extern void entry_untrain_ret(void);
+ extern void entry_ibpb(void);
++#ifdef CONFIG_BPF_JIT
++extern void bpf_arch_ibpb(void);
++#endif
++
+ #ifdef CONFIG_X86_64
+ extern void clear_bhb_loop(void);
+ #endif
+diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
+index 939401b5d2ef04..12544fdcadd6af 100644
+--- a/arch/x86/kernel/cpu/bugs.c
++++ b/arch/x86/kernel/cpu/bugs.c
+@@ -16,6 +16,7 @@
+ #include <linux/sched/smt.h>
+ #include <linux/pgtable.h>
+ #include <linux/bpf.h>
++#include <linux/filter.h>
+ #include <asm/spec-ctrl.h>
+ #include <asm/cmdline.h>
+@@ -1360,8 +1361,21 @@ static inline const char *spectre_v2_module_string(void)
+ {
+       return spectre_v2_bad_module ? " - vulnerable module loaded" : "";
+ }
++
++/*
++ * The "retpoline sequence" is the "call;mov;ret" sequence that
++ * replaces normal indirect branch instructions. Differentiate
++ * *the* retpoline sequence from the LFENCE-prefixed indirect
++ * branches that simply use the retpoline infrastructure.
++ */
++static inline bool retpoline_seq_enabled(void)
++{
++      return boot_cpu_has(X86_FEATURE_RETPOLINE) && !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE);
++}
++
+ #else
+ static inline const char *spectre_v2_module_string(void) { return ""; }
++static inline bool retpoline_seq_enabled(void) { return false; }
+ #endif
+ #define SPECTRE_V2_LFENCE_MSG "WARNING: LFENCE mitigation is not recommended for this CPU, data leaks possible!\n"
+@@ -1843,8 +1857,7 @@ static void __init bhi_select_mitigation(void)
+               return;
+       /* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */
+-      if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
+-          !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE)) {
++      if (retpoline_seq_enabled()) {
+               spec_ctrl_disable_kernel_rrsba();
+               if (rrsba_disabled)
+                       return;
+@@ -1868,6 +1881,27 @@ static void __init bhi_select_mitigation(void)
+       setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT);
+ }
++#ifdef CONFIG_BPF_JIT
++static void __bpf_arch_ibpb(void *unused)
++{
++      entry_ibpb();
++}
++
++void bpf_arch_ibpb(void)
++{
++      on_each_cpu(__bpf_arch_ibpb, NULL, 1);
++}
++
++static bool __init cpu_wants_ibpb_bpf(void)
++{
++      /* A genuine retpoline already neutralizes ring0 indirect predictions */
++      if (retpoline_seq_enabled())
++              return false;
++
++      return boot_cpu_has(X86_FEATURE_IBPB);
++}
++#endif
++
+ static void __init spectre_v2_select_mitigation(void)
+ {
+       enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
+@@ -2051,6 +2085,14 @@ static void __init spectre_v2_select_mitigation(void)
+               pr_info("Enabling Restricted Speculation for firmware calls\n");
+       }
++#ifdef CONFIG_BPF_JIT
++      if (cpu_wants_ibpb_bpf()) {
++              static_call_update(bpf_arch_pred_flush, bpf_arch_ibpb);
++              static_branch_enable(&bpf_pred_flush_enabled);
++              pr_info("Enabling IBPB for BPF\n");
++      }
++#endif
++
+       /* Set up IBPB and STIBP depending on the general spectre V2 command */
+       spectre_v2_cmd = cmd;
+ }
+@@ -3239,9 +3281,7 @@ static const char *spectre_bhi_state(void)
+               return "; BHI: BHI_DIS_S";
+       else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP))
+               return "; BHI: SW loop, KVM: SW loop";
+-      else if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
+-               !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE) &&
+-               rrsba_disabled)
++      else if (retpoline_seq_enabled() && rrsba_disabled)
+               return "; BHI: Retpoline";
+       else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT))
+               return "; BHI: Vulnerable, KVM: SW loop";
+-- 
+2.53.0
+
diff --git a/staging-6.18/crypto-algif_skcipher-force-synchronous-processing.patch b/staging-6.18/crypto-algif_skcipher-force-synchronous-processing.patch
new file mode 100644 (file)
index 0000000..a5149c6
--- /dev/null
@@ -0,0 +1,159 @@
+From ed7e0af4a748b8f7b1163c5a584b8494d03e1129 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 02:58:36 +0000
+Subject: crypto: algif_skcipher - force synchronous processing
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+
+The AIO/async path in skcipher_recvmsg() passes the socket-wide ctx->iv
+directly into the skcipher request. After io_submit() the socket lock is
+dropped and the request is processed asynchronously by a worker (e.g.
+cryptd), which dereferences ctx->iv only later.
+
+A concurrent sendmsg(ALG_SET_IV) on the same socket can overwrite ctx->iv
+inside this window, so the in-flight request runs under an
+attacker-controlled IV. For CTR and other stream modes this causes
+IV/keystream reuse and allows an unprivileged user to recover the
+plaintext of a concurrent operation.
+
+Snapshotting ctx->iv into per-request storage for the async path is not
+sufficient here. For ciphers with statesize == 0 - which includes cbc
+and ctr - skcipher_prepare_alg() installs skcipher_noimport()/
+skcipher_noexport(), so ctx->state carries nothing and the MSG_MORE
+inter-chunk IV chaining is carried solely by the in-place req->iv
+writeback. A snapshot redirects that writeback into per-request memory
+that af_alg_free_resources() releases on completion, so AIO + MSG_MORE
+with cbc/ctr would silently produce wrong output. Writing the IV back
+from the completion callback instead is not possible either: that would
+require lock_sock() there, but the callback can run in softirq/atomic
+context, so it must not sleep.
+
+Make the operation synchronous instead. ctx->iv is then only ever
+dereferenced under the socket lock held by recvmsg(), which removes the
+race, and the req->iv writeback lands in ctx->iv as before, which keeps
+MSG_MORE chaining intact for statesize == 0 ciphers. The ctx->state
+import/export path is unchanged for ciphers that do have state.
+
+This is equivalent to the upstream resolution: commit fcc77d33a34c
+("net: Remove support for AIO on sockets") removed the AIO socket path
+across net/ entirely, producing the same end state for this file -
+algif_skcipher never processes an AIO request asynchronously. After this
+patch, _skcipher_recvmsg() matches mainline's crypto/algif_skcipher.c as
+it stands today, including the same now-dead -EIOCBQUEUED check. This
+patch deviates from that commit deliberately: rather than removing AIO
+socket support tree-wide, which would be far too invasive for stable, it
+removes only the AIO branch in crypto/algif_skcipher.c. io_submit() now
+completes synchronously, which is valid for the AIO interface; AF_ALG
+async is rarely used in practice.
+
+The -EIOCBQUEUED check in skcipher_recvmsg() is now dead but harmless,
+and is left alone to keep the fix minimal.
+
+Fixes: e870456d8e7c ("crypto: algif_skcipher - overhaul memory management")
+Cc: <stable@vger.kernel.org>
+Reported-by: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+Signed-off-by: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ crypto/algif_skcipher.c | 75 +++++++++++++----------------------------
+ 1 file changed, 24 insertions(+), 51 deletions(-)
+
+diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
+index ba0a17fd95aca2..35ebc3e0201b04 100644
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -79,20 +79,6 @@ static int algif_skcipher_export(struct sock *sk, struct skcipher_request *req)
+       return err;
+ }
+-static void algif_skcipher_done(void *data, int err)
+-{
+-      struct af_alg_async_req *areq = data;
+-      struct sock *sk = areq->sk;
+-
+-      if (err)
+-              goto out;
+-
+-      err = algif_skcipher_export(sk, &areq->cra_u.skcipher_req);
+-
+-out:
+-      af_alg_async_cb(data, err);
+-}
+-
+ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
+                            size_t ignored, int flags)
+ {
+@@ -171,43 +157,30 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
+               cflags |= CRYPTO_SKCIPHER_REQ_CONT;
+       }
+-      if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
+-              /* AIO operation */
+-              sock_hold(sk);
+-              areq->iocb = msg->msg_iocb;
+-
+-              /* Remember output size that will be generated. */
+-              areq->outlen = len;
+-
+-              skcipher_request_set_callback(&areq->cra_u.skcipher_req,
+-                                            cflags |
+-                                            CRYPTO_TFM_REQ_MAY_SLEEP,
+-                                            algif_skcipher_done, areq);
+-              err = ctx->enc ?
+-                      crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
+-                      crypto_skcipher_decrypt(&areq->cra_u.skcipher_req);
+-
+-              /* AIO operation in progress */
+-              if (err == -EINPROGRESS)
+-                      return -EIOCBQUEUED;
+-
+-              sock_put(sk);
+-      } else {
+-              /* Synchronous operation */
+-              skcipher_request_set_callback(&areq->cra_u.skcipher_req,
+-                                            cflags |
+-                                            CRYPTO_TFM_REQ_MAY_SLEEP |
+-                                            CRYPTO_TFM_REQ_MAY_BACKLOG,
+-                                            crypto_req_done, &ctx->wait);
+-              err = crypto_wait_req(ctx->enc ?
+-                      crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
+-                      crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
+-                                               &ctx->wait);
+-
+-              if (!err)
+-                      err = algif_skcipher_export(
+-                              sk, &areq->cra_u.skcipher_req);
+-      }
++      /*
++       * Force synchronous processing.  The async (AIO) path passed the
++       * socket-wide ctx->iv into the request, which the worker
++       * dereferenced after the socket lock had been dropped, letting a
++       * concurrent sendmsg(ALG_SET_IV) inject an attacker IV.  Mainline
++       * removed the AIO socket path in commit fcc77d33a34c ("net: Remove
++       * support for AIO on sockets"); the minimal stable fix is to always
++       * complete synchronously, so ctx->iv is only ever dereferenced under
++       * the socket lock.  This also keeps the IV chaining intact: for
++       * ciphers with statesize == 0 (e.g. ctr, cbc) the chained IV is
++       * carried by the req->iv writeback into ctx->iv, which is only
++       * consistent on the synchronous path.
++       */
++      skcipher_request_set_callback(&areq->cra_u.skcipher_req,
++                                    cflags |
++                                    CRYPTO_TFM_REQ_MAY_SLEEP |
++                                    CRYPTO_TFM_REQ_MAY_BACKLOG,
++                                    crypto_req_done, &ctx->wait);
++      err = crypto_wait_req(ctx->enc ?
++              crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
++              crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
++                               &ctx->wait);
++      if (!err)
++              err = algif_skcipher_export(sk, &areq->cra_u.skcipher_req);
+ free:
+       af_alg_free_resources(areq);
+-- 
+2.53.0
+
diff --git a/staging-6.18/iommu-vt-d-clear-present-bit-before-tearing-down-sca.patch b/staging-6.18/iommu-vt-d-clear-present-bit-before-tearing-down-sca.patch
new file mode 100644 (file)
index 0000000..576b773
--- /dev/null
@@ -0,0 +1,65 @@
+From 761b3fae7b763a27f47aaf723ccc32e69ca1ad93 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 14:03:07 +0800
+Subject: iommu/vt-d: Clear Present bit before tearing down scalable-mode
+ context entry
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+[ Upstream commit f46452c3df7a8d8a5addc0926e76ef19ea7da0a0 ]
+
+device_pasid_table_teardown() zeroes the 128-bit scalable-mode context
+entry with context_clear_entry() while the Present bit is still set. This
+creates a window where the hardware can fetch a torn entry, with some
+fields already zeroed while Present is still set, leading to unpredictable
+behavior or spurious faults. The context-cache invalidation is issued only
+after the entry has been zeroed, and intel_pasid_free_table() then frees
+the PASID directory pages, so the IOMMU can keep walking a stale Present=1
+entry that points at freed memory.
+
+While x86 provides strong write ordering, the compiler may reorder the two
+64-bit writes to the entry, and the hardware fetch is not guaranteed to be
+atomic with respect to multiple CPU writes.
+
+Commit c1e4f1dccbe9d ("iommu/vt-d: Clear Present bit before tearing down
+context entry") fixed this exact pattern in domain_context_clear_one() and
+the copied-context path, but device_pasid_table_teardown() was not
+converted.
+
+Align it with the "Guidance to Software for Invalidations" in the VT-d
+spec, Section 6.5.3.3, using the same ownership handshake as the sibling
+fix: clear only the Present bit, flush it to the IOMMU, perform the
+context-cache invalidation, and only then zero the rest of the entry.
+
+Fixes: 81e921fd32161 ("iommu/vt-d: Fix NULL domain on device release")
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Assisted-by: Claude:claude-opus-4-7
+Link: https://lore.kernel.org/r/20260528025557.3209367-1-michael.bommarito@gmail.com
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/pasid.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
+index 787897e61efa37..85c3116e351c60 100644
+--- a/drivers/iommu/intel/pasid.c
++++ b/drivers/iommu/intel/pasid.c
+@@ -746,10 +746,12 @@ static void device_pasid_table_teardown(struct device *dev, u8 bus, u8 devfn)
+       }
+       did = context_domain_id(context);
+-      context_clear_entry(context);
++      context_clear_present(context);
+       __iommu_flush_cache(iommu, context, sizeof(*context));
+       spin_unlock(&iommu->lock);
+       intel_context_flush_no_pasid(info, context, did);
++      context_clear_entry(context);
++      __iommu_flush_cache(iommu, context, sizeof(*context));
+ }
+ static int pci_pasid_table_teardown(struct pci_dev *pdev, u16 alias, void *data)
+-- 
+2.53.0
+
diff --git a/staging-6.18/kvm-arm64-bound-used_lrs-when-flushing-the-pkvm-hyp-.patch b/staging-6.18/kvm-arm64-bound-used_lrs-when-flushing-the-pkvm-hyp-.patch
new file mode 100644 (file)
index 0000000..3fc6da7
--- /dev/null
@@ -0,0 +1,94 @@
+From f8e5bda889ad63f9e28829ebb56b5c19e0009f4b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 14:24:34 +0100
+Subject: KVM: arm64: Bound used_lrs when flushing the pKVM hyp vCPU
+
+From: Hyunwoo Kim <imv4bel@gmail.com>
+
+commit 8cc8bbbfab14c22c5551d0dd19b208a44b141c76 upstream.
+
+flush_hyp_vcpu() copies the host vGIC state into the hyp's private vCPU
+on every run. The vGIC list register save and restore use used_lrs as
+their loop bound and expect it to stay within the number of implemented
+list registers. While this is generally the case, flush_hyp_vcpu()
+copies vgic_v3 verbatim and does not enforce this, so a value provided
+by the host is used at EL2 to index vgic_lr[] and access ICH_LR<n>_EL2
+(host -> EL2).
+
+Fix by clamping used_lrs to the number of implemented list registers
+after the copy, as the trusted path already does in
+vgic_flush_lr_state(). The number of implemented list registers is
+constant after init, so it is replicated once from
+kvm_vgic_global_state.nr_lr into hyp_gicv3_nr_lr rather than read on
+every entry.
+
+Cc: stable@vger.kernel.org
+Fixes: be66e67f1750 ("KVM: arm64: Use the pKVM hyp vCPU structure in handle___kvm_vcpu_run()")
+Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
+Reviewed-by: Fuad Tabba <tabba@google.com>
+Tested-by: Fuad Tabba <tabba@google.com>
+Link: https://patch.msgid.link/20260606175614.83273-3-imv4bel@gmail.com
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+[ tabba: adjust context in flush_hyp_vcpu() and kvm_hyp.h ]
+Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/kvm_hyp.h   | 1 +
+ arch/arm64/kvm/arm.c               | 2 ++
+ arch/arm64/kvm/hyp/nvhe/hyp-main.c | 9 +++++++++
+ 3 files changed, 12 insertions(+)
+
+diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
+index e6be1f5d0967f6..8020e91b536d26 100644
+--- a/arch/arm64/include/asm/kvm_hyp.h
++++ b/arch/arm64/include/asm/kvm_hyp.h
+@@ -146,5 +146,6 @@ extern u64 kvm_nvhe_sym(id_aa64smfr0_el1_sys_val);
+ extern unsigned long kvm_nvhe_sym(__icache_flags);
+ extern unsigned int kvm_nvhe_sym(kvm_arm_vmid_bits);
+ extern unsigned int kvm_nvhe_sym(kvm_host_sve_max_vl);
++extern unsigned int kvm_nvhe_sym(hyp_gicv3_nr_lr);
+ #endif /* __ARM64_KVM_HYP_H__ */
+diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
+index e59cb36b5f36f3..10fc6783cd608a 100644
+--- a/arch/arm64/kvm/arm.c
++++ b/arch/arm64/kvm/arm.c
+@@ -2311,6 +2311,8 @@ static int __init init_subsystems(void)
+       switch (err) {
+       case 0:
+               vgic_present = true;
++              if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
++                      kvm_nvhe_sym(hyp_gicv3_nr_lr) = kvm_vgic_global_state.nr_lr;
+               break;
+       case -ENODEV:
+       case -ENXIO:
+diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+index 3dda50391446d9..6e7547b7ca432a 100644
+--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
++++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+@@ -22,6 +22,9 @@
+ DEFINE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
++/* Number of implemented GICv3 LRs. Used by flush_hyp_vcpu(). */
++unsigned int hyp_gicv3_nr_lr;
++
+ void __kvm_hyp_host_forward_smc(struct kvm_cpu_context *host_ctxt);
+ static void __hyp_sve_save_guest(struct kvm_vcpu *vcpu)
+@@ -139,6 +142,12 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
+       hyp_vcpu->vcpu.arch.vsesr_el2   = host_vcpu->arch.vsesr_el2;
+       hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3 = host_vcpu->arch.vgic_cpu.vgic_v3;
++
++      /* Bound used_lrs by the number of implemented list registers. */
++      hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs =
++              min_t(unsigned int,
++                    hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs,
++                    hyp_gicv3_nr_lr);
+ }
+ static void sync_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
+-- 
+2.53.0
+
diff --git a/staging-6.18/nvme-pci-dma-unmap-the-correct-regions-in-nvme_free_.patch b/staging-6.18/nvme-pci-dma-unmap-the-correct-regions-in-nvme_free_.patch
new file mode 100644 (file)
index 0000000..621bd0c
--- /dev/null
@@ -0,0 +1,49 @@
+From 934f28062e7a9f36286c7baf93e3d3896c04523d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jul 2026 22:13:42 +0200
+Subject: nvme-pci: DMA unmap the correct regions in nvme_free_sgls
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Roger Pau Monne <roger.pau@citrix.com>
+
+commit a54afbc8a2138f8c2490510cf26cde188d480c43 upstream.
+
+The call to nvme_free_sgls() in nvme_unmap_data() has the sg_list and sge
+parameters swapped.  This wasn't noticed by the compiler because both share
+the same type.  On a Xen PV hardware domain, and possibly any other
+architectures that takes that path, this leads to corruption of the NVMe
+contents.
+
+Fixes: f0887e2a52d4 ("nvme-pci: create common sgl unmapping helper")
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+[nb: drop the attrs parameter added in 6.19 by commit 61d43b1731e0
+ ("nvme-pci: migrate to dma_map_phys instead of map_page"), which is
+ not in 6.18.y]
+Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/pci.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index 5e36a5926fe03d..8c66fd23a143c1 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -761,8 +761,8 @@ static void nvme_unmap_data(struct request *req)
+       if (!blk_rq_dma_unmap(req, dma_dev, &iod->dma_state, iod->total_len)) {
+               if (nvme_pci_cmd_use_sgl(&iod->cmd))
+-                      nvme_free_sgls(req, iod->descriptors[0],
+-                                     &iod->cmd.common.dptr.sgl);
++                      nvme_free_sgls(req, &iod->cmd.common.dptr.sgl,
++                                     iod->descriptors[0]);
+               else
+                       nvme_free_prps(req);
+       }
+-- 
+2.53.0
+
diff --git a/staging-6.18/series b/staging-6.18/series
new file mode 100644 (file)
index 0000000..8a5bfe4
--- /dev/null
@@ -0,0 +1,6 @@
+nvme-pci-dma-unmap-the-correct-regions-in-nvme_free_.patch
+smb-server-do-not-require-delete-access-for-non-repl.patch
+tcp-add-preempt_-disable-enable-_nested-in-reqsk_que.patch
+crypto-algif_skcipher-force-synchronous-processing.patch
+kvm-arm64-bound-used_lrs-when-flushing-the-pkvm-hyp-.patch
+iommu-vt-d-clear-present-bit-before-tearing-down-sca.patch
diff --git a/staging-6.18/smb-server-do-not-require-delete-access-for-non-repl.patch b/staging-6.18/smb-server-do-not-require-delete-access-for-non-repl.patch
new file mode 100644 (file)
index 0000000..c087c6d
--- /dev/null
@@ -0,0 +1,61 @@
+From 1034d817981342a8b7d3b769c5708346f63aa8df Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 28 Jun 2026 07:42:43 +0000
+Subject: smb/server: do not require delete access for non-replacing links
+
+From: ChenXiaoSong <chenxiaosong@kylinos.cn>
+
+[ Upstream commit 851ed9e09639e0daf79a506ce26097b296ed5518 ]
+
+Reproducer:
+
+  1. server: systemctl start ksmbd
+  2. client: mount -t cifs //${server_ip}/export /mnt
+  3. client: touch /mnt/file; ln /mnt/file /mnt/hardlink
+  4. client err log: ln: failed to create hard link 'hardlink' =>
+     'file': Permission denied
+  5. server err log: ksmbd: no right to delete : 0x80
+
+Fixes: 13f3942f2bf4 ("ksmbd: add per-handle permission check to FILE_LINK_INFORMATION")
+Cc: stable@vger.kernel.org
+Reported-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/server/smb2pdu.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
+index 50e36050f9ea3c..44b87196c5afca 100644
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -6572,16 +6572,18 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
+       }
+       case FILE_LINK_INFORMATION:
+       {
+-              if (!(fp->daccess & FILE_DELETE_LE)) {
+-                      pr_err("no right to delete : 0x%x\n", fp->daccess);
+-                      return -EACCES;
+-              }
++              struct smb2_file_link_info *file_info;
+               if (buf_len < sizeof(struct smb2_file_link_info))
+                       return -EINVAL;
+-              return smb2_create_link(work, work->tcon->share_conf,
+-                                      (struct smb2_file_link_info *)buffer,
++              file_info = (struct smb2_file_link_info *)buffer;
++              if (file_info->ReplaceIfExists && !(fp->daccess & FILE_DELETE_LE)) {
++                      pr_err("no right to delete : 0x%x\n", fp->daccess);
++                      return -EACCES;
++              }
++
++              return smb2_create_link(work, work->tcon->share_conf, file_info,
+                                       buf_len, fp->filp,
+                                       work->conn->local_nls);
+       }
+-- 
+2.53.0
+
diff --git a/staging-6.18/tcp-add-preempt_-disable-enable-_nested-in-reqsk_que.patch b/staging-6.18/tcp-add-preempt_-disable-enable-_nested-in-reqsk_que.patch
new file mode 100644 (file)
index 0000000..5685e6e
--- /dev/null
@@ -0,0 +1,124 @@
+From 3c01ce5447cb2c7fdee49c0e16725c545bec767c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 14:07:04 +0200
+Subject: tcp: Add preempt_{disable,enable}_nested() in reqsk_queue_hash_req().
+
+From: Kuniyuki Iwashima <kuniyu@google.com>
+
+[ Upstream commit e10902df24488ca722303133acfc82490f7d59ad ]
+
+syzbot reported a weird reqsk->rsk_refcnt underflow in
+__inet_csk_reqsk_queue_drop().
+
+The captured reqsk_put() in __inet_csk_reqsk_queue_drop()
+is called only when it successfully removes reqsk from ehash.
+
+Moreover, reqsk_timer_handler() calls another reqsk_put()
+after that.
+
+This indicates that the reqsk was missing both refcnts for
+ehash and the timer itself.
+
+Since all the syzbot reports had PREEMPT_RT enabled, the only
+possible scenario is that reqsk_queue_hash_req() is preempted
+after mod_timer() and before refcount_set(), and then the timer
+triggered after 1s aborts the reqsk due to its listener's close().
+
+Let's wrap mod_timer() and refcount_set() with
+preempt_disable_nested() and preempt_enable_nested().
+
+Note that inet_ehash_insert() holds the normal spin_lock()
+(mutex in PREEMPT_RT), so it must be called outside of
+preempt_disable_nested(), but this is fine.
+
+The lookup path just ignores 0 sk_refcnt entries in ehash
+and tries to create another reqsk, but this will fail at
+inet_ehash_insert().
+
+[0]:
+refcount_t: underflow; use-after-free.
+WARNING: lib/refcount.c:28 at refcount_warn_saturate+0xb2/0x110 lib/refcount.c:28, CPU#0: ktimers/0/16
+Modules linked in:
+CPU: 0 UID: 0 PID: 16 Comm: ktimers/0 Tainted: G             L      syzkaller #0 PREEMPT_{RT,(full)}
+Tainted: [L]=SOFTLOCKUP
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026
+RIP: 0010:refcount_warn_saturate+0xb2/0x110 lib/refcount.c:28
+Code: e4 7d d1 0a 67 48 0f b9 3a eb 4a e8 38 3d 23 fd 48 8d 3d e1 7d d1 0a 67 48 0f b9 3a eb 37 e8 25 3d 23 fd 48 8d 3d de 7d d1 0a <67> 48 0f b9 3a eb 24 e8 12 3d 23 fd 48 8d 3d db 7d d1 0a 67 48 0f
+RSP: 0000:ffffc90000157948 EFLAGS: 00010246
+RAX: ffffffff84a1301b RBX: 0000000000000003 RCX: ffff88801ca98000
+RDX: 0000000000000100 RSI: 0000000000000000 RDI: ffffffff8f72ae00
+RBP: ffffffff99ae3b01 R08: ffff88801ca98000 R09: 0000000000000005
+R10: 0000000000000100 R11: 0000000000000004 R12: ffff8880425ef568
+R13: ffff8880425ef4f8 R14: ffff8880425ef578 R15: 0000000000000000
+FS:  0000000000000000(0000) GS:ffff888126386000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f7b46710e9c CR3: 000000000dbb6000 CR4: 00000000003526f0
+Call Trace:
+ <TASK>
+ __refcount_sub_and_test include/linux/refcount.h:400 [inline]
+ __refcount_dec_and_test include/linux/refcount.h:432 [inline]
+ refcount_dec_and_test include/linux/refcount.h:450 [inline]
+ reqsk_put include/net/request_sock.h:136 [inline]
+ __inet_csk_reqsk_queue_drop+0x3ce/0x440 net/ipv4/inet_connection_sock.c:1007
+ reqsk_timer_handler+0x651/0xdf0 net/ipv4/inet_connection_sock.c:1137
+ call_timer_fn+0x192/0x5e0 kernel/time/timer.c:1748
+ expire_timers kernel/time/timer.c:1799 [inline]
+ __run_timers kernel/time/timer.c:2374 [inline]
+ __run_timer_base+0x6a3/0x9f0 kernel/time/timer.c:2386
+ run_timer_base kernel/time/timer.c:2395 [inline]
+ run_timer_softirq+0x67/0x170 kernel/time/timer.c:2403
+ handle_softirqs+0x1de/0x6d0 kernel/softirq.c:622
+ __do_softirq kernel/softirq.c:656 [inline]
+ run_ktimerd+0x69/0x100 kernel/softirq.c:1151
+ smpboot_thread_fn+0x541/0xa50 kernel/smpboot.c:160
+ kthread+0x388/0x470 kernel/kthread.c:436
+ ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
+ ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
+ </TASK>
+
+Fixes: d2d6422f8bd1 ("x86: Allow to enable PREEMPT_RT.")
+Reported-by: syzbot+e809069bc15f26300526@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/6a1a7bcf.0a9e871e.332604.000b.GAE@google.com/
+Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://patch.msgid.link/20260601182101.3183993-1-kuniyu@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[updated to not require timeout changes from
+ commit 3ce5dd8161ec ("tcp: Remove timeout arg from reqsk_queue_hash_req()")
+ DCCP was retired by commit 2a63dd0edf38 ("net: Retire DCCP socket.") after
+ the release of 6.12, so the shared inet_csk_reqsk_queue_hash_add still
+ requires the timout argument]
+Signed-off-by: Heiko Stuebner <heiko.stuebner@cherry.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/inet_connection_sock.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
+index c777895a720eec..4aa5cdef8e42c4 100644
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -1163,6 +1163,9 @@ static bool reqsk_queue_hash_req(struct request_sock *req,
+       /* The timer needs to be setup after a successful insertion. */
+       timer_setup(&req->rsk_timer, reqsk_timer_handler, TIMER_PINNED);
++
++      preempt_disable_nested();
++
+       mod_timer(&req->rsk_timer, jiffies + timeout);
+       /* before letting lookups find us, make sure all req fields
+@@ -1170,6 +1173,9 @@ static bool reqsk_queue_hash_req(struct request_sock *req,
+        */
+       smp_wmb();
+       refcount_set(&req->rsk_refcnt, 2 + 1);
++
++      preempt_enable_nested();
++
+       return true;
+ }
+-- 
+2.53.0
+
diff --git a/staging-6.6/block-skip-sync_blockdev-on-surprise-removal-in-bdev.patch b/staging-6.6/block-skip-sync_blockdev-on-surprise-removal-in-bdev.patch
new file mode 100644 (file)
index 0000000..981bd6e
--- /dev/null
@@ -0,0 +1,67 @@
+From fe92b1c1dc089943451aa4be5d372efd5d356af2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 03:34:52 -0400
+Subject: block: skip sync_blockdev() on surprise removal in bdev_mark_dead()
+
+From: Chao Shi <coshi036@gmail.com>
+
+commit 49f06cff50a4ccf3b7a1a662ceb892b3b21a527a upstream.
+
+bdev_mark_dead()'s @surprise == true means the device is already gone.
+The filesystem callback fs_bdev_mark_dead() honours this and skips
+sync_filesystem(), but the bare block device path (no ->mark_dead op)
+lost its !surprise guard when the holder ->mark_dead callback was wired
+up (see Fixes), and now calls sync_blockdev() unconditionally, which can
+hang forever waiting on writeback that can no longer complete.
+
+syzkaller hit this via nvme_reset_work()'s "I/O queues lost" path:
+nvme_mark_namespaces_dead() -> blk_mark_disk_dead() ->
+bdev_mark_dead(bdev, true) -> sync_blockdev() blocks in
+folio_wait_writeback(), wedging the reset worker and every task waiting
+on it.
+
+Skip the sync on surprise removal, matching fs_bdev_mark_dead();
+invalidate_bdev() still runs. Orderly removal (surprise == false) is
+unchanged.
+
+Found by FuzzNvme.
+
+Fixes: d8530de5a6e8 ("block: call into the file system for bdev_mark_dead")
+Acked-by: Sungwoo Kim <iam@sung-woo.kim>
+Acked-by: Dave Tian <daveti@purdue.edu>
+Acked-by: Weidong Zhu <weizhu@fiu.edu>
+Signed-off-by: Chao Shi <coshi036@gmail.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://patch.msgid.link/20260522220025.1770388-1-coshi036@gmail.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+[ adjusted for 6.6.y: bdev_mark_dead() there still unlocks bd_holder_lock
+  after the if/else and the else arm is a bare sync_blockdev(), so the
+  !surprise guard is added as "else if (!surprise)" instead of inside the
+  mainline else block. ]
+Signed-off-by: Chao Shi <coshi036@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/bdev.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/block/bdev.c b/block/bdev.c
+index 598f94827b941f..a255492ba82654 100644
+--- a/block/bdev.c
++++ b/block/bdev.c
+@@ -1024,7 +1024,12 @@ void bdev_mark_dead(struct block_device *bdev, bool surprise)
+       mutex_lock(&bdev->bd_holder_lock);
+       if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead)
+               bdev->bd_holder_ops->mark_dead(bdev, surprise);
+-      else
++      /*
++       * On surprise removal the device is already gone; syncing is
++       * futile and can hang forever waiting on I/O that will never
++       * complete.  Match fs_bdev_mark_dead(), which also skips it.
++       */
++      else if (!surprise)
+               sync_blockdev(bdev);
+       mutex_unlock(&bdev->bd_holder_lock);
+-- 
+2.53.0
+
diff --git a/staging-6.6/crypto-algif_skcipher-force-synchronous-processing-o.patch b/staging-6.6/crypto-algif_skcipher-force-synchronous-processing-o.patch
new file mode 100644 (file)
index 0000000..31e6597
--- /dev/null
@@ -0,0 +1,116 @@
+From 2ea7b51316ebdf3311a7c63dd309f51fa0d8b053 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 02:58:37 +0000
+Subject: crypto: algif_skcipher - force synchronous processing on trees
+ without ctx->state
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+
+The AIO/async path in skcipher_recvmsg() passes the socket-wide ctx->iv
+directly into the skcipher request. After io_submit() the socket lock is
+dropped and the request is processed asynchronously, so a concurrent
+sendmsg(ALG_SET_IV) can overwrite ctx->iv and make the in-flight request
+run under an attacker-controlled IV. For CTR/stream modes this is
+IV/keystream reuse and lets an unprivileged user recover the plaintext of
+a concurrent operation.
+
+Snapshotting ctx->iv into per-request storage for the async path is not
+sufficient. For ciphers with statesize == 0 - which includes cbc and ctr -
+the MSG_MORE inter-chunk IV chaining is carried solely by the in-place
+req->iv writeback, which a snapshot redirects into per-request memory that
+af_alg_free_resources() releases on completion, silently producing wrong
+output. Writing the IV back from the completion callback instead is not
+possible either: that would require lock_sock() there, but the callback can
+run in softirq/atomic context, so it must not sleep.
+
+Make the operation synchronous instead, which removes both the IV race and
+any writeback race. This is equivalent to the upstream resolution, commit
+fcc77d33a34c ("net: Remove support for AIO on sockets"), which removed the
+AIO socket path across net/ entirely and so produces the same end state for
+this file. This patch deviates from that commit deliberately: rather than
+removing AIO socket support tree-wide, which would be far too invasive for
+stable, it removes only the AIO branch in crypto/algif_skcipher.c.
+io_submit() now completes synchronously; AF_ALG async is rarely used in
+practice.
+
+The -EIOCBQUEUED check in skcipher_recvmsg() is now dead but harmless,
+and is left alone to keep the fix minimal.
+
+Tested on 6.6.y: attacker IV injection dropped from 2296/200000 to 0/200000
+after the change; MSG_MORE chunked CTR output bit-identical to single-shot.
+
+Reported-by: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+Fixes: e870456d8e7c ("crypto: algif_skcipher - overhaul memory management")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ crypto/algif_skcipher.c | 49 +++++++++++++++--------------------------
+ 1 file changed, 18 insertions(+), 31 deletions(-)
+
+diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
+index e31b1da58dba41..b12df4544d0bbb 100644
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -107,37 +107,24 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
+       skcipher_request_set_crypt(&areq->cra_u.skcipher_req, areq->tsgl,
+                                  areq->first_rsgl.sgl.sgt.sgl, len, ctx->iv);
+-      if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
+-              /* AIO operation */
+-              sock_hold(sk);
+-              areq->iocb = msg->msg_iocb;
+-
+-              /* Remember output size that will be generated. */
+-              areq->outlen = len;
+-
+-              skcipher_request_set_callback(&areq->cra_u.skcipher_req,
+-                                            CRYPTO_TFM_REQ_MAY_SLEEP,
+-                                            af_alg_async_cb, areq);
+-              err = ctx->enc ?
+-                      crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
+-                      crypto_skcipher_decrypt(&areq->cra_u.skcipher_req);
+-
+-              /* AIO operation in progress */
+-              if (err == -EINPROGRESS)
+-                      return -EIOCBQUEUED;
+-
+-              sock_put(sk);
+-      } else {
+-              /* Synchronous operation */
+-              skcipher_request_set_callback(&areq->cra_u.skcipher_req,
+-                                            CRYPTO_TFM_REQ_MAY_SLEEP |
+-                                            CRYPTO_TFM_REQ_MAY_BACKLOG,
+-                                            crypto_req_done, &ctx->wait);
+-              err = crypto_wait_req(ctx->enc ?
+-                      crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
+-                      crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
+-                                               &ctx->wait);
+-      }
++      /*
++       * Force synchronous processing.  The async (AIO) path passed the
++       * socket-wide ctx->iv into the request, which the worker
++       * dereferenced after the socket lock was dropped, letting a
++       * concurrent sendmsg(ALG_SET_IV) inject an attacker IV.  Mainline
++       * removed the AIO socket path in commit fcc77d33a34c ("net: Remove
++       * support for AIO on sockets"); these stable trees lack the
++       * per-request ctx->state used by newer kernels, so the minimal safe
++       * fix is to always complete synchronously.
++       */
++      skcipher_request_set_callback(&areq->cra_u.skcipher_req,
++                                    CRYPTO_TFM_REQ_MAY_SLEEP |
++                                    CRYPTO_TFM_REQ_MAY_BACKLOG,
++                                    crypto_req_done, &ctx->wait);
++      err = crypto_wait_req(ctx->enc ?
++              crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
++              crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
++                                    &ctx->wait);
+ free:
+-- 
+2.53.0
+
diff --git a/staging-6.6/kvm-arm64-bound-used_lrs-when-flushing-the-pkvm-hyp-.patch b/staging-6.6/kvm-arm64-bound-used_lrs-when-flushing-the-pkvm-hyp-.patch
new file mode 100644 (file)
index 0000000..bc95c61
--- /dev/null
@@ -0,0 +1,94 @@
+From 5a48125885d2b2ae9bd5215017b9cad010dd2e38 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 14:50:36 +0100
+Subject: KVM: arm64: Bound used_lrs when flushing the pKVM hyp vCPU
+
+From: Hyunwoo Kim <imv4bel@gmail.com>
+
+commit 8cc8bbbfab14c22c5551d0dd19b208a44b141c76 upstream.
+
+flush_hyp_vcpu() copies the host vGIC state into the hyp's private vCPU
+on every run. The vGIC list register save and restore use used_lrs as
+their loop bound and expect it to stay within the number of implemented
+list registers. While this is generally the case, flush_hyp_vcpu()
+copies vgic_v3 verbatim and does not enforce this, so a value provided
+by the host is used at EL2 to index vgic_lr[] and access ICH_LR<n>_EL2
+(host -> EL2).
+
+Fix by clamping used_lrs to the number of implemented list registers
+after the copy, as the trusted path already does in
+vgic_flush_lr_state(). The number of implemented list registers is
+constant after init, so it is replicated once from
+kvm_vgic_global_state.nr_lr into hyp_gicv3_nr_lr rather than read on
+every entry.
+
+Cc: stable@vger.kernel.org
+Fixes: be66e67f1750 ("KVM: arm64: Use the pKVM hyp vCPU structure in handle___kvm_vcpu_run()")
+Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
+Reviewed-by: Fuad Tabba <tabba@google.com>
+Tested-by: Fuad Tabba <tabba@google.com>
+Link: https://patch.msgid.link/20260606175614.83273-3-imv4bel@gmail.com
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+[ tabba: adjust context in flush_hyp_vcpu() and kvm_hyp.h ]
+Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/kvm_hyp.h   | 1 +
+ arch/arm64/kvm/arm.c               | 2 ++
+ arch/arm64/kvm/hyp/nvhe/hyp-main.c | 9 +++++++++
+ 3 files changed, 12 insertions(+)
+
+diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
+index 51cd106cd840a0..1b209efac97287 100644
+--- a/arch/arm64/include/asm/kvm_hyp.h
++++ b/arch/arm64/include/asm/kvm_hyp.h
+@@ -146,5 +146,6 @@ extern u64 kvm_nvhe_sym(id_aa64smfr0_el1_sys_val);
+ extern unsigned long kvm_nvhe_sym(__icache_flags);
+ extern unsigned int kvm_nvhe_sym(kvm_arm_vmid_bits);
+ extern unsigned int kvm_nvhe_sym(kvm_host_sve_max_vl);
++extern unsigned int kvm_nvhe_sym(hyp_gicv3_nr_lr);
+ #endif /* __ARM64_KVM_HYP_H__ */
+diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
+index 3ae529e967c7fb..e49ead6d005cc4 100644
+--- a/arch/arm64/kvm/arm.c
++++ b/arch/arm64/kvm/arm.c
+@@ -2026,6 +2026,8 @@ static int __init init_subsystems(void)
+       switch (err) {
+       case 0:
+               vgic_present = true;
++              if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
++                      kvm_nvhe_sym(hyp_gicv3_nr_lr) = kvm_vgic_global_state.nr_lr;
+               break;
+       case -ENODEV:
+       case -ENXIO:
+diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+index 350d1775a5ce88..aa6c486667e706 100644
+--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
++++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+@@ -22,6 +22,9 @@
+ DEFINE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
++/* Number of implemented GICv3 LRs. Used by flush_hyp_vcpu(). */
++unsigned int hyp_gicv3_nr_lr;
++
+ void __kvm_hyp_host_forward_smc(struct kvm_cpu_context *host_ctxt);
+ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
+@@ -46,6 +49,12 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
+       hyp_vcpu->vcpu.arch.vsesr_el2   = host_vcpu->arch.vsesr_el2;
+       hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3 = host_vcpu->arch.vgic_cpu.vgic_v3;
++
++      /* Bound used_lrs by the number of implemented list registers. */
++      hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs =
++              min_t(unsigned int,
++                    hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs,
++                    hyp_gicv3_nr_lr);
+ }
+ static void sync_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
+-- 
+2.53.0
+
diff --git a/staging-6.6/kvm-arm64-clear-__hyp_running_vcpu-when-flushing-the.patch b/staging-6.6/kvm-arm64-clear-__hyp_running_vcpu-when-flushing-the.patch
new file mode 100644 (file)
index 0000000..c012d64
--- /dev/null
@@ -0,0 +1,50 @@
+From e4aaffe40dfd4714b0ee66ba21637dbffe8dc126 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 14:50:12 +0100
+Subject: KVM: arm64: Clear __hyp_running_vcpu when flushing the pKVM hyp vCPU
+
+From: Hyunwoo Kim <imv4bel@gmail.com>
+
+commit e8042f6e1d7befb2fb6b10a75918642bcd0acf9a upstream.
+
+flush_hyp_vcpu() copies the host vCPU context into the hyp's private
+vCPU on every run. ctxt_to_vcpu() expects a guest context to have a
+NULL __hyp_running_vcpu, which is only ever set on the host context, so
+that it resolves the vCPU via container_of(). While this is generally
+the case, flush_hyp_vcpu() copies the context verbatim and does not
+enforce this, so a value provided by the host is dereferenced at EL2
+(host -> EL2).
+
+Fix by clearing __hyp_running_vcpu after the copy.
+
+Cc: stable@vger.kernel.org
+Fixes: be66e67f1750 ("KVM: arm64: Use the pKVM hyp vCPU structure in handle___kvm_vcpu_run()")
+Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
+Reviewed-by: Fuad Tabba <tabba@google.com>
+Tested-by: Fuad Tabba <tabba@google.com>
+Link: https://patch.msgid.link/20260606175614.83273-2-imv4bel@gmail.com
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+[ tabba: adjust flush_hyp_vcpu() context ]
+Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/kvm/hyp/nvhe/hyp-main.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+index aa6c486667e706..ac0d5a0de01496 100644
+--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
++++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+@@ -33,6 +33,9 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
+       hyp_vcpu->vcpu.arch.ctxt        = host_vcpu->arch.ctxt;
++      /* __hyp_running_vcpu must be NULL in a guest context. */
++      hyp_vcpu->vcpu.arch.ctxt.__hyp_running_vcpu = NULL;
++
+       hyp_vcpu->vcpu.arch.sve_state   = kern_hyp_va(host_vcpu->arch.sve_state);
+       hyp_vcpu->vcpu.arch.sve_max_vl  = host_vcpu->arch.sve_max_vl;
+-- 
+2.53.0
+
diff --git a/staging-6.6/sched-fair-only-update-stats-for-allowed-cpus-when-l.patch b/staging-6.6/sched-fair-only-update-stats-for-allowed-cpus-when-l.patch
new file mode 100644 (file)
index 0000000..ee70452
--- /dev/null
@@ -0,0 +1,50 @@
+From 7a1916724391731d0bc6d2555dfdfe111c8fb299 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 11 Oct 2025 06:43:22 +0000
+Subject: sched/fair: Only update stats for allowed CPUs when looking for dst
+ group
+
+From: Adam Li <adamli@os.amperecomputing.com>
+
+[ Upstream commit 82d6e01a0699800efd8b048eb584c907ccb47b7a ]
+
+Load imbalance is observed when the workload frequently forks new threads.
+Due to CPU affinity, the workload can run on CPU 0-7 in the first
+group, and only on CPU 8-11 in the second group. CPU 12-15 are always idle.
+
+{ 0 1 2 3 4 5 6 7 } {8 9 10 11 12 13 14 15}
+  * * * * * * * *    * * *  *
+
+When looking for dst group for newly forked threads, in many times
+update_sg_wakeup_stats() reports the second group has more idle CPUs
+than the first group. The scheduler thinks the second group is less
+busy. Then it selects least busy CPUs among CPU 8-11. Therefore CPU 8-11
+can be crowded with newly forked threads, at the same time CPU 0-7
+can be idle.
+
+A task may not use all the CPUs in a schedule group due to CPU affinity.
+Only update schedule group statistics for allowed CPUs.
+
+Signed-off-by: Adam Li <adamli@os.amperecomputing.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sched/fair.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index cdf49a04fd5820..2fc9fe94d3f1f4 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -10266,7 +10266,7 @@ static inline void update_sg_wakeup_stats(struct sched_domain *sd,
+       if (sd->flags & SD_ASYM_CPUCAPACITY)
+               sgs->group_misfit_task_load = 1;
+-      for_each_cpu(i, sched_group_span(group)) {
++      for_each_cpu_and(i, sched_group_span(group), p->cpus_ptr) {
+               struct rq *rq = cpu_rq(i);
+               unsigned int local;
+-- 
+2.53.0
+
diff --git a/staging-6.6/series b/staging-6.6/series
new file mode 100644 (file)
index 0000000..76fbd3f
--- /dev/null
@@ -0,0 +1,6 @@
+smb-server-do-not-require-delete-access-for-non-repl.patch
+block-skip-sync_blockdev-on-surprise-removal-in-bdev.patch
+sched-fair-only-update-stats-for-allowed-cpus-when-l.patch
+crypto-algif_skcipher-force-synchronous-processing-o.patch
+kvm-arm64-bound-used_lrs-when-flushing-the-pkvm-hyp-.patch
+kvm-arm64-clear-__hyp_running_vcpu-when-flushing-the.patch
diff --git a/staging-6.6/smb-server-do-not-require-delete-access-for-non-repl.patch b/staging-6.6/smb-server-do-not-require-delete-access-for-non-repl.patch
new file mode 100644 (file)
index 0000000..05e2192
--- /dev/null
@@ -0,0 +1,61 @@
+From e445390cf6374aedb297c9ef97a3fc26a4f1b1c4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 28 Jun 2026 07:42:43 +0000
+Subject: smb/server: do not require delete access for non-replacing links
+
+From: ChenXiaoSong <chenxiaosong@kylinos.cn>
+
+[ Upstream commit 851ed9e09639e0daf79a506ce26097b296ed5518 ]
+
+Reproducer:
+
+  1. server: systemctl start ksmbd
+  2. client: mount -t cifs //${server_ip}/export /mnt
+  3. client: touch /mnt/file; ln /mnt/file /mnt/hardlink
+  4. client err log: ln: failed to create hard link 'hardlink' =>
+     'file': Permission denied
+  5. server err log: ksmbd: no right to delete : 0x80
+
+Fixes: 13f3942f2bf4 ("ksmbd: add per-handle permission check to FILE_LINK_INFORMATION")
+Cc: stable@vger.kernel.org
+Reported-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/server/smb2pdu.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
+index 968b1b5d858fb7..fafbb4275bba4d 100644
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -6504,16 +6504,18 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
+       }
+       case FILE_LINK_INFORMATION:
+       {
+-              if (!(fp->daccess & FILE_DELETE_LE)) {
+-                      pr_err("no right to delete : 0x%x\n", fp->daccess);
+-                      return -EACCES;
+-              }
++              struct smb2_file_link_info *file_info;
+               if (buf_len < sizeof(struct smb2_file_link_info))
+                       return -EINVAL;
+-              return smb2_create_link(work, work->tcon->share_conf,
+-                                      (struct smb2_file_link_info *)buffer,
++              file_info = (struct smb2_file_link_info *)buffer;
++              if (file_info->ReplaceIfExists && !(fp->daccess & FILE_DELETE_LE)) {
++                      pr_err("no right to delete : 0x%x\n", fp->daccess);
++                      return -EACCES;
++              }
++
++              return smb2_create_link(work, work->tcon->share_conf, file_info,
+                                       buf_len, fp->filp,
+                                       work->conn->local_nls);
+       }
+-- 
+2.53.0
+
diff --git a/staging-7.1/crypto-algif_skcipher-force-synchronous-processing.patch b/staging-7.1/crypto-algif_skcipher-force-synchronous-processing.patch
new file mode 100644 (file)
index 0000000..c84cc14
--- /dev/null
@@ -0,0 +1,159 @@
+From 60397482ee75cb912cee1d6ce597921804ab6d57 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jul 2026 02:58:36 +0000
+Subject: crypto: algif_skcipher - force synchronous processing
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+
+The AIO/async path in skcipher_recvmsg() passes the socket-wide ctx->iv
+directly into the skcipher request. After io_submit() the socket lock is
+dropped and the request is processed asynchronously by a worker (e.g.
+cryptd), which dereferences ctx->iv only later.
+
+A concurrent sendmsg(ALG_SET_IV) on the same socket can overwrite ctx->iv
+inside this window, so the in-flight request runs under an
+attacker-controlled IV. For CTR and other stream modes this causes
+IV/keystream reuse and allows an unprivileged user to recover the
+plaintext of a concurrent operation.
+
+Snapshotting ctx->iv into per-request storage for the async path is not
+sufficient here. For ciphers with statesize == 0 - which includes cbc
+and ctr - skcipher_prepare_alg() installs skcipher_noimport()/
+skcipher_noexport(), so ctx->state carries nothing and the MSG_MORE
+inter-chunk IV chaining is carried solely by the in-place req->iv
+writeback. A snapshot redirects that writeback into per-request memory
+that af_alg_free_resources() releases on completion, so AIO + MSG_MORE
+with cbc/ctr would silently produce wrong output. Writing the IV back
+from the completion callback instead is not possible either: that would
+require lock_sock() there, but the callback can run in softirq/atomic
+context, so it must not sleep.
+
+Make the operation synchronous instead. ctx->iv is then only ever
+dereferenced under the socket lock held by recvmsg(), which removes the
+race, and the req->iv writeback lands in ctx->iv as before, which keeps
+MSG_MORE chaining intact for statesize == 0 ciphers. The ctx->state
+import/export path is unchanged for ciphers that do have state.
+
+This is equivalent to the upstream resolution: commit fcc77d33a34c
+("net: Remove support for AIO on sockets") removed the AIO socket path
+across net/ entirely, producing the same end state for this file -
+algif_skcipher never processes an AIO request asynchronously. After this
+patch, _skcipher_recvmsg() matches mainline's crypto/algif_skcipher.c as
+it stands today, including the same now-dead -EIOCBQUEUED check. This
+patch deviates from that commit deliberately: rather than removing AIO
+socket support tree-wide, which would be far too invasive for stable, it
+removes only the AIO branch in crypto/algif_skcipher.c. io_submit() now
+completes synchronously, which is valid for the AIO interface; AF_ALG
+async is rarely used in practice.
+
+The -EIOCBQUEUED check in skcipher_recvmsg() is now dead but harmless,
+and is left alone to keep the fix minimal.
+
+Fixes: e870456d8e7c ("crypto: algif_skcipher - overhaul memory management")
+Cc: <stable@vger.kernel.org>
+Reported-by: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+Signed-off-by: Muhammet Kaan KILINÇ <muhammetkaankilinc@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ crypto/algif_skcipher.c | 75 +++++++++++++----------------------------
+ 1 file changed, 24 insertions(+), 51 deletions(-)
+
+diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
+index ba0a17fd95aca2..35ebc3e0201b04 100644
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -79,20 +79,6 @@ static int algif_skcipher_export(struct sock *sk, struct skcipher_request *req)
+       return err;
+ }
+-static void algif_skcipher_done(void *data, int err)
+-{
+-      struct af_alg_async_req *areq = data;
+-      struct sock *sk = areq->sk;
+-
+-      if (err)
+-              goto out;
+-
+-      err = algif_skcipher_export(sk, &areq->cra_u.skcipher_req);
+-
+-out:
+-      af_alg_async_cb(data, err);
+-}
+-
+ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
+                            size_t ignored, int flags)
+ {
+@@ -171,43 +157,30 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
+               cflags |= CRYPTO_SKCIPHER_REQ_CONT;
+       }
+-      if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
+-              /* AIO operation */
+-              sock_hold(sk);
+-              areq->iocb = msg->msg_iocb;
+-
+-              /* Remember output size that will be generated. */
+-              areq->outlen = len;
+-
+-              skcipher_request_set_callback(&areq->cra_u.skcipher_req,
+-                                            cflags |
+-                                            CRYPTO_TFM_REQ_MAY_SLEEP,
+-                                            algif_skcipher_done, areq);
+-              err = ctx->enc ?
+-                      crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
+-                      crypto_skcipher_decrypt(&areq->cra_u.skcipher_req);
+-
+-              /* AIO operation in progress */
+-              if (err == -EINPROGRESS)
+-                      return -EIOCBQUEUED;
+-
+-              sock_put(sk);
+-      } else {
+-              /* Synchronous operation */
+-              skcipher_request_set_callback(&areq->cra_u.skcipher_req,
+-                                            cflags |
+-                                            CRYPTO_TFM_REQ_MAY_SLEEP |
+-                                            CRYPTO_TFM_REQ_MAY_BACKLOG,
+-                                            crypto_req_done, &ctx->wait);
+-              err = crypto_wait_req(ctx->enc ?
+-                      crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
+-                      crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
+-                                               &ctx->wait);
+-
+-              if (!err)
+-                      err = algif_skcipher_export(
+-                              sk, &areq->cra_u.skcipher_req);
+-      }
++      /*
++       * Force synchronous processing.  The async (AIO) path passed the
++       * socket-wide ctx->iv into the request, which the worker
++       * dereferenced after the socket lock had been dropped, letting a
++       * concurrent sendmsg(ALG_SET_IV) inject an attacker IV.  Mainline
++       * removed the AIO socket path in commit fcc77d33a34c ("net: Remove
++       * support for AIO on sockets"); the minimal stable fix is to always
++       * complete synchronously, so ctx->iv is only ever dereferenced under
++       * the socket lock.  This also keeps the IV chaining intact: for
++       * ciphers with statesize == 0 (e.g. ctr, cbc) the chained IV is
++       * carried by the req->iv writeback into ctx->iv, which is only
++       * consistent on the synchronous path.
++       */
++      skcipher_request_set_callback(&areq->cra_u.skcipher_req,
++                                    cflags |
++                                    CRYPTO_TFM_REQ_MAY_SLEEP |
++                                    CRYPTO_TFM_REQ_MAY_BACKLOG,
++                                    crypto_req_done, &ctx->wait);
++      err = crypto_wait_req(ctx->enc ?
++              crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
++              crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
++                               &ctx->wait);
++      if (!err)
++              err = algif_skcipher_export(sk, &areq->cra_u.skcipher_req);
+ free:
+       af_alg_free_resources(areq);
+-- 
+2.53.0
+
diff --git a/staging-7.1/iommu-vt-d-clear-present-bit-before-tearing-down-sca.patch b/staging-7.1/iommu-vt-d-clear-present-bit-before-tearing-down-sca.patch
new file mode 100644 (file)
index 0000000..829cda4
--- /dev/null
@@ -0,0 +1,65 @@
+From bb96b190abfa0604a98e79205066f5d9692ed1d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 14:03:07 +0800
+Subject: iommu/vt-d: Clear Present bit before tearing down scalable-mode
+ context entry
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+[ Upstream commit f46452c3df7a8d8a5addc0926e76ef19ea7da0a0 ]
+
+device_pasid_table_teardown() zeroes the 128-bit scalable-mode context
+entry with context_clear_entry() while the Present bit is still set. This
+creates a window where the hardware can fetch a torn entry, with some
+fields already zeroed while Present is still set, leading to unpredictable
+behavior or spurious faults. The context-cache invalidation is issued only
+after the entry has been zeroed, and intel_pasid_free_table() then frees
+the PASID directory pages, so the IOMMU can keep walking a stale Present=1
+entry that points at freed memory.
+
+While x86 provides strong write ordering, the compiler may reorder the two
+64-bit writes to the entry, and the hardware fetch is not guaranteed to be
+atomic with respect to multiple CPU writes.
+
+Commit c1e4f1dccbe9d ("iommu/vt-d: Clear Present bit before tearing down
+context entry") fixed this exact pattern in domain_context_clear_one() and
+the copied-context path, but device_pasid_table_teardown() was not
+converted.
+
+Align it with the "Guidance to Software for Invalidations" in the VT-d
+spec, Section 6.5.3.3, using the same ownership handshake as the sibling
+fix: clear only the Present bit, flush it to the IOMMU, perform the
+context-cache invalidation, and only then zero the rest of the entry.
+
+Fixes: 81e921fd32161 ("iommu/vt-d: Fix NULL domain on device release")
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Assisted-by: Claude:claude-opus-4-7
+Link: https://lore.kernel.org/r/20260528025557.3209367-1-michael.bommarito@gmail.com
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/pasid.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
+index 89541b74ab8ca3..40910dc7363b13 100644
+--- a/drivers/iommu/intel/pasid.c
++++ b/drivers/iommu/intel/pasid.c
+@@ -748,10 +748,12 @@ static void device_pasid_table_teardown(struct device *dev, u8 bus, u8 devfn)
+       }
+       did = context_domain_id(context);
+-      context_clear_entry(context);
++      context_clear_present(context);
+       __iommu_flush_cache(iommu, context, sizeof(*context));
+       spin_unlock(&iommu->lock);
+       intel_context_flush_no_pasid(info, context, did);
++      context_clear_entry(context);
++      __iommu_flush_cache(iommu, context, sizeof(*context));
+ }
+ static int pci_pasid_table_teardown(struct pci_dev *pdev, u16 alias, void *data)
+-- 
+2.53.0
+
diff --git a/staging-7.1/series b/staging-7.1/series
new file mode 100644 (file)
index 0000000..60b2d45
--- /dev/null
@@ -0,0 +1,2 @@
+crypto-algif_skcipher-force-synchronous-processing.patch
+iommu-vt-d-clear-present-bit-before-tearing-down-sca.patch