]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Jul 2026 12:29:09 +0000 (14:29 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Jul 2026 12:29:09 +0000 (14:29 +0200)
added patches:
arm64-dts-qcom-sdm630-describe-adsp_mem-region-properly.patch
kvm-arm64-vgic-check-the-interrupt-is-still-ours-before-migrating-it.patch
kvm-arm64-vgic-handle-race-between-interrupt-affinity-change-and-lpi-disabling.patch
mlxsw-fix-refcount-leak-in-mlxsw_sp_vrs_lpm_tree_replace.patch
net-atm-reject-out-of-range-traffic-classes-in-qos-validation.patch
net-ife-require-eth_hlen-to-be-pullable-in-ife_decode.patch
net-qrtr-fix-32-bit-integer-overflow-in-qrtr_endpoint_post.patch
vduse-fix-race-in-vduse_dev_msg_sync-and-vduse_dev_read_iter.patch

queue-5.15/arm64-dts-qcom-sdm630-describe-adsp_mem-region-properly.patch [new file with mode: 0644]
queue-5.15/kvm-arm64-vgic-check-the-interrupt-is-still-ours-before-migrating-it.patch [new file with mode: 0644]
queue-5.15/kvm-arm64-vgic-handle-race-between-interrupt-affinity-change-and-lpi-disabling.patch [new file with mode: 0644]
queue-5.15/mlxsw-fix-refcount-leak-in-mlxsw_sp_vrs_lpm_tree_replace.patch [new file with mode: 0644]
queue-5.15/net-atm-reject-out-of-range-traffic-classes-in-qos-validation.patch [new file with mode: 0644]
queue-5.15/net-ife-require-eth_hlen-to-be-pullable-in-ife_decode.patch [new file with mode: 0644]
queue-5.15/net-qrtr-fix-32-bit-integer-overflow-in-qrtr_endpoint_post.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/vduse-fix-race-in-vduse_dev_msg_sync-and-vduse_dev_read_iter.patch [new file with mode: 0644]

diff --git a/queue-5.15/arm64-dts-qcom-sdm630-describe-adsp_mem-region-properly.patch b/queue-5.15/arm64-dts-qcom-sdm630-describe-adsp_mem-region-properly.patch
new file mode 100644 (file)
index 0000000..d7dd4d9
--- /dev/null
@@ -0,0 +1,44 @@
+From ce414263e9ebe5080381a50cbdf9065c29816202 Mon Sep 17 00:00:00 2001
+From: Nickolay Goppen <setotau@mainlining.org>
+Date: Wed, 29 Apr 2026 12:30:11 +0300
+Subject: arm64: dts: qcom: sdm630: describe adsp_mem region properly
+
+From: Nickolay Goppen <setotau@mainlining.org>
+
+commit ce414263e9ebe5080381a50cbdf9065c29816202 upstream.
+
+Downstream [1] this region is marked as shared, reusable and dynamic so
+describe it that way.
+
+[1]: https://github.com/xiaomi-sdm660/android_kernel_xiaomi_sdm660/blob/11-EAS/arch/arm/boot/dts/qcom/sdm660.dtsi#L448
+
+Fixes: b190fb010664 ("arm64: dts: qcom: sdm630: Add sdm630 dts file")
+Cc: stable@vger.kernel.org
+Reviewed-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Signed-off-by: Nickolay Goppen <setotau@mainlining.org>
+Link: https://lore.kernel.org/r/20260429-qcom-sdm660-cdsp-adsp-fastrpc-dts-fix-v5-4-16bc82e622ad@mainlining.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/qcom/sdm630.dtsi |    9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/arch/arm64/boot/dts/qcom/sdm630.dtsi
++++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi
+@@ -397,9 +397,12 @@
+                       no-map;
+               };
+-              adsp_mem: adsp-region@f6000000 {
+-                      reg = <0x0 0xf6000000 0x0 0x800000>;
+-                      no-map;
++              adsp_mem: adsp-region {
++                      compatible = "shared-dma-pool";
++                      alloc-ranges = <0x0 0x80000000 0x0 0x80000000>;
++                      alignment = <0x0 0x400000>;
++                      size = <0x0 0x800000>;
++                      reusable;
+               };
+               qseecom_mem: qseecom-region@f6800000 {
diff --git a/queue-5.15/kvm-arm64-vgic-check-the-interrupt-is-still-ours-before-migrating-it.patch b/queue-5.15/kvm-arm64-vgic-check-the-interrupt-is-still-ours-before-migrating-it.patch
new file mode 100644 (file)
index 0000000..2d3d909
--- /dev/null
@@ -0,0 +1,60 @@
+From 0074b82cdfcb5fd13710a0ac308ade68ac6f6fbe Mon Sep 17 00:00:00 2001
+From: Hyunwoo Kim <imv4bel@gmail.com>
+Date: Fri, 5 Jun 2026 05:59:15 +0900
+Subject: KVM: arm64: vgic: Check the interrupt is still ours before migrating it
+
+From: Hyunwoo Kim <imv4bel@gmail.com>
+
+commit 0074b82cdfcb5fd13710a0ac308ade68ac6f6fbe upstream.
+
+vgic_prune_ap_list() drops both ap_list_lock and irq_lock while migrating
+an interrupt to another vCPU. After reacquiring the locks it only checks
+that the affinity is unchanged (target_vcpu == vgic_target_oracle(irq))
+before moving the interrupt, which assumes that an interrupt whose affinity
+is preserved is still queued on this vCPU's ap_list.
+
+That assumption no longer holds if the interrupt is taken off the ap_list
+while the locks are dropped. vgic_flush_pending_lpis() removes the
+interrupt from the list and sets irq->vcpu to NULL, but leaves
+enabled/pending/target_vcpu untouched. As the interrupt is still enabled
+and pending, vgic_target_oracle() returns the same target_vcpu, so the
+affinity check passes and list_del() is run a second time on an entry that
+has already been removed.
+
+Also check that the interrupt is still assigned to this vCPU
+(irq->vcpu == vcpu) before moving it.
+
+Fixes: 0919e84c0fc1 ("KVM: arm/arm64: vgic-new: Add IRQ sync/flush framework")
+Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
+Link: https://patch.msgid.link/aiHnI1mu6SGQrgnz@v4bel
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/vgic/vgic.c |   11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/arch/arm64/kvm/vgic/vgic.c
++++ b/arch/arm64/kvm/vgic/vgic.c
+@@ -684,15 +684,16 @@ retry:
+               raw_spin_lock(&irq->irq_lock);
+               /*
+-               * If the affinity has been preserved, move the
+-               * interrupt around. Otherwise, it means things have
+-               * changed while the interrupt was unlocked, and we
+-               * need to replay this.
++               * If the interrupt is still ours and its affinity has
++               * been preserved, move it around. Otherwise, it means
++               * things have changed while the interrupt was unlocked
++               * (it may even have been taken off the list with its
++               * affinity left untouched), and we need to replay this.
+                *
+                * In all cases, we cannot trust the list not to have
+                * changed, so we restart from the beginning.
+                */
+-              if (target_vcpu == vgic_target_oracle(irq)) {
++              if (irq->vcpu == vcpu && target_vcpu == vgic_target_oracle(irq)) {
+                       struct vgic_cpu *new_cpu = &target_vcpu->arch.vgic_cpu;
+                       list_del(&irq->ap_list);
diff --git a/queue-5.15/kvm-arm64-vgic-handle-race-between-interrupt-affinity-change-and-lpi-disabling.patch b/queue-5.15/kvm-arm64-vgic-handle-race-between-interrupt-affinity-change-and-lpi-disabling.patch
new file mode 100644 (file)
index 0000000..2a0e468
--- /dev/null
@@ -0,0 +1,76 @@
+From 7258770e5814f15e8308ebda82ac9acf6964ba8e Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <maz@kernel.org>
+Date: Mon, 15 Jun 2026 19:16:25 +0100
+Subject: KVM: arm64: vgic: Handle race between interrupt affinity change and LPI disabling
+
+From: Marc Zyngier <maz@kernel.org>
+
+commit 7258770e5814f15e8308ebda82ac9acf6964ba8e upstream.
+
+Hyunwoo Kim reports some really bad races should the following
+situation occur:
+
+- LPI-I is pending in vcpu-B's AP list
+- vcpu-A writes to vcpu-B's RD to disable its LPIs
+- vcpu-C moves I from B to C
+
+If the last two race nicely enough, vgic_prune_ap_list() can drop
+the irq and AP list locks, reacquire them, and in the interval
+the irq has been freed. UAF follows.
+
+The fix is two-fold:
+
+- Before dropping the irq and ap_list locks, take a reference on
+  the irq
+
+- Do not try to handle migration of the pending bit: there is no
+  expectation that this state is retained, as per the architecture
+
+With that, we're sure that the interrupt is still around, and we
+safely remove it from the AP list as it has no target at this
+stage (unless another interrupt fires, but that's another story).
+
+Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
+Tested-by: Hyunwoo Kim <imv4bel@gmail.com>
+Link: https://lore.kernel.org/r/ailsCnyoS82r_QRz@v4bel
+Link: https://patch.msgid.link/20260615181625.3029352-1-maz@kernel.org
+Fixes: 5dd4b924e390a ("KVM: arm/arm64: vgic: Add refcounting for IRQs")
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/vgic/vgic.c |    9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/arch/arm64/kvm/vgic/vgic.c
++++ b/arch/arm64/kvm/vgic/vgic.c
+@@ -158,6 +158,7 @@ void vgic_flush_pending_lpis(struct kvm_
+       list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
+               if (irq->intid >= VGIC_MIN_LPI) {
+                       raw_spin_lock(&irq->irq_lock);
++                      irq->pending_latch = false;
+                       list_del(&irq->ap_list);
+                       irq->vcpu = NULL;
+                       raw_spin_unlock(&irq->irq_lock);
+@@ -661,7 +662,11 @@ retry:
+                       continue;
+               }
+-              /* This interrupt looks like it has to be migrated. */
++              /*
++               * This interrupt looks like it has to be migrated,
++               * make sure it is kept alive while locks are dropped.
++               */
++              vgic_get_irq_ref(irq);
+               raw_spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&vgic_cpu->ap_list_lock);
+@@ -706,6 +711,8 @@ retry:
+               raw_spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
+               raw_spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
++              deleted_lpis |= vgic_put_irq_norelease(vcpu->kvm, irq);
++
+               if (target_vcpu_needs_kick) {
+                       kvm_make_request(KVM_REQ_IRQ_PENDING, target_vcpu);
+                       kvm_vcpu_kick(target_vcpu);
diff --git a/queue-5.15/mlxsw-fix-refcount-leak-in-mlxsw_sp_vrs_lpm_tree_replace.patch b/queue-5.15/mlxsw-fix-refcount-leak-in-mlxsw_sp_vrs_lpm_tree_replace.patch
new file mode 100644 (file)
index 0000000..152fe26
--- /dev/null
@@ -0,0 +1,47 @@
+From 21cf8dc478a49e8de039c2739b1646a774cb1944 Mon Sep 17 00:00:00 2001
+From: Wentao Liang <vulab@iscas.ac.cn>
+Date: Tue, 9 Jun 2026 08:47:30 +0000
+Subject: mlxsw: fix refcount leak in mlxsw_sp_vrs_lpm_tree_replace()
+
+From: Wentao Liang <vulab@iscas.ac.cn>
+
+commit 21cf8dc478a49e8de039c2739b1646a774cb1944 upstream.
+
+When mlxsw_sp_vrs_lpm_tree_replace() fails after replacing some VRs,
+the error rollback loop does not correctly revert the preceding
+replacements. The loop decrements the index but fails to update the
+vr pointer, which still points to the VR that caused the failure. As
+a result, the condition and the rollback call always operate on the
+same VR, potentially calling mlxsw_sp_vr_lpm_tree_replace() multiple
+times on it while never rolling back the earlier VRs. Those VRs
+continue to hold a reference to new_tree acquired via
+mlxsw_sp_lpm_tree_hold(), leaking the reference count of new_tree.
+
+Fix by reinitializing vr inside the error loop with the updated index:
+
+       vr = &mlxsw_sp->router->vrs[i];
+
+so that the loop correctly iterates over all VRs that were actually
+replaced.
+
+Cc: stable@vger.kernel.org
+Fixes: fc922bb0dd94 ("mlxsw: spectrum_router: Use one LPM tree for all virtual routers")
+Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260609084730.215732-1-vulab@iscas.ac.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+@@ -1007,6 +1007,7 @@ static int mlxsw_sp_vrs_lpm_tree_replace
+ err_tree_replace:
+       for (i--; i >= 0; i--) {
++              vr = &mlxsw_sp->router->vrs[i];
+               if (!mlxsw_sp_vr_lpm_tree_should_replace(vr, proto, new_id))
+                       continue;
+               mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp,
diff --git a/queue-5.15/net-atm-reject-out-of-range-traffic-classes-in-qos-validation.patch b/queue-5.15/net-atm-reject-out-of-range-traffic-classes-in-qos-validation.patch
new file mode 100644 (file)
index 0000000..15d830f
--- /dev/null
@@ -0,0 +1,46 @@
+From cdf19f380e46192e7084be559638aab1f6ed86a2 Mon Sep 17 00:00:00 2001
+From: Zhengchuan Liang <zcliangcn@gmail.com>
+Date: Tue, 9 Jun 2026 16:34:37 +0800
+Subject: net: atm: reject out-of-range traffic classes in QoS validation
+
+From: Zhengchuan Liang <zcliangcn@gmail.com>
+
+commit cdf19f380e46192e7084be559638aab1f6ed86a2 upstream.
+
+Reject ATM traffic classes above ATM_ANYCLASS in check_tp().
+SO_ATMQOS stores the supplied QoS after check_qos() succeeds, so
+accepting larger values leaves invalid traffic_class values in
+vcc->qos.
+
+That bad state later reaches pvc_info(), which indexes class_name[]
+with vcc->qos.{rx,tp}.traffic_class. Values above ATM_ANYCLASS cause
+an out-of-bounds read when /proc/net/atm/pvc is read.
+
+Tighten the existing QoS validation so invalid traffic_class values
+are rejected at the point where user supplied QoS is accepted.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Zhengchuan Liang <zcliangcn@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/58f02c6f73d9818fd5d2022e1116759fdde6116b.1780965530.git.zcliangcn@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/atm/common.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/atm/common.c
++++ b/net/atm/common.c
+@@ -720,6 +720,8 @@ static int atm_change_qos(struct atm_vcc
+ static int check_tp(const struct atm_trafprm *tp)
+ {
+       /* @@@ Should be merged with adjust_tp */
++      if (tp->traffic_class > ATM_ANYCLASS)
++              return -EINVAL;
+       if (!tp->traffic_class || tp->traffic_class == ATM_ANYCLASS)
+               return 0;
+       if (tp->traffic_class != ATM_UBR && !tp->min_pcr && !tp->pcr &&
diff --git a/queue-5.15/net-ife-require-eth_hlen-to-be-pullable-in-ife_decode.patch b/queue-5.15/net-ife-require-eth_hlen-to-be-pullable-in-ife_decode.patch
new file mode 100644 (file)
index 0000000..76b3da8
--- /dev/null
@@ -0,0 +1,45 @@
+From 9406f6012b7343661efb516a11c62d4db2b62f75 Mon Sep 17 00:00:00 2001
+From: Yong Wang <edragain@163.com>
+Date: Thu, 11 Jun 2026 02:37:43 +0800
+Subject: net: ife: require ETH_HLEN to be pullable in ife_decode()
+
+From: Yong Wang <edragain@163.com>
+
+commit 9406f6012b7343661efb516a11c62d4db2b62f75 upstream.
+
+ife decode may return after making only the outer IFE header and
+metadata pullable. The caller then passes the decapsulated packet to
+eth_type_trans(), which expects the inner Ethernet header to be
+accessible from the linear data area.
+
+With a malformed IFE frame, the inner Ethernet header may still be
+shorter than ETH_HLEN in the linear area, which can lead to a crash in
+the original code.
+
+Fix this by extending the pull check in ife_decode() so that the inner
+Ethernet header is also guaranteed to be pullable before returning.
+
+Fixes: ef6980b6becb ("introduce IFE action")
+Cc: stable@vger.kernel.org
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Yong Wang <edragain@163.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Link: https://patch.msgid.link/20260610183814.1648888-2-n05ec@lzu.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ife/ife.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ife/ife.c
++++ b/net/ife/ife.c
+@@ -79,7 +79,7 @@ void *ife_decode(struct sk_buff *skb, u1
+       if (unlikely(ifehdrln < 2))
+               return NULL;
+-      if (unlikely(!pskb_may_pull(skb, total_pull)))
++      if (unlikely(!pskb_may_pull(skb, total_pull + ETH_HLEN)))
+               return NULL;
+       ifehdr = (struct ifeheadr *)(skb->data + skb->dev->hard_header_len);
diff --git a/queue-5.15/net-qrtr-fix-32-bit-integer-overflow-in-qrtr_endpoint_post.patch b/queue-5.15/net-qrtr-fix-32-bit-integer-overflow-in-qrtr_endpoint_post.patch
new file mode 100644 (file)
index 0000000..1844807
--- /dev/null
@@ -0,0 +1,46 @@
+From 20054869770c7df060c5ecee3e8bbf9029c47191 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Thu, 11 Jun 2026 08:54:55 -0400
+Subject: net: qrtr: fix 32-bit integer overflow in qrtr_endpoint_post()
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit 20054869770c7df060c5ecee3e8bbf9029c47191 upstream.
+
+qrtr_endpoint_post() validates an incoming packet with
+
+       if (!size || len != ALIGN(size, 4) + hdrlen)
+               goto err;
+
+where size comes from the wire. On 32-bit, size_t is 32 bits and
+ALIGN(size, 4) wraps to 0 for size >= 0xfffffffd, so the check
+passes and skb_put_data(skb, data + hdrlen, size) writes past the
+hdrlen-sized skb and oopses the kernel. 64-bit is unaffected.
+
+This is the 32-bit residual of ad9d24c9429e2 ("net: qrtr: fix OOB
+Read in qrtr_endpoint_post"), which fixed only the 64-bit case.
+
+Reject any size that cannot fit the buffer before the ALIGN.
+
+Fixes: ad9d24c9429e2 ("net: qrtr: fix OOB Read in qrtr_endpoint_post")
+Cc: stable@vger.kernel.org
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260611125455.2352279-1-michael.bommarito@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/qrtr/af_qrtr.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/qrtr/af_qrtr.c
++++ b/net/qrtr/af_qrtr.c
+@@ -491,7 +491,7 @@ int qrtr_endpoint_post(struct qrtr_endpo
+               goto err;
+       }
+-      if (!size || len != ALIGN(size, 4) + hdrlen)
++      if (!size || size > len || len != ALIGN(size, 4) + hdrlen)
+               goto err;
+       if ((cb->type == QRTR_TYPE_NEW_SERVER ||
index cc07d4af89064c63cd2b1aaaa878a8ccebe7a7be..51a48057cc2edaf444b7ccf22d455df80bfed4b3 100644 (file)
@@ -554,3 +554,11 @@ regulator-core-make-regulator_lock_two-logic-easier-.patch
 regulator-core-regulator_lock_two-should-test-for-ed.patch
 net-mlx5-fix-l3-tunnel-entropy-refcount-leak.patch
 smb-client-fix-overflow-in-passthrough-ioctl-bounds-.patch
+mlxsw-fix-refcount-leak-in-mlxsw_sp_vrs_lpm_tree_replace.patch
+vduse-fix-race-in-vduse_dev_msg_sync-and-vduse_dev_read_iter.patch
+net-qrtr-fix-32-bit-integer-overflow-in-qrtr_endpoint_post.patch
+net-atm-reject-out-of-range-traffic-classes-in-qos-validation.patch
+net-ife-require-eth_hlen-to-be-pullable-in-ife_decode.patch
+arm64-dts-qcom-sdm630-describe-adsp_mem-region-properly.patch
+kvm-arm64-vgic-check-the-interrupt-is-still-ours-before-migrating-it.patch
+kvm-arm64-vgic-handle-race-between-interrupt-affinity-change-and-lpi-disabling.patch
diff --git a/queue-5.15/vduse-fix-race-in-vduse_dev_msg_sync-and-vduse_dev_read_iter.patch b/queue-5.15/vduse-fix-race-in-vduse_dev_msg_sync-and-vduse_dev_read_iter.patch
new file mode 100644 (file)
index 0000000..fac5f17
--- /dev/null
@@ -0,0 +1,108 @@
+From ae9c13b6fd79087cc5a216ee1649b6f012c2a238 Mon Sep 17 00:00:00 2001
+From: Zhang Tianci <zhangtianci.1997@bytedance.com>
+Date: Thu, 26 Feb 2026 19:55:50 +0800
+Subject: vduse: Fix race in vduse_dev_msg_sync and vduse_dev_read_iter
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zhang Tianci <zhangtianci.1997@bytedance.com>
+
+commit ae9c13b6fd79087cc5a216ee1649b6f012c2a238 upstream.
+
+There is one race case in vduse_dev_msg_sync and vduse_dev_read_iter:
+
+vduse_dev_read_iter():
+    lock(msg_lock);
+    dequeue_msg(send_list);
+    unlock(msg_lock);
+vduse_dev_msg_sync():
+    wait_timeout() finish
+    lock(msg_lock);
+    check msg->complete is false
+        list_del(msg);   <- double list_del() crash!
+
+To fix this case, we shall ensure vduse_msg is on send_list or recv_list
+outside the msg_lock critical section.
+
+Fixes: c8a6153b6c59 ("vduse: Introduce VDUSE - vDPA Device in Userspace")
+Cc: stable@vger.kernel.org
+Signed-off-by: Zhang Tianci <zhangtianci.1997@bytedance.com>
+Reviewed-by: Xie Yongji <xieyongji@bytedance.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Acked-by: Eugenio PĂ©rez <eperezma@redhat.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Message-ID: <20260226115550.1814-3-zhangtianci.1997@bytedance.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/vdpa/vdpa_user/vduse_dev.c |   37 +++++++++++++++++++++++++++----------
+ 1 file changed, 27 insertions(+), 10 deletions(-)
+
+--- a/drivers/vdpa/vdpa_user/vduse_dev.c
++++ b/drivers/vdpa/vdpa_user/vduse_dev.c
+@@ -308,6 +308,7 @@ static ssize_t vduse_dev_read_iter(struc
+       struct file *file = iocb->ki_filp;
+       struct vduse_dev *dev = file->private_data;
+       struct vduse_dev_msg *msg;
++      struct vduse_dev_request req;
+       int size = sizeof(struct vduse_dev_request);
+       ssize_t ret;
+@@ -319,12 +320,11 @@ static ssize_t vduse_dev_read_iter(struc
+               msg = vduse_dequeue_msg(&dev->send_list);
+               if (msg)
+                       break;
++              spin_unlock(&dev->msg_lock);
+-              ret = -EAGAIN;
+               if (file->f_flags & O_NONBLOCK)
+-                      goto unlock;
++                      return -EAGAIN;
+-              spin_unlock(&dev->msg_lock);
+               ret = wait_event_interruptible_exclusive(dev->waitq,
+                                       !list_empty(&dev->send_list));
+               if (ret)
+@@ -332,17 +332,34 @@ static ssize_t vduse_dev_read_iter(struc
+               spin_lock(&dev->msg_lock);
+       }
++
++      memcpy(&req, &msg->req, sizeof(req));
++      /*
++       * We must ensure vduse_msg is on send_list or recv_list before unlock
++       * dev->msg_lock. Because vduse_dev_msg_sync() may be timeout when we
++       * copy data to userspace, and will call list_del() for this msg.
++       */
++      vduse_enqueue_msg(&dev->recv_list, msg);
+       spin_unlock(&dev->msg_lock);
+-      ret = copy_to_iter(&msg->req, size, to);
+-      spin_lock(&dev->msg_lock);
++
++      ret = copy_to_iter(&req, size, to);
+       if (ret != size) {
++              /*
++               * Roll back: move msg back to send_list if still pending.
++               *
++               * NOTE:
++               * vduse_find_msg() must use req.request_id instead of `msg`.
++               * A malicious userspace may reply to this request, and wake up
++               * the caller, after which `msg` will have already been freed.
++               * And here vduse_find_msg() will return NULL then do nothing.
++               */
++              spin_lock(&dev->msg_lock);
++              msg = vduse_find_msg(&dev->recv_list, req.request_id);
++              if (msg)
++                      vduse_enqueue_msg_head(&dev->send_list, msg);
++              spin_unlock(&dev->msg_lock);
+               ret = -EFAULT;
+-              vduse_enqueue_msg_head(&dev->send_list, msg);
+-              goto unlock;
+       }
+-      vduse_enqueue_msg(&dev->recv_list, msg);
+-unlock:
+-      spin_unlock(&dev->msg_lock);
+       return ret;
+ }