]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
7.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Jun 2026 10:21:08 +0000 (11:21 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Jun 2026 10:21:08 +0000 (11:21 +0100)
added patches:
agp-amd64-fix-broken-error-propagation-in-agp_amd64_probe.patch
bpf-fix-null-pointer-dereference-in-bpf_sk_storage_clone-and-diag-paths.patch
i2c-stub-reject-i2c-block-transfers-with-invalid-length.patch
net-qualcomm-rmnet-fix-endpoint-use-after-free-in-rmnet_dellink.patch

queue-7.0/agp-amd64-fix-broken-error-propagation-in-agp_amd64_probe.patch [new file with mode: 0644]
queue-7.0/bpf-fix-null-pointer-dereference-in-bpf_sk_storage_clone-and-diag-paths.patch [new file with mode: 0644]
queue-7.0/i2c-stub-reject-i2c-block-transfers-with-invalid-length.patch [new file with mode: 0644]
queue-7.0/net-qualcomm-rmnet-fix-endpoint-use-after-free-in-rmnet_dellink.patch [new file with mode: 0644]
queue-7.0/series

diff --git a/queue-7.0/agp-amd64-fix-broken-error-propagation-in-agp_amd64_probe.patch b/queue-7.0/agp-amd64-fix-broken-error-propagation-in-agp_amd64_probe.patch
new file mode 100644 (file)
index 0000000..acbd322
--- /dev/null
@@ -0,0 +1,52 @@
+From b08472db93b1ccff84a7adec5779d47f0e9d3a30 Mon Sep 17 00:00:00 2001
+From: Mingyu Wang <25181214217@stu.xidian.edu.cn>
+Date: Mon, 4 May 2026 15:48:23 +0800
+Subject: agp/amd64: Fix broken error propagation in agp_amd64_probe()
+
+From: Mingyu Wang <25181214217@stu.xidian.edu.cn>
+
+commit b08472db93b1ccff84a7adec5779d47f0e9d3a30 upstream.
+
+A NULL pointer dereference was observed in the AMD64 AGP driver when
+running in a virtualized environment (e.g. qemu/kvm) without a physical
+AMD northbridge. The crash occurs in amd64_fetch_size() when attempting
+to dereference the pointer returned by node_to_amd_nb(0).
+
+The root cause of this crash is broken error propagation in
+agp_amd64_probe(): When no AMD northbridges are found, cache_nbs()
+correctly returns -ENODEV. However, the probe function erroneously
+checks the return value against exactly -1, rather than < 0.
+
+As a result, the hardware absence error is masked, allowing the driver
+to improperly proceed with initialization. It eventually calls
+agp_add_bridge(), which invokes amd64_fetch_size(). Since the hardware
+does not exist, node_to_amd_nb(0) returns NULL, leading to a General
+Protection Fault (GPF) when accessing its ->misc member.
+
+Fix the issue by correcting the error check in agp_amd64_probe() to
+abort properly when cache_nbs() returns any negative error code. This
+prevents the driver from erroneously proceeding without hardware, thereby
+avoiding the subsequent NULL pointer dereference at its source.
+
+Fixes: a32073bffc65 ("[PATCH] x86_64: Clean and enhance up K8 northbridge access code")
+Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Reviewed-by: Lukas Wunner <lukas@wunner.de>
+Cc: stable@vger.kernel.org # v2.6.18+
+Link: https://patch.msgid.link/20260504074823.99377-1-w15303746062@163.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/agp/amd64-agp.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/char/agp/amd64-agp.c
++++ b/drivers/char/agp/amd64-agp.c
+@@ -546,7 +546,7 @@ static int agp_amd64_probe(struct pci_de
+       /* Fill in the mode register */
+       pci_read_config_dword(pdev, bridge->capndx+PCI_AGP_STATUS, &bridge->mode);
+-      if (cache_nbs(pdev, cap_ptr) == -1) {
++      if (cache_nbs(pdev, cap_ptr) < 0) {
+               agp_put_bridge(bridge);
+               return -ENODEV;
+       }
diff --git a/queue-7.0/bpf-fix-null-pointer-dereference-in-bpf_sk_storage_clone-and-diag-paths.patch b/queue-7.0/bpf-fix-null-pointer-dereference-in-bpf_sk_storage_clone-and-diag-paths.patch
new file mode 100644 (file)
index 0000000..c1cd4bb
--- /dev/null
@@ -0,0 +1,100 @@
+From 375e4e33c18dfa05c5dfd5f3dfffeb29343dd4c7 Mon Sep 17 00:00:00 2001
+From: Weiming Shi <bestswngs@gmail.com>
+Date: Tue, 21 Apr 2026 23:54:12 -0700
+Subject: bpf: Fix NULL pointer dereference in bpf_sk_storage_clone and diag paths
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+commit 375e4e33c18dfa05c5dfd5f3dfffeb29343dd4c7 upstream.
+
+bpf_selem_unlink_nofail() sets SDATA(selem)->smap to NULL before
+removing the selem from the storage hlist. A concurrent RCU reader in
+bpf_sk_storage_clone() can observe the selem still on the list with
+smap already NULL, causing a NULL pointer dereference.
+
+ general protection fault, probably for non-canonical address 0xdffffc000000000a:
+ KASAN: null-ptr-deref in range [0x0000000000000050-0x0000000000000057]
+ RIP: 0010:bpf_sk_storage_clone+0x1cd/0xaa0 net/core/bpf_sk_storage.c:174
+ Call Trace:
+  <IRQ>
+  sk_clone+0xfed/0x1980 net/core/sock.c:2591
+  inet_csk_clone_lock+0x30/0x760 net/ipv4/inet_connection_sock.c:1222
+  tcp_create_openreq_child+0x35/0x2680 net/ipv4/tcp_minisocks.c:571
+  tcp_v4_syn_recv_sock+0x123/0xf90 net/ipv4/tcp_ipv4.c:1729
+  tcp_check_req+0x8e1/0x2580 include/net/tcp.h:855
+  tcp_v4_rcv+0x1845/0x3b80 net/ipv4/tcp_ipv4.c:2347
+
+Add a NULL check for smap in bpf_sk_storage_clone().
+
+bpf_sk_storage_diag_put_all() has the same issue. Add a NULL check
+and pass the validated smap directly to diag_get(), which is refactored
+to take smap as a parameter instead of reading it internally.
+
+bpf_sk_storage_diag_put() uses diag->maps[i] which is always valid
+under its refcount, so diag->maps[i] is passed directly to diag_get().
+
+Fixes: 5d800f87d0a5 ("bpf: Support lockless unlink when freeing map or local storage")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Acked-by: Amery Hung <ameryhung@gmail.com>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Link: https://patch.msgid.link/20260422065411.1007737-2-bestswngs@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/bpf_sk_storage.c |   13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/net/core/bpf_sk_storage.c
++++ b/net/core/bpf_sk_storage.c
+@@ -172,7 +172,7 @@ int bpf_sk_storage_clone(const struct so
+               struct bpf_map *map;
+               smap = rcu_dereference(SDATA(selem)->smap);
+-              if (!(smap->map.map_flags & BPF_F_CLONE))
++              if (!smap || !(smap->map.map_flags & BPF_F_CLONE))
+                       continue;
+               /* Note that for lockless listeners adding new element
+@@ -534,10 +534,10 @@ err_free:
+ }
+ EXPORT_SYMBOL_GPL(bpf_sk_storage_diag_alloc);
+-static int diag_get(struct bpf_local_storage_data *sdata, struct sk_buff *skb)
++static int diag_get(struct bpf_local_storage_map *smap,
++                  struct bpf_local_storage_data *sdata, struct sk_buff *skb)
+ {
+       struct nlattr *nla_stg, *nla_value;
+-      struct bpf_local_storage_map *smap;
+       /* It cannot exceed max nlattr's payload */
+       BUILD_BUG_ON(U16_MAX - NLA_HDRLEN < BPF_LOCAL_STORAGE_MAX_VALUE_SIZE);
+@@ -546,7 +546,6 @@ static int diag_get(struct bpf_local_sto
+       if (!nla_stg)
+               return -EMSGSIZE;
+-      smap = rcu_dereference(sdata->smap);
+       if (nla_put_u32(skb, SK_DIAG_BPF_STORAGE_MAP_ID, smap->map.id))
+               goto errout;
+@@ -599,9 +598,11 @@ static int bpf_sk_storage_diag_put_all(s
+       saved_len = skb->len;
+       hlist_for_each_entry_rcu(selem, &sk_storage->list, snode) {
+               smap = rcu_dereference(SDATA(selem)->smap);
++              if (!smap)
++                      continue;
+               diag_size += nla_value_size(smap->map.value_size);
+-              if (nla_stgs && diag_get(SDATA(selem), skb))
++              if (nla_stgs && diag_get(smap, SDATA(selem), skb))
+                       /* Continue to learn diag_size */
+                       err = -EMSGSIZE;
+       }
+@@ -668,7 +669,7 @@ int bpf_sk_storage_diag_put(struct bpf_s
+               diag_size += nla_value_size(diag->maps[i]->value_size);
+-              if (nla_stgs && diag_get(sdata, skb))
++              if (nla_stgs && diag_get((struct bpf_local_storage_map *)diag->maps[i], sdata, skb))
+                       /* Continue to learn diag_size */
+                       err = -EMSGSIZE;
+       }
diff --git a/queue-7.0/i2c-stub-reject-i2c-block-transfers-with-invalid-length.patch b/queue-7.0/i2c-stub-reject-i2c-block-transfers-with-invalid-length.patch
new file mode 100644 (file)
index 0000000..a602798
--- /dev/null
@@ -0,0 +1,71 @@
+From 6036b5067a8199ba7a2dc7b377d4b9dd276d5f9e Mon Sep 17 00:00:00 2001
+From: Weiming Shi <bestswngs@gmail.com>
+Date: Wed, 15 Apr 2026 01:23:39 +0800
+Subject: i2c: stub: Reject I2C block transfers with invalid length
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+commit 6036b5067a8199ba7a2dc7b377d4b9dd276d5f9e upstream.
+
+The I2C_SMBUS_I2C_BLOCK_DATA case in stub_xfer() uses data->block[0]
+as the transfer length. The existing check only clamps it to avoid
+overrunning the chip->words[256] register array, but does not validate
+it against I2C_SMBUS_BLOCK_MAX (32), which is the limit of the union
+i2c_smbus_data.block buffer (34 bytes total). The driver is a
+development/test tool (CONFIG_I2C_STUB=m, not built by default)
+that must be loaded with a chip_addr= parameter.
+
+A local user with access to /dev/i2c-* can issue an I2C_SMBUS ioctl
+with I2C_SMBUS_I2C_BLOCK_DATA and data->block[0] > 32, causing
+stub_xfer() to read or write past the end of the union
+i2c_smbus_data.block buffer:
+
+ BUG: KASAN: stack-out-of-bounds in stub_xfer (drivers/i2c/i2c-stub.c:223)
+ Read of size 1 at addr ffff88800abcfd92 by task exploit/81
+ Call Trace:
+  <TASK>
+  stub_xfer (drivers/i2c/i2c-stub.c:223)
+  __i2c_smbus_xfer (drivers/i2c/i2c-core-smbus.c:593)
+  i2c_smbus_xfer (drivers/i2c/i2c-core-smbus.c:536)
+  i2cdev_ioctl_smbus (drivers/i2c/i2c-dev.c:391)
+  i2cdev_ioctl (drivers/i2c/i2c-dev.c:478)
+  __x64_sys_ioctl (fs/ioctl.c:583)
+  do_syscall_64 (arch/x86/entry/syscall_64.c:94)
+  entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
+  </TASK>
+
+The bug exists because i2c-stub implements .smbus_xfer directly,
+bypassing the I2C_SMBUS_BLOCK_MAX validation in
+i2c_smbus_xfer_emulated(). The I2C_SMBUS_BLOCK_DATA case in the same
+function correctly validates against I2C_SMBUS_BLOCK_MAX, but the
+I2C_SMBUS_I2C_BLOCK_DATA case does not.
+
+Fix by rejecting transfers with data->block[0] == 0 or
+data->block[0] > I2C_SMBUS_BLOCK_MAX with -EINVAL, consistent with
+both the I2C_SMBUS_BLOCK_DATA case in the same function and the
+I2C_SMBUS_I2C_BLOCK_DATA validation in i2c_smbus_xfer_emulated().
+
+Fixes: 4710317891e4 ("i2c-stub: Implement I2C block support")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Reviewed-by: Jean Delvare <jdelvare@suse.de>
+Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/i2c-stub.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/i2c/i2c-stub.c
++++ b/drivers/i2c/i2c-stub.c
+@@ -214,6 +214,11 @@ static s32 stub_xfer(struct i2c_adapter
+                * We ignore banks here, because banked chips don't use I2C
+                * block transfers
+                */
++              if (data->block[0] == 0 ||
++                  data->block[0] > I2C_SMBUS_BLOCK_MAX) {
++                      ret = -EINVAL;
++                      break;
++              }
+               if (data->block[0] > 256 - command)     /* Avoid overrun */
+                       data->block[0] = 256 - command;
+               len = data->block[0];
diff --git a/queue-7.0/net-qualcomm-rmnet-fix-endpoint-use-after-free-in-rmnet_dellink.patch b/queue-7.0/net-qualcomm-rmnet-fix-endpoint-use-after-free-in-rmnet_dellink.patch
new file mode 100644 (file)
index 0000000..f3f3b27
--- /dev/null
@@ -0,0 +1,87 @@
+From d00c953a8f69921f484b629801766da68f27f658 Mon Sep 17 00:00:00 2001
+From: Weiming Shi <bestswngs@gmail.com>
+Date: Thu, 14 May 2026 05:25:12 -0700
+Subject: net: qualcomm: rmnet: fix endpoint use-after-free in rmnet_dellink()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+commit d00c953a8f69921f484b629801766da68f27f658 upstream.
+
+rmnet_dellink() removes the endpoint from the hash table with
+hlist_del_init_rcu() and then immediately frees it with kfree(). However,
+RCU readers on the receive path (rmnet_rx_handler ->
+__rmnet_map_ingress_handler) may still hold a reference to the endpoint and
+dereference ep->egress_dev after the memory has been freed. The endpoint is
+a kmalloc-32 object, and the stale read at offset 8 corresponds to the
+egress_dev pointer.
+
+  BUG: unable to handle page fault for address: ffffffffde942eef
+  Oops: 0002 [#1] SMP NOPTI
+  CPU: 1 UID: 0 PID: 137 Comm: poc_write Not tainted 7.0.0+ #4 PREEMPTLAZY
+  RIP: 0010:rmnet_vnd_rx_fixup (rmnet_vnd.c:27)
+  Call Trace:
+   <TASK>
+   __rmnet_map_ingress_handler (rmnet_handlers.c:48 rmnet_handlers.c:101)
+   rmnet_rx_handler (rmnet_handlers.c:129 rmnet_handlers.c:235)
+   __netif_receive_skb_core.constprop.0 (net/core/dev.c:6096)
+   __netif_receive_skb_one_core (net/core/dev.c:6208)
+   netif_receive_skb (net/core/dev.c:6467)
+   tun_get_user (drivers/net/tun.c:1955)
+   tun_chr_write_iter (drivers/net/tun.c:2003)
+   vfs_write (fs/read_write.c:688)
+   ksys_write (fs/read_write.c:740)
+   </TASK>
+
+Add an rcu_head field to struct rmnet_endpoint and replace kfree() with
+kfree_rcu() so the endpoint memory remains valid through the RCU grace
+period. Also remove the rmnet_vnd_dellink() call and inline only the
+nr_rmnet_devs decrement, since rmnet_vnd_dellink() would set
+ep->egress_dev to NULL during the grace period, creating a data race
+with lockless readers.
+
+Fixes: ceed73a2cf4a ("drivers: net: ethernet: qualcomm: rmnet: Initial implementation")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Link: https://patch.msgid.link/20260514122511.3083479-2-bestswngs@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c |    8 ++++----
+ drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h |    1 +
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
++++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
+@@ -213,8 +213,8 @@ static void rmnet_dellink(struct net_dev
+       ep = rmnet_get_endpoint(real_port, mux_id);
+       if (ep) {
+               hlist_del_init_rcu(&ep->hlnode);
+-              rmnet_vnd_dellink(mux_id, real_port, ep);
+-              kfree(ep);
++              real_port->nr_rmnet_devs--;
++              kfree_rcu(ep, rcu);
+       }
+       netdev_upper_dev_unlink(real_dev, dev);
+@@ -238,9 +238,9 @@ static void rmnet_force_unassociate_devi
+               hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
+                       unregister_netdevice_queue(ep->egress_dev, &list);
+                       netdev_upper_dev_unlink(real_dev, ep->egress_dev);
+-                      rmnet_vnd_dellink(ep->mux_id, port, ep);
+                       hlist_del_init_rcu(&ep->hlnode);
+-                      kfree(ep);
++                      port->nr_rmnet_devs--;
++                      kfree_rcu(ep, rcu);
+               }
+               rmnet_unregister_real_device(real_dev);
+               unregister_netdevice_many(&list);
+--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
++++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
+@@ -18,6 +18,7 @@ struct rmnet_endpoint {
+       u8 mux_id;
+       struct net_device *egress_dev;
+       struct hlist_node hlnode;
++      struct rcu_head rcu;
+ };
+ struct rmnet_egress_agg_params {
index 098900599bf68ec20b0fa508eb25fd2ac7a6b4f5..676eaf89dd598c53a04b8a0b16415b25e03e15ec 100644 (file)
@@ -9,3 +9,7 @@ firmware-samsung-acpm-fix-missing-lkmm-barriers-in-sequence-allocator.patch
 fuse-re-lock-request-before-replacing-page-cache-folio.patch
 revert-nfsd-defer-sub-object-cleanup-in-export-put-callbacks.patch
 rdma-bnxt_re-zero-shared-page-before-exposing-to-userspace.patch
+bpf-fix-null-pointer-dereference-in-bpf_sk_storage_clone-and-diag-paths.patch
+i2c-stub-reject-i2c-block-transfers-with-invalid-length.patch
+net-qualcomm-rmnet-fix-endpoint-use-after-free-in-rmnet_dellink.patch
+agp-amd64-fix-broken-error-propagation-in-agp_amd64_probe.patch