--- /dev/null
+From b4a9ea2b55c10bfd11b13a3ba981babdd49f788b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 18:29:50 +0300
+Subject: ALSA: usb-audio: fix null pointer dereference on pointer cs_desc
+
+From: Chengfeng Ye <cyeaa@connect.ust.hk>
+
+commit b97053df0f04747c3c1e021ecbe99db675342954 upstream.
+
+The pointer cs_desc return from snd_usb_find_clock_source could
+be null, so there is a potential null pointer dereference issue.
+Fix this by adding a null check before dereference.
+
+Signed-off-by: Chengfeng Ye <cyeaa@connect.ust.hk>
+Link: https://lore.kernel.org/r/20211024111736.11342-1-cyeaa@connect.ust.hk
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Fixes: 1dc669fed61a ("ALSA: usb-audio: UAC2: support read-only freq control")
+[ kovalev: bp to fix CVE-2021-47211; added Fixes tag; the null
+ check was added into both UAC2 and UAC3 branches since the
+ older kernel still has the clock source lookup split between
+ snd_usb_find_clock_source() and snd_usb_find_clock_source_v3()
+ (see upstream commit 9ec730052fa2); return -ENXIO instead of 0
+ to match upstream behavior, where the caller reaches the clock
+ validation path and returns -ENXIO ]
+Signed-off-by: Vasiliy Kovalev <kovalev@altlinux.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/clock.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/sound/usb/clock.c b/sound/usb/clock.c
+index 197a6b7d8ad6f9..8759e20c419ed5 100644
+--- a/sound/usb/clock.c
++++ b/sound/usb/clock.c
+@@ -646,11 +646,17 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
+ struct uac3_clock_source_descriptor *cs_desc;
+
+ cs_desc = snd_usb_find_clock_source_v3(chip->ctrl_intf, clock);
++
++ if (!cs_desc)
++ return -ENXIO;
+ bmControls = le32_to_cpu(cs_desc->bmControls);
+ } else {
+ struct uac_clock_source_descriptor *cs_desc;
+
+ cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock);
++
++ if (!cs_desc)
++ return -ENXIO;
+ bmControls = cs_desc->bmControls;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 500f36193c6c19b959dcfad8ad70029000cad7fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Apr 2026 17:24:36 +0200
+Subject: net/sched: cls_fw: fix NULL dereference of "old" filters before
+ change()
+
+From: Davide Caratti <dcaratti@redhat.com>
+
+[ Upstream commit 65782b2db7321d5f97c16718c4c7f6c7205a56be ]
+
+Like pointed out by Sashiko [1], since commit ed76f5edccc9 ("net: sched:
+protect filter_chain list with filter_chain_lock mutex") TC filters are
+added to a shared block and published to datapath before their ->change()
+function is called. This is a problem for cls_fw: an invalid filter
+created with the "old" method can still classify some packets before it
+is destroyed by the validation logic added by Xiang.
+Therefore, insisting with repeated runs of the following script:
+
+ # ip link add dev crash0 type dummy
+ # ip link set dev crash0 up
+ # mausezahn crash0 -c 100000 -P 10 \
+ > -A 4.3.2.1 -B 1.2.3.4 -t udp "dp=1234" -q &
+ # sleep 1
+ # tc qdisc add dev crash0 egress_block 1 clsact
+ # tc filter add block 1 protocol ip prio 1 matchall \
+ > action skbedit mark 65536 continue
+ # tc filter add block 1 protocol ip prio 2 fw
+ # ip link del dev crash0
+
+can still make fw_classify() hit the WARN_ON() in [2]:
+
+ WARNING: ./include/net/pkt_cls.h:88 at fw_classify+0x244/0x250 [cls_fw], CPU#18: mausezahn/1399
+ Modules linked in: cls_fw(E) act_skbedit(E)
+ CPU: 18 UID: 0 PID: 1399 Comm: mausezahn Tainted: G E 7.0.0-rc6-virtme #17 PREEMPT(full)
+ Tainted: [E]=UNSIGNED_MODULE
+ Hardware name: Red Hat KVM, BIOS 1.16.3-2.el9 04/01/2014
+ RIP: 0010:fw_classify+0x244/0x250 [cls_fw]
+ Code: 5c 49 c7 45 00 00 00 00 00 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 5b b8 ff ff ff ff 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 90 <0f> 0b 90 eb a0 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90
+ RSP: 0018:ffffd1b7026bf8a8 EFLAGS: 00010202
+ RAX: ffff8c5ac9c60800 RBX: ffff8c5ac99322c0 RCX: 0000000000000004
+ RDX: 0000000000000001 RSI: ffff8c5b74d7a000 RDI: ffff8c5ac8284f40
+ RBP: ffffd1b7026bf8d0 R08: 0000000000000000 R09: ffffd1b7026bf9b0
+ R10: 00000000ffffffff R11: 0000000000000000 R12: 0000000000010000
+ R13: ffffd1b7026bf930 R14: ffff8c5ac8284f40 R15: 0000000000000000
+ FS: 00007fca40c37740(0000) GS:ffff8c5b74d7a000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 00007fca40e822a0 CR3: 0000000005ca0001 CR4: 0000000000172ef0
+ Call Trace:
+ <TASK>
+ tcf_classify+0x17d/0x5c0
+ tc_run+0x9d/0x150
+ __dev_queue_xmit+0x2ab/0x14d0
+ ip_finish_output2+0x340/0x8f0
+ ip_output+0xa4/0x250
+ raw_sendmsg+0x147d/0x14b0
+ __sys_sendto+0x1cc/0x1f0
+ __x64_sys_sendto+0x24/0x30
+ do_syscall_64+0x126/0xf80
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+ RIP: 0033:0x7fca40e822ba
+ Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb b8 0f 1f 00 f3 0f 1e fa 41 89 ca 64 8b 04 25 18 00 00 00 85 c0 75 15 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 7e c3 0f 1f 44 00 00 41 54 48 83 ec 30 44 89
+ RSP: 002b:00007ffc248a42c8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
+ RAX: ffffffffffffffda RBX: 000055ef233289d0 RCX: 00007fca40e822ba
+ RDX: 000000000000001e RSI: 000055ef23328c30 RDI: 0000000000000003
+ RBP: 000055ef233289d0 R08: 00007ffc248a42d0 R09: 0000000000000010
+ R10: 0000000000000000 R11: 0000000000000246 R12: 000000000000001e
+ R13: 00000000000186a0 R14: 0000000000000000 R15: 00007fca41043000
+ </TASK>
+ irq event stamp: 1045778
+ hardirqs last enabled at (1045784): [<ffffffff864ec042>] __up_console_sem+0x52/0x60
+ hardirqs last disabled at (1045789): [<ffffffff864ec027>] __up_console_sem+0x37/0x60
+ softirqs last enabled at (1045426): [<ffffffff874d48c7>] __alloc_skb+0x207/0x260
+ softirqs last disabled at (1045434): [<ffffffff874fe8f8>] __dev_queue_xmit+0x78/0x14d0
+
+Then, because of the value in the packet's mark, dereference on 'q->handle'
+with NULL 'q' occurs:
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000038
+ [...]
+ RIP: 0010:fw_classify+0x1fe/0x250 [cls_fw]
+ [...]
+
+Skip "old-style" classification on shared blocks, so that the NULL
+dereference is fixed and WARN_ON() is not hit anymore in the short
+lifetime of invalid cls_fw "old-style" filters.
+
+[1] https://sashiko.dev/#/patchset/20260331050217.504278-1-xmei5%40asu.edu
+[2] https://elixir.bootlin.com/linux/v7.0-rc6/source/include/net/pkt_cls.h#L86
+
+Fixes: faeea8bbf6e9 ("net/sched: cls_fw: fix NULL pointer dereference on shared blocks")
+Fixes: ed76f5edccc9 ("net: sched: protect filter_chain list with filter_chain_lock mutex")
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: Davide Caratti <dcaratti@redhat.com>
+Link: https://patch.msgid.link/e39cbd3103a337f1e515d186fe697b4459d24757.1775661704.git.dcaratti@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_fw.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
+index 23cf4f71111740..1dfbae9dc050a6 100644
+--- a/net/sched/cls_fw.c
++++ b/net/sched/cls_fw.c
+@@ -72,9 +72,13 @@ static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp,
+ }
+ }
+ } else {
+- struct Qdisc *q = tcf_block_q(tp->chain->block);
++ struct Qdisc *q;
+
+ /* Old method: classify the packet using its skb mark. */
++ if (tcf_block_shared(tp->chain->block))
++ return -1;
++
++ q = tcf_block_q(tp->chain->block);
+ if (id && (TC_H_MAJ(id) == 0 ||
+ !(TC_H_MAJ(id ^ q->handle)))) {
+ res->classid = id;
+--
+2.53.0
+
--- /dev/null
+From 602911ed40bd0d82a6aca27ef3576b28bc5fe2a2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Apr 2026 11:29:56 -0400
+Subject: net/sched: sch_sfb: Replace direct dequeue call with peek and
+ qdisc_dequeue_peeked
+
+From: Victor Nogueria <victor@mojatatu.com>
+
+[ Upstream commit 1b9bc71153b01dbde8045b9edede4240f4f5520e ]
+
+When sfb has children (eg qfq qdisc) whose peek() callback is
+qdisc_peek_dequeued(), we could get a kernel panic. When the parent of such
+qdiscs (eg illustrated in patch #3 as tbf) wants to retrieve an skb from
+its child (sfb in this case), it will do the following:
+ 1a. do a peek() - and when sensing there's an skb the child can offer, then
+ - the child in this case(sfb) calls its child's (qfq) peek.
+ qfq does the right thing and will return the gso_skb queue packet.
+ Note: if there wasnt a gso_skb entry then qfq will store it there.
+ 1b. invoke a dequeue() on the child (sfb). And herein lies the problem.
+ - sfb will call the child's dequeue() which will essentially just
+ try to grab something of qfq's queue.
+
+[ 127.594489][ T453] KASAN: null-ptr-deref in range [0x0000000000000048-0x000000000000004f]
+[ 127.594741][ T453] CPU: 2 UID: 0 PID: 453 Comm: ping Not tainted 7.1.0-rc1-00035-gac961974495b-dirty #793 PREEMPT(full)
+[ 127.595059][ T453] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+[ 127.595254][ T453] RIP: 0010:qfq_dequeue+0x35c/0x1650 [sch_qfq]
+[ 127.595461][ T453] Code: 00 fc ff df 80 3c 02 00 0f 85 17 0e 00 00 4c 8d 73 48 48 89 9d b8 02 00 00 48 b8 00 00 00 00 00 fc ff df 4c 89 f2 48 c1 ea 03 <80> 3c 02 00 0f 85 76 0c 00 00 48 b8 00 00 00 00 00 fc ff df 4c 8b
+[ 127.596081][ T453] RSP: 0018:ffff88810e5af440 EFLAGS: 00010216
+[ 127.596337][ T453] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: dffffc0000000000
+[ 127.596623][ T453] RDX: 0000000000000009 RSI: 0000001880000000 RDI: ffff888104fd82b0
+[ 127.596917][ T453] RBP: ffff888104fd8000 R08: ffff888104fd8280 R09: 1ffff110211893a3
+[ 127.597165][ T453] R10: 1ffff110211893a6 R11: 1ffff110211893a7 R12: 0000001880000000
+[ 127.597404][ T453] R13: ffff888104fd82b8 R14: 0000000000000048 R15: 0000000040000000
+[ 127.597644][ T453] FS: 00007fc380cbfc40(0000) GS:ffff88816f2a8000(0000) knlGS:0000000000000000
+[ 127.597956][ T453] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 127.598160][ T453] CR2: 00005610aa9890a8 CR3: 000000010369e000 CR4: 0000000000750ef0
+[ 127.598390][ T453] PKRU: 55555554
+[ 127.598509][ T453] Call Trace:
+[ 127.598629][ T453] <TASK>
+[ 127.598718][ T453] ? mark_held_locks+0x40/0x70
+[ 127.598890][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599053][ T453] sfb_dequeue+0x88/0x4d0
+[ 127.599174][ T453] ? ktime_get+0x137/0x230
+[ 127.599328][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599480][ T453] ? qdisc_peek_dequeued+0x7b/0x350 [sch_qfq]
+[ 127.599670][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599831][ T453] tbf_dequeue+0x6b1/0x1098 [sch_tbf]
+[ 127.599988][ T453] __qdisc_run+0x169/0x1900
+
+The right thing to do in #1b is to grab the skb off gso_skb queue.
+This patchset fixes that issue by changing #1b to use qdisc_dequeue_peeked()
+method instead.
+
+Fixes: e13e02a3c68d ("net_sched: SFB flow scheduler")
+Signed-off-by: Victor Nogueria <victor@mojatatu.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260430152957.194015-3-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_sfb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
+index 1b04e760e47d6c..ce6c7e34e3c470 100644
+--- a/net/sched/sch_sfb.c
++++ b/net/sched/sch_sfb.c
+@@ -439,7 +439,7 @@ static struct sk_buff *sfb_dequeue(struct Qdisc *sch)
+ struct Qdisc *child = q->qdisc;
+ struct sk_buff *skb;
+
+- skb = child->dequeue(q->qdisc);
++ skb = qdisc_dequeue_peeked(child);
+
+ if (skb) {
+ qdisc_bstats_update(sch, skb);
+--
+2.53.0
+
--- /dev/null
+From 6217f4dacef15c78d1d236e2b86d8a7c4887d3bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 2 May 2026 07:58:59 +0900
+Subject: phy: renesas: rcar-gen3-usb2: Fix the use of msleep during spinlock
+
+From: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+
+This fixes an issue caused by the use of msleep during spinlock.
+In the original commit, msleep was changed to mdelay, but this fix was not
+carried over during the backport to 5.10.y tree.
+
+This is a backporting error, so no fix is needed in the upstream.
+
+```
+[ 62.677594] BUG: scheduling while atomic: kworker/1:2/126/0x00000002
+[ 62.683957] Modules linked in:
+[ 62.687014] CPU: 1 PID: 126 Comm: kworker/1:2 Not tainted 5.10.253 #1
+[ 62.693447] Hardware name: HopeRun HiHope RZ/G2M with sub board (DT)
+[ 62.699812] Workqueue: events deferred_probe_work_func
+[ 62.704948] Call trace:
+[ 62.707397] dump_backtrace+0x0/0x1c0
+[ 62.711058] show_stack+0x18/0x40
+[ 62.714375] dump_stack+0xe8/0x124
+[ 62.717776] __schedule_bug+0x54/0x70
+[ 62.721436] __schedule+0x6b4/0x710
+[ 62.724920] schedule+0x70/0x104
+[ 62.728145] schedule_timeout+0x80/0xf0
+[ 62.728153] msleep+0x30/0x44
+[ 62.728165] rcar_gen3_phy_usb2_init+0x180/0x1e0
+[ 62.736946] phy_init+0x64/0x100
+[ 62.736955] usb_phy_roothub_init+0x48/0xa0
+[ 62.736962] usb_add_hcd+0x54/0x6c0
+[ 62.736974] ehci_platform_probe+0x1ec/0x4b0
+[ 62.744541] platform_drv_probe+0x54/0xac
+[ 62.744548] really_probe+0xec/0x4f0
+[ 62.744552] driver_probe_device+0x58/0xec
+[ 62.744556] __device_attach_driver+0xb8/0x120
+[ 62.744562] bus_for_each_drv+0x78/0xd0
+[ 62.744568] __device_attach+0xa8/0x1c0
+[ 62.744575] device_initial_probe+0x14/0x20
+[ 62.752315] bus_probe_device+0x9c/0xa4
+[ 62.752319] deferred_probe_work_func+0x88/0xc0
+[ 62.752327] process_one_work+0x1cc/0x370
+[ 62.759977] worker_thread+0x218/0x480
+[ 62.759984] kthread+0x154/0x160
+[ 62.759990] ret_from_fork+0x10/0x18
+[ 62.760115] ehci-platform ee080100.usb: EHCI Host Controller
+[ 62.839982] ehci-platform ee080100.usb: new USB bus registered, assigned bus number 3
+```
+
+Fixes: 0f86a559900f ("phy: renesas: rcar-gen3-usb2: Lock around hardware registers and driver data")
+Cc: stable@vger.kernel.org
+Cc: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Cc: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/phy/renesas/phy-rcar-gen3-usb2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+index 5166a115879ea1..90f2a0e5b2aa05 100644
+--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
++++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+@@ -386,7 +386,7 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
+ val = readl(usb2_base + USB2_ADPCTRL);
+ writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL);
+
+- msleep(20);
++ mdelay(20);
+
+ writel(0xffffffff, usb2_base + USB2_OBINTSTA);
+ writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
+--
+2.53.0
+
--- /dev/null
+alsa-usb-audio-fix-null-pointer-dereference-on-point.patch
+net-sched-cls_fw-fix-null-dereference-of-old-filters.patch
+phy-renesas-rcar-gen3-usb2-fix-the-use-of-msleep-dur.patch
+net-sched-sch_sfb-replace-direct-dequeue-call-with-p.patch
--- /dev/null
+From dd377066acf6a499d33d775bc6b01e388213a569 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 13:24:12 +0800
+Subject: dmaengine: idxd: Fix not releasing workqueue on .release()
+
+From: Vinicius Costa Gomes <vinicius.gomes@intel.com>
+
+[ Upstream commit 3d33de353b1ff9023d5ec73b9becf80ea87af695 ]
+
+The workqueue associated with an DSA/IAA device is not released when
+the object is freed.
+
+Fixes: 47c16ac27d4c ("dmaengine: idxd: fix idxd conf_dev 'struct device' lifetime")
+Reviewed-by: Dave Jiang <dave.jiang@intel.com>
+Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
+Link: https://patch.msgid.link/20260121-idxd-fix-flr-on-kernel-queues-v3-v3-7-7ed70658a9d1@intel.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+[ Remove destroy_workqueue(idxd->wq) from the function idxd_remove() to
+avoid the workqueue is released twice. ]
+Signed-off-by: Wenshan Lan <jetlan9@163.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/idxd/init.c | 1 -
+ drivers/dma/idxd/sysfs.c | 1 +
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c
+index f2d27c6ec1ce88..698387103da738 100644
+--- a/drivers/dma/idxd/init.c
++++ b/drivers/dma/idxd/init.c
+@@ -829,7 +829,6 @@ static void idxd_remove(struct pci_dev *pdev)
+ pci_iounmap(pdev, idxd->reg_base);
+ iommu_dev_disable_feature(&pdev->dev, IOMMU_DEV_FEAT_SVA);
+ pci_disable_device(pdev);
+- destroy_workqueue(idxd->wq);
+ perfmon_pmu_remove(idxd);
+ put_device(idxd_confdev(idxd));
+ }
+diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c
+index 489a9d8850764b..ee208dfdd0cb51 100644
+--- a/drivers/dma/idxd/sysfs.c
++++ b/drivers/dma/idxd/sysfs.c
+@@ -1271,6 +1271,7 @@ static void idxd_conf_device_release(struct device *dev)
+ {
+ struct idxd_device *idxd = confdev_to_idxd(dev);
+
++ destroy_workqueue(idxd->wq);
+ kfree(idxd->groups);
+ kfree(idxd->wqs);
+ kfree(idxd->engines);
+--
+2.53.0
+
--- /dev/null
+From 7dbfa79727370ef895b883a5e7be5772b163ef45 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Sep 2023 11:15:18 -0300
+Subject: drm: Remove plane hsub/vsub alignment requirement for core helpers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Carlos Eduardo Gallo Filho <gcarlos@disroot.org>
+
+[ Upstream commit f2f455981a34ce8ca88a41458c09494b387d344f ]
+
+The drm_format_info_plane_{height,width} functions was implemented using
+regular division for the plane size calculation, which cause issues [1][2]
+when used on contexts where the dimensions are misaligned with relation
+to the subsampling factors. So, replace the regular division by the
+DIV_ROUND_UP macro.
+
+This allows these functions to be used in more drivers, making further
+work to bring more core presence on them possible.
+
+[1] http://patchwork.freedesktop.org/patch/msgid/20170321181218.10042-3-ville.syrjala@linux.intel.com
+[2] https://patchwork.freedesktop.org/patch/msgid/20211026225105.2783797-2-imre.deak@intel.com
+
+Signed-off-by: Carlos Eduardo Gallo Filho <gcarlos@disroot.org>
+Reviewed-by: André Almeida <andrealmeid@igalia.com>
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230926141519.9315-2-gcarlos@disroot.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/drm/drm_fourcc.h | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
+index 22aa64d07c7905..78ef00b94a4635 100644
+--- a/include/drm/drm_fourcc.h
++++ b/include/drm/drm_fourcc.h
+@@ -22,6 +22,7 @@
+ #ifndef __DRM_FOURCC_H__
+ #define __DRM_FOURCC_H__
+
++#include <linux/math.h>
+ #include <linux/types.h>
+ #include <uapi/drm/drm_fourcc.h>
+
+@@ -276,7 +277,7 @@ int drm_format_info_plane_width(const struct drm_format_info *info, int width,
+ if (plane == 0)
+ return width;
+
+- return width / info->hsub;
++ return DIV_ROUND_UP(width, info->hsub);
+ }
+
+ /**
+@@ -298,7 +299,7 @@ int drm_format_info_plane_height(const struct drm_format_info *info, int height,
+ if (plane == 0)
+ return height;
+
+- return height / info->vsub;
++ return DIV_ROUND_UP(height, info->vsub);
+ }
+
+ const struct drm_format_info *__drm_format_info(u32 format);
+--
+2.53.0
+
--- /dev/null
+From f9ae7c1e69f317ef515bc4e59db6c94b118c06c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 15:38:11 +0800
+Subject: net: cpsw_new: Fix potential unregister of netdev that has not been
+ registered yet
+
+From: Kevin Hao <haokexin@gmail.com>
+
+[ Upstream commit 9d724b34fbe13b71865ad0906a4be97571f19cf5 ]
+
+If an error occurs during register_netdev() for the first MAC in
+cpsw_register_ports(), even though cpsw->slaves[0].ndev is set to NULL,
+cpsw->slaves[1].ndev would remain unchanged. This could later cause
+cpsw_unregister_ports() to attempt unregistering the second MAC.
+To address this, add a check for ndev->reg_state before calling
+unregister_netdev(). With this change, setting cpsw->slaves[i].ndev
+to NULL becomes unnecessary and can be removed accordingly.
+
+Fixes: ed3525eda4c4 ("net: ethernet: ti: introduce cpsw switchdev based driver part 1 - dual-emac")
+Signed-off-by: Kevin Hao <haokexin@gmail.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
+Link: https://patch.msgid.link/20260205-cpsw-error-path-v1-2-6e58bae6b299@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Wenshan Lan <jetlan9@163.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ti/cpsw_new.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
+index 9d52b949ae3f95..bef2c71b905972 100644
+--- a/drivers/net/ethernet/ti/cpsw_new.c
++++ b/drivers/net/ethernet/ti/cpsw_new.c
+@@ -1447,7 +1447,8 @@ static void cpsw_unregister_ports(struct cpsw_common *cpsw)
+ int i = 0;
+
+ for (i = 0; i < cpsw->data.slaves; i++) {
+- if (!cpsw->slaves[i].ndev)
++ if (!cpsw->slaves[i].ndev ||
++ cpsw->slaves[i].ndev->reg_state != NETREG_REGISTERED)
+ continue;
+
+ unregister_netdev(cpsw->slaves[i].ndev);
+@@ -1467,7 +1468,6 @@ static int cpsw_register_ports(struct cpsw_common *cpsw)
+ if (ret) {
+ dev_err(cpsw->dev,
+ "cpsw: err registering net device%d\n", i);
+- cpsw->slaves[i].ndev = NULL;
+ break;
+ }
+ }
+--
+2.53.0
+
--- /dev/null
+From 064f67d7f6cea701db841802e86e75a12951291b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 15:50:14 +0800
+Subject: net: mctp: ensure our nlmsg responses are initialised
+
+From: Jeremy Kerr <jk@codeconstruct.com.au>
+
+[ Upstream commit a6a9bc544b675d8b5180f2718ec985ad267b5cbf ]
+
+Syed Faraz Abrar (@farazsth98) from Zellic, and Pumpkin (@u1f383) from
+DEVCORE Research Team working with Trend Micro Zero Day Initiative
+report that a RTM_GETNEIGH will return uninitalised data in the pad
+bytes of the ndmsg data.
+
+Ensure we're initialising the netlink data to zero, in the link, addr
+and neigh response messages.
+
+Fixes: 831119f88781 ("mctp: Add neighbour netlink interface")
+Fixes: 06d2f4c583a7 ("mctp: Add netlink route management")
+Fixes: 583be982d934 ("mctp: Add device handling and netlink interface")
+Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260209-dev-mctp-nlmsg-v1-1-f1e30c346a43@codeconstruct.com.au
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Li hongliang <1468888505@139.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mctp/device.c | 1 +
+ net/mctp/neigh.c | 1 +
+ net/mctp/route.c | 1 +
+ 3 files changed, 3 insertions(+)
+
+diff --git a/net/mctp/device.c b/net/mctp/device.c
+index aec7ffad2666ab..a11d5aca201c27 100644
+--- a/net/mctp/device.c
++++ b/net/mctp/device.c
+@@ -55,6 +55,7 @@ static int mctp_fill_addrinfo(struct sk_buff *skb, struct netlink_callback *cb,
+ return -EMSGSIZE;
+
+ hdr = nlmsg_data(nlh);
++ memset(hdr, 0, sizeof(*hdr));
+ hdr->ifa_family = AF_MCTP;
+ hdr->ifa_prefixlen = 0;
+ hdr->ifa_flags = 0;
+diff --git a/net/mctp/neigh.c b/net/mctp/neigh.c
+index bc75a263719c77..18a6be38f17211 100644
+--- a/net/mctp/neigh.c
++++ b/net/mctp/neigh.c
+@@ -217,6 +217,7 @@ static int mctp_fill_neigh(struct sk_buff *skb, u32 portid, u32 seq, int event,
+ return -EMSGSIZE;
+
+ hdr = nlmsg_data(nlh);
++ memset(hdr, 0, sizeof(*hdr));
+ hdr->ndm_family = AF_MCTP;
+ hdr->ndm_ifindex = dev->ifindex;
+ hdr->ndm_state = 0; // TODO other state bits?
+diff --git a/net/mctp/route.c b/net/mctp/route.c
+index 48d32bfd386363..a93796eb0a092c 100644
+--- a/net/mctp/route.c
++++ b/net/mctp/route.c
+@@ -1031,6 +1031,7 @@ static int mctp_fill_rtinfo(struct sk_buff *skb, struct mctp_route *rt,
+ return -EMSGSIZE;
+
+ hdr = nlmsg_data(nlh);
++ memset(hdr, 0, sizeof(*hdr));
+ hdr->rtm_family = AF_MCTP;
+
+ /* we use the _len fields as a number of EIDs, rather than
+--
+2.53.0
+
--- /dev/null
+From f183caf9869e5a9abe3197437c92966494630e77 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Apr 2026 17:24:36 +0200
+Subject: net/sched: cls_fw: fix NULL dereference of "old" filters before
+ change()
+
+From: Davide Caratti <dcaratti@redhat.com>
+
+[ Upstream commit 65782b2db7321d5f97c16718c4c7f6c7205a56be ]
+
+Like pointed out by Sashiko [1], since commit ed76f5edccc9 ("net: sched:
+protect filter_chain list with filter_chain_lock mutex") TC filters are
+added to a shared block and published to datapath before their ->change()
+function is called. This is a problem for cls_fw: an invalid filter
+created with the "old" method can still classify some packets before it
+is destroyed by the validation logic added by Xiang.
+Therefore, insisting with repeated runs of the following script:
+
+ # ip link add dev crash0 type dummy
+ # ip link set dev crash0 up
+ # mausezahn crash0 -c 100000 -P 10 \
+ > -A 4.3.2.1 -B 1.2.3.4 -t udp "dp=1234" -q &
+ # sleep 1
+ # tc qdisc add dev crash0 egress_block 1 clsact
+ # tc filter add block 1 protocol ip prio 1 matchall \
+ > action skbedit mark 65536 continue
+ # tc filter add block 1 protocol ip prio 2 fw
+ # ip link del dev crash0
+
+can still make fw_classify() hit the WARN_ON() in [2]:
+
+ WARNING: ./include/net/pkt_cls.h:88 at fw_classify+0x244/0x250 [cls_fw], CPU#18: mausezahn/1399
+ Modules linked in: cls_fw(E) act_skbedit(E)
+ CPU: 18 UID: 0 PID: 1399 Comm: mausezahn Tainted: G E 7.0.0-rc6-virtme #17 PREEMPT(full)
+ Tainted: [E]=UNSIGNED_MODULE
+ Hardware name: Red Hat KVM, BIOS 1.16.3-2.el9 04/01/2014
+ RIP: 0010:fw_classify+0x244/0x250 [cls_fw]
+ Code: 5c 49 c7 45 00 00 00 00 00 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 5b b8 ff ff ff ff 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 90 <0f> 0b 90 eb a0 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90
+ RSP: 0018:ffffd1b7026bf8a8 EFLAGS: 00010202
+ RAX: ffff8c5ac9c60800 RBX: ffff8c5ac99322c0 RCX: 0000000000000004
+ RDX: 0000000000000001 RSI: ffff8c5b74d7a000 RDI: ffff8c5ac8284f40
+ RBP: ffffd1b7026bf8d0 R08: 0000000000000000 R09: ffffd1b7026bf9b0
+ R10: 00000000ffffffff R11: 0000000000000000 R12: 0000000000010000
+ R13: ffffd1b7026bf930 R14: ffff8c5ac8284f40 R15: 0000000000000000
+ FS: 00007fca40c37740(0000) GS:ffff8c5b74d7a000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 00007fca40e822a0 CR3: 0000000005ca0001 CR4: 0000000000172ef0
+ Call Trace:
+ <TASK>
+ tcf_classify+0x17d/0x5c0
+ tc_run+0x9d/0x150
+ __dev_queue_xmit+0x2ab/0x14d0
+ ip_finish_output2+0x340/0x8f0
+ ip_output+0xa4/0x250
+ raw_sendmsg+0x147d/0x14b0
+ __sys_sendto+0x1cc/0x1f0
+ __x64_sys_sendto+0x24/0x30
+ do_syscall_64+0x126/0xf80
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+ RIP: 0033:0x7fca40e822ba
+ Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb b8 0f 1f 00 f3 0f 1e fa 41 89 ca 64 8b 04 25 18 00 00 00 85 c0 75 15 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 7e c3 0f 1f 44 00 00 41 54 48 83 ec 30 44 89
+ RSP: 002b:00007ffc248a42c8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
+ RAX: ffffffffffffffda RBX: 000055ef233289d0 RCX: 00007fca40e822ba
+ RDX: 000000000000001e RSI: 000055ef23328c30 RDI: 0000000000000003
+ RBP: 000055ef233289d0 R08: 00007ffc248a42d0 R09: 0000000000000010
+ R10: 0000000000000000 R11: 0000000000000246 R12: 000000000000001e
+ R13: 00000000000186a0 R14: 0000000000000000 R15: 00007fca41043000
+ </TASK>
+ irq event stamp: 1045778
+ hardirqs last enabled at (1045784): [<ffffffff864ec042>] __up_console_sem+0x52/0x60
+ hardirqs last disabled at (1045789): [<ffffffff864ec027>] __up_console_sem+0x37/0x60
+ softirqs last enabled at (1045426): [<ffffffff874d48c7>] __alloc_skb+0x207/0x260
+ softirqs last disabled at (1045434): [<ffffffff874fe8f8>] __dev_queue_xmit+0x78/0x14d0
+
+Then, because of the value in the packet's mark, dereference on 'q->handle'
+with NULL 'q' occurs:
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000038
+ [...]
+ RIP: 0010:fw_classify+0x1fe/0x250 [cls_fw]
+ [...]
+
+Skip "old-style" classification on shared blocks, so that the NULL
+dereference is fixed and WARN_ON() is not hit anymore in the short
+lifetime of invalid cls_fw "old-style" filters.
+
+[1] https://sashiko.dev/#/patchset/20260331050217.504278-1-xmei5%40asu.edu
+[2] https://elixir.bootlin.com/linux/v7.0-rc6/source/include/net/pkt_cls.h#L86
+
+Fixes: faeea8bbf6e9 ("net/sched: cls_fw: fix NULL pointer dereference on shared blocks")
+Fixes: ed76f5edccc9 ("net: sched: protect filter_chain list with filter_chain_lock mutex")
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: Davide Caratti <dcaratti@redhat.com>
+Link: https://patch.msgid.link/e39cbd3103a337f1e515d186fe697b4459d24757.1775661704.git.dcaratti@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_fw.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
+index a4ffee135c8557..60249d7b333af3 100644
+--- a/net/sched/cls_fw.c
++++ b/net/sched/cls_fw.c
+@@ -72,9 +72,13 @@ static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp,
+ }
+ }
+ } else {
+- struct Qdisc *q = tcf_block_q(tp->chain->block);
++ struct Qdisc *q;
+
+ /* Old method: classify the packet using its skb mark. */
++ if (tcf_block_shared(tp->chain->block))
++ return -1;
++
++ q = tcf_block_q(tp->chain->block);
+ if (id && (TC_H_MAJ(id) == 0 ||
+ !(TC_H_MAJ(id ^ q->handle)))) {
+ res->classid = id;
+--
+2.53.0
+
--- /dev/null
+From 4fdf09884af2aa559968839a79ac8ab334110825 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Apr 2026 11:29:56 -0400
+Subject: net/sched: sch_sfb: Replace direct dequeue call with peek and
+ qdisc_dequeue_peeked
+
+From: Victor Nogueria <victor@mojatatu.com>
+
+[ Upstream commit 1b9bc71153b01dbde8045b9edede4240f4f5520e ]
+
+When sfb has children (eg qfq qdisc) whose peek() callback is
+qdisc_peek_dequeued(), we could get a kernel panic. When the parent of such
+qdiscs (eg illustrated in patch #3 as tbf) wants to retrieve an skb from
+its child (sfb in this case), it will do the following:
+ 1a. do a peek() - and when sensing there's an skb the child can offer, then
+ - the child in this case(sfb) calls its child's (qfq) peek.
+ qfq does the right thing and will return the gso_skb queue packet.
+ Note: if there wasnt a gso_skb entry then qfq will store it there.
+ 1b. invoke a dequeue() on the child (sfb). And herein lies the problem.
+ - sfb will call the child's dequeue() which will essentially just
+ try to grab something of qfq's queue.
+
+[ 127.594489][ T453] KASAN: null-ptr-deref in range [0x0000000000000048-0x000000000000004f]
+[ 127.594741][ T453] CPU: 2 UID: 0 PID: 453 Comm: ping Not tainted 7.1.0-rc1-00035-gac961974495b-dirty #793 PREEMPT(full)
+[ 127.595059][ T453] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+[ 127.595254][ T453] RIP: 0010:qfq_dequeue+0x35c/0x1650 [sch_qfq]
+[ 127.595461][ T453] Code: 00 fc ff df 80 3c 02 00 0f 85 17 0e 00 00 4c 8d 73 48 48 89 9d b8 02 00 00 48 b8 00 00 00 00 00 fc ff df 4c 89 f2 48 c1 ea 03 <80> 3c 02 00 0f 85 76 0c 00 00 48 b8 00 00 00 00 00 fc ff df 4c 8b
+[ 127.596081][ T453] RSP: 0018:ffff88810e5af440 EFLAGS: 00010216
+[ 127.596337][ T453] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: dffffc0000000000
+[ 127.596623][ T453] RDX: 0000000000000009 RSI: 0000001880000000 RDI: ffff888104fd82b0
+[ 127.596917][ T453] RBP: ffff888104fd8000 R08: ffff888104fd8280 R09: 1ffff110211893a3
+[ 127.597165][ T453] R10: 1ffff110211893a6 R11: 1ffff110211893a7 R12: 0000001880000000
+[ 127.597404][ T453] R13: ffff888104fd82b8 R14: 0000000000000048 R15: 0000000040000000
+[ 127.597644][ T453] FS: 00007fc380cbfc40(0000) GS:ffff88816f2a8000(0000) knlGS:0000000000000000
+[ 127.597956][ T453] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 127.598160][ T453] CR2: 00005610aa9890a8 CR3: 000000010369e000 CR4: 0000000000750ef0
+[ 127.598390][ T453] PKRU: 55555554
+[ 127.598509][ T453] Call Trace:
+[ 127.598629][ T453] <TASK>
+[ 127.598718][ T453] ? mark_held_locks+0x40/0x70
+[ 127.598890][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599053][ T453] sfb_dequeue+0x88/0x4d0
+[ 127.599174][ T453] ? ktime_get+0x137/0x230
+[ 127.599328][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599480][ T453] ? qdisc_peek_dequeued+0x7b/0x350 [sch_qfq]
+[ 127.599670][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599831][ T453] tbf_dequeue+0x6b1/0x1098 [sch_tbf]
+[ 127.599988][ T453] __qdisc_run+0x169/0x1900
+
+The right thing to do in #1b is to grab the skb off gso_skb queue.
+This patchset fixes that issue by changing #1b to use qdisc_dequeue_peeked()
+method instead.
+
+Fixes: e13e02a3c68d ("net_sched: SFB flow scheduler")
+Signed-off-by: Victor Nogueria <victor@mojatatu.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260430152957.194015-3-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_sfb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
+index 497bc022fc0c10..45787f7d86477d 100644
+--- a/net/sched/sch_sfb.c
++++ b/net/sched/sch_sfb.c
+@@ -439,7 +439,7 @@ static struct sk_buff *sfb_dequeue(struct Qdisc *sch)
+ struct Qdisc *child = q->qdisc;
+ struct sk_buff *skb;
+
+- skb = child->dequeue(q->qdisc);
++ skb = qdisc_dequeue_peeked(child);
+
+ if (skb) {
+ qdisc_bstats_update(sch, skb);
+--
+2.53.0
+
--- /dev/null
+net-sched-cls_fw-fix-null-dereference-of-old-filters.patch
+net-mctp-ensure-our-nlmsg-responses-are-initialised.patch
+net-sched-sch_sfb-replace-direct-dequeue-call-with-p.patch
+drm-remove-plane-hsub-vsub-alignment-requirement-for.patch
+dmaengine-idxd-fix-not-releasing-workqueue-on-.relea.patch
+net-cpsw_new-fix-potential-unregister-of-netdev-that.patch
--- /dev/null
+From 496aa7947f806ec8bd59668275ffbf136e5f9269 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Sep 2023 11:15:18 -0300
+Subject: drm: Remove plane hsub/vsub alignment requirement for core helpers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Carlos Eduardo Gallo Filho <gcarlos@disroot.org>
+
+[ Upstream commit f2f455981a34ce8ca88a41458c09494b387d344f ]
+
+The drm_format_info_plane_{height,width} functions was implemented using
+regular division for the plane size calculation, which cause issues [1][2]
+when used on contexts where the dimensions are misaligned with relation
+to the subsampling factors. So, replace the regular division by the
+DIV_ROUND_UP macro.
+
+This allows these functions to be used in more drivers, making further
+work to bring more core presence on them possible.
+
+[1] http://patchwork.freedesktop.org/patch/msgid/20170321181218.10042-3-ville.syrjala@linux.intel.com
+[2] https://patchwork.freedesktop.org/patch/msgid/20211026225105.2783797-2-imre.deak@intel.com
+
+Signed-off-by: Carlos Eduardo Gallo Filho <gcarlos@disroot.org>
+Reviewed-by: André Almeida <andrealmeid@igalia.com>
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230926141519.9315-2-gcarlos@disroot.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/drm/drm_fourcc.h | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
+index 532ae78ca747e6..ccf91daa430702 100644
+--- a/include/drm/drm_fourcc.h
++++ b/include/drm/drm_fourcc.h
+@@ -22,6 +22,7 @@
+ #ifndef __DRM_FOURCC_H__
+ #define __DRM_FOURCC_H__
+
++#include <linux/math.h>
+ #include <linux/types.h>
+ #include <uapi/drm/drm_fourcc.h>
+
+@@ -279,7 +280,7 @@ int drm_format_info_plane_width(const struct drm_format_info *info, int width,
+ if (plane == 0)
+ return width;
+
+- return width / info->hsub;
++ return DIV_ROUND_UP(width, info->hsub);
+ }
+
+ /**
+@@ -301,7 +302,7 @@ int drm_format_info_plane_height(const struct drm_format_info *info, int height,
+ if (plane == 0)
+ return height;
+
+- return height / info->vsub;
++ return DIV_ROUND_UP(height, info->vsub);
+ }
+
+ const struct drm_format_info *__drm_format_info(u32 format);
+--
+2.53.0
+
--- /dev/null
+From 051d4a307d558c6da4bb63af2abe7fa45d0ac563 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 15:37:56 +0800
+Subject: net: cpsw_new: Fix potential unregister of netdev that has not been
+ registered yet
+
+From: Kevin Hao <haokexin@gmail.com>
+
+[ Upstream commit 9d724b34fbe13b71865ad0906a4be97571f19cf5 ]
+
+If an error occurs during register_netdev() for the first MAC in
+cpsw_register_ports(), even though cpsw->slaves[0].ndev is set to NULL,
+cpsw->slaves[1].ndev would remain unchanged. This could later cause
+cpsw_unregister_ports() to attempt unregistering the second MAC.
+To address this, add a check for ndev->reg_state before calling
+unregister_netdev(). With this change, setting cpsw->slaves[i].ndev
+to NULL becomes unnecessary and can be removed accordingly.
+
+Fixes: ed3525eda4c4 ("net: ethernet: ti: introduce cpsw switchdev based driver part 1 - dual-emac")
+Signed-off-by: Kevin Hao <haokexin@gmail.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
+Link: https://patch.msgid.link/20260205-cpsw-error-path-v1-2-6e58bae6b299@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Wenshan Lan <jetlan9@163.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ti/cpsw_new.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
+index c99dde9dbe7750..17c267f6d79aa9 100644
+--- a/drivers/net/ethernet/ti/cpsw_new.c
++++ b/drivers/net/ethernet/ti/cpsw_new.c
+@@ -1437,7 +1437,8 @@ static void cpsw_unregister_ports(struct cpsw_common *cpsw)
+ int i = 0;
+
+ for (i = 0; i < cpsw->data.slaves; i++) {
+- if (!cpsw->slaves[i].ndev)
++ if (!cpsw->slaves[i].ndev ||
++ cpsw->slaves[i].ndev->reg_state != NETREG_REGISTERED)
+ continue;
+
+ unregister_netdev(cpsw->slaves[i].ndev);
+@@ -1457,7 +1458,6 @@ static int cpsw_register_ports(struct cpsw_common *cpsw)
+ if (ret) {
+ dev_err(cpsw->dev,
+ "cpsw: err registering net device%d\n", i);
+- cpsw->slaves[i].ndev = NULL;
+ break;
+ }
+ }
+--
+2.53.0
+
--- /dev/null
+From c4c0c7079ec5427e9e949372ba9bb6f98f8416bf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 15:50:05 +0800
+Subject: net: mctp: ensure our nlmsg responses are initialised
+
+From: Jeremy Kerr <jk@codeconstruct.com.au>
+
+[ Upstream commit a6a9bc544b675d8b5180f2718ec985ad267b5cbf ]
+
+Syed Faraz Abrar (@farazsth98) from Zellic, and Pumpkin (@u1f383) from
+DEVCORE Research Team working with Trend Micro Zero Day Initiative
+report that a RTM_GETNEIGH will return uninitalised data in the pad
+bytes of the ndmsg data.
+
+Ensure we're initialising the netlink data to zero, in the link, addr
+and neigh response messages.
+
+Fixes: 831119f88781 ("mctp: Add neighbour netlink interface")
+Fixes: 06d2f4c583a7 ("mctp: Add netlink route management")
+Fixes: 583be982d934 ("mctp: Add device handling and netlink interface")
+Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260209-dev-mctp-nlmsg-v1-1-f1e30c346a43@codeconstruct.com.au
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Li hongliang <1468888505@139.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mctp/device.c | 1 +
+ net/mctp/neigh.c | 1 +
+ net/mctp/route.c | 1 +
+ 3 files changed, 3 insertions(+)
+
+diff --git a/net/mctp/device.c b/net/mctp/device.c
+index 85cc5f31f1e7c0..fd368249246dff 100644
+--- a/net/mctp/device.c
++++ b/net/mctp/device.c
+@@ -71,6 +71,7 @@ static int mctp_fill_addrinfo(struct sk_buff *skb,
+ return -EMSGSIZE;
+
+ hdr = nlmsg_data(nlh);
++ memset(hdr, 0, sizeof(*hdr));
+ hdr->ifa_family = AF_MCTP;
+ hdr->ifa_prefixlen = 0;
+ hdr->ifa_flags = 0;
+diff --git a/net/mctp/neigh.c b/net/mctp/neigh.c
+index 590f642413e4ef..c0151a69d2b7c2 100644
+--- a/net/mctp/neigh.c
++++ b/net/mctp/neigh.c
+@@ -218,6 +218,7 @@ static int mctp_fill_neigh(struct sk_buff *skb, u32 portid, u32 seq, int event,
+ return -EMSGSIZE;
+
+ hdr = nlmsg_data(nlh);
++ memset(hdr, 0, sizeof(*hdr));
+ hdr->ndm_family = AF_MCTP;
+ hdr->ndm_ifindex = dev->ifindex;
+ hdr->ndm_state = 0; // TODO other state bits?
+diff --git a/net/mctp/route.c b/net/mctp/route.c
+index fdeaf80691e555..c9b0b75422432e 100644
+--- a/net/mctp/route.c
++++ b/net/mctp/route.c
+@@ -1331,6 +1331,7 @@ static int mctp_fill_rtinfo(struct sk_buff *skb, struct mctp_route *rt,
+ return -EMSGSIZE;
+
+ hdr = nlmsg_data(nlh);
++ memset(hdr, 0, sizeof(*hdr));
+ hdr->rtm_family = AF_MCTP;
+
+ /* we use the _len fields as a number of EIDs, rather than
+--
+2.53.0
+
--- /dev/null
+From 32307ae23d1035c2d7aca164930f2f7b987e666c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Apr 2026 17:24:36 +0200
+Subject: net/sched: cls_fw: fix NULL dereference of "old" filters before
+ change()
+
+From: Davide Caratti <dcaratti@redhat.com>
+
+[ Upstream commit 65782b2db7321d5f97c16718c4c7f6c7205a56be ]
+
+Like pointed out by Sashiko [1], since commit ed76f5edccc9 ("net: sched:
+protect filter_chain list with filter_chain_lock mutex") TC filters are
+added to a shared block and published to datapath before their ->change()
+function is called. This is a problem for cls_fw: an invalid filter
+created with the "old" method can still classify some packets before it
+is destroyed by the validation logic added by Xiang.
+Therefore, insisting with repeated runs of the following script:
+
+ # ip link add dev crash0 type dummy
+ # ip link set dev crash0 up
+ # mausezahn crash0 -c 100000 -P 10 \
+ > -A 4.3.2.1 -B 1.2.3.4 -t udp "dp=1234" -q &
+ # sleep 1
+ # tc qdisc add dev crash0 egress_block 1 clsact
+ # tc filter add block 1 protocol ip prio 1 matchall \
+ > action skbedit mark 65536 continue
+ # tc filter add block 1 protocol ip prio 2 fw
+ # ip link del dev crash0
+
+can still make fw_classify() hit the WARN_ON() in [2]:
+
+ WARNING: ./include/net/pkt_cls.h:88 at fw_classify+0x244/0x250 [cls_fw], CPU#18: mausezahn/1399
+ Modules linked in: cls_fw(E) act_skbedit(E)
+ CPU: 18 UID: 0 PID: 1399 Comm: mausezahn Tainted: G E 7.0.0-rc6-virtme #17 PREEMPT(full)
+ Tainted: [E]=UNSIGNED_MODULE
+ Hardware name: Red Hat KVM, BIOS 1.16.3-2.el9 04/01/2014
+ RIP: 0010:fw_classify+0x244/0x250 [cls_fw]
+ Code: 5c 49 c7 45 00 00 00 00 00 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 5b b8 ff ff ff ff 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 90 <0f> 0b 90 eb a0 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90
+ RSP: 0018:ffffd1b7026bf8a8 EFLAGS: 00010202
+ RAX: ffff8c5ac9c60800 RBX: ffff8c5ac99322c0 RCX: 0000000000000004
+ RDX: 0000000000000001 RSI: ffff8c5b74d7a000 RDI: ffff8c5ac8284f40
+ RBP: ffffd1b7026bf8d0 R08: 0000000000000000 R09: ffffd1b7026bf9b0
+ R10: 00000000ffffffff R11: 0000000000000000 R12: 0000000000010000
+ R13: ffffd1b7026bf930 R14: ffff8c5ac8284f40 R15: 0000000000000000
+ FS: 00007fca40c37740(0000) GS:ffff8c5b74d7a000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 00007fca40e822a0 CR3: 0000000005ca0001 CR4: 0000000000172ef0
+ Call Trace:
+ <TASK>
+ tcf_classify+0x17d/0x5c0
+ tc_run+0x9d/0x150
+ __dev_queue_xmit+0x2ab/0x14d0
+ ip_finish_output2+0x340/0x8f0
+ ip_output+0xa4/0x250
+ raw_sendmsg+0x147d/0x14b0
+ __sys_sendto+0x1cc/0x1f0
+ __x64_sys_sendto+0x24/0x30
+ do_syscall_64+0x126/0xf80
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+ RIP: 0033:0x7fca40e822ba
+ Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb b8 0f 1f 00 f3 0f 1e fa 41 89 ca 64 8b 04 25 18 00 00 00 85 c0 75 15 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 7e c3 0f 1f 44 00 00 41 54 48 83 ec 30 44 89
+ RSP: 002b:00007ffc248a42c8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
+ RAX: ffffffffffffffda RBX: 000055ef233289d0 RCX: 00007fca40e822ba
+ RDX: 000000000000001e RSI: 000055ef23328c30 RDI: 0000000000000003
+ RBP: 000055ef233289d0 R08: 00007ffc248a42d0 R09: 0000000000000010
+ R10: 0000000000000000 R11: 0000000000000246 R12: 000000000000001e
+ R13: 00000000000186a0 R14: 0000000000000000 R15: 00007fca41043000
+ </TASK>
+ irq event stamp: 1045778
+ hardirqs last enabled at (1045784): [<ffffffff864ec042>] __up_console_sem+0x52/0x60
+ hardirqs last disabled at (1045789): [<ffffffff864ec027>] __up_console_sem+0x37/0x60
+ softirqs last enabled at (1045426): [<ffffffff874d48c7>] __alloc_skb+0x207/0x260
+ softirqs last disabled at (1045434): [<ffffffff874fe8f8>] __dev_queue_xmit+0x78/0x14d0
+
+Then, because of the value in the packet's mark, dereference on 'q->handle'
+with NULL 'q' occurs:
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000038
+ [...]
+ RIP: 0010:fw_classify+0x1fe/0x250 [cls_fw]
+ [...]
+
+Skip "old-style" classification on shared blocks, so that the NULL
+dereference is fixed and WARN_ON() is not hit anymore in the short
+lifetime of invalid cls_fw "old-style" filters.
+
+[1] https://sashiko.dev/#/patchset/20260331050217.504278-1-xmei5%40asu.edu
+[2] https://elixir.bootlin.com/linux/v7.0-rc6/source/include/net/pkt_cls.h#L86
+
+Fixes: faeea8bbf6e9 ("net/sched: cls_fw: fix NULL pointer dereference on shared blocks")
+Fixes: ed76f5edccc9 ("net: sched: protect filter_chain list with filter_chain_lock mutex")
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: Davide Caratti <dcaratti@redhat.com>
+Link: https://patch.msgid.link/e39cbd3103a337f1e515d186fe697b4459d24757.1775661704.git.dcaratti@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_fw.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
+index 366bcc960e43e6..979662292dced6 100644
+--- a/net/sched/cls_fw.c
++++ b/net/sched/cls_fw.c
+@@ -72,9 +72,13 @@ static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp,
+ }
+ }
+ } else {
+- struct Qdisc *q = tcf_block_q(tp->chain->block);
++ struct Qdisc *q;
+
+ /* Old method: classify the packet using its skb mark. */
++ if (tcf_block_shared(tp->chain->block))
++ return -1;
++
++ q = tcf_block_q(tp->chain->block);
+ if (id && (TC_H_MAJ(id) == 0 ||
+ !(TC_H_MAJ(id ^ q->handle)))) {
+ res->classid = id;
+--
+2.53.0
+
--- /dev/null
+From 0a4acbedca9332c494ab8692a7ed701e8b7d6096 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Apr 2026 11:29:56 -0400
+Subject: net/sched: sch_sfb: Replace direct dequeue call with peek and
+ qdisc_dequeue_peeked
+
+From: Victor Nogueria <victor@mojatatu.com>
+
+[ Upstream commit 1b9bc71153b01dbde8045b9edede4240f4f5520e ]
+
+When sfb has children (eg qfq qdisc) whose peek() callback is
+qdisc_peek_dequeued(), we could get a kernel panic. When the parent of such
+qdiscs (eg illustrated in patch #3 as tbf) wants to retrieve an skb from
+its child (sfb in this case), it will do the following:
+ 1a. do a peek() - and when sensing there's an skb the child can offer, then
+ - the child in this case(sfb) calls its child's (qfq) peek.
+ qfq does the right thing and will return the gso_skb queue packet.
+ Note: if there wasnt a gso_skb entry then qfq will store it there.
+ 1b. invoke a dequeue() on the child (sfb). And herein lies the problem.
+ - sfb will call the child's dequeue() which will essentially just
+ try to grab something of qfq's queue.
+
+[ 127.594489][ T453] KASAN: null-ptr-deref in range [0x0000000000000048-0x000000000000004f]
+[ 127.594741][ T453] CPU: 2 UID: 0 PID: 453 Comm: ping Not tainted 7.1.0-rc1-00035-gac961974495b-dirty #793 PREEMPT(full)
+[ 127.595059][ T453] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+[ 127.595254][ T453] RIP: 0010:qfq_dequeue+0x35c/0x1650 [sch_qfq]
+[ 127.595461][ T453] Code: 00 fc ff df 80 3c 02 00 0f 85 17 0e 00 00 4c 8d 73 48 48 89 9d b8 02 00 00 48 b8 00 00 00 00 00 fc ff df 4c 89 f2 48 c1 ea 03 <80> 3c 02 00 0f 85 76 0c 00 00 48 b8 00 00 00 00 00 fc ff df 4c 8b
+[ 127.596081][ T453] RSP: 0018:ffff88810e5af440 EFLAGS: 00010216
+[ 127.596337][ T453] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: dffffc0000000000
+[ 127.596623][ T453] RDX: 0000000000000009 RSI: 0000001880000000 RDI: ffff888104fd82b0
+[ 127.596917][ T453] RBP: ffff888104fd8000 R08: ffff888104fd8280 R09: 1ffff110211893a3
+[ 127.597165][ T453] R10: 1ffff110211893a6 R11: 1ffff110211893a7 R12: 0000001880000000
+[ 127.597404][ T453] R13: ffff888104fd82b8 R14: 0000000000000048 R15: 0000000040000000
+[ 127.597644][ T453] FS: 00007fc380cbfc40(0000) GS:ffff88816f2a8000(0000) knlGS:0000000000000000
+[ 127.597956][ T453] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 127.598160][ T453] CR2: 00005610aa9890a8 CR3: 000000010369e000 CR4: 0000000000750ef0
+[ 127.598390][ T453] PKRU: 55555554
+[ 127.598509][ T453] Call Trace:
+[ 127.598629][ T453] <TASK>
+[ 127.598718][ T453] ? mark_held_locks+0x40/0x70
+[ 127.598890][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599053][ T453] sfb_dequeue+0x88/0x4d0
+[ 127.599174][ T453] ? ktime_get+0x137/0x230
+[ 127.599328][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599480][ T453] ? qdisc_peek_dequeued+0x7b/0x350 [sch_qfq]
+[ 127.599670][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599831][ T453] tbf_dequeue+0x6b1/0x1098 [sch_tbf]
+[ 127.599988][ T453] __qdisc_run+0x169/0x1900
+
+The right thing to do in #1b is to grab the skb off gso_skb queue.
+This patchset fixes that issue by changing #1b to use qdisc_dequeue_peeked()
+method instead.
+
+Fixes: e13e02a3c68d ("net_sched: SFB flow scheduler")
+Signed-off-by: Victor Nogueria <victor@mojatatu.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260430152957.194015-3-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_sfb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
+index ce67826fdf9b6d..58bf4c803f7fee 100644
+--- a/net/sched/sch_sfb.c
++++ b/net/sched/sch_sfb.c
+@@ -439,7 +439,7 @@ static struct sk_buff *sfb_dequeue(struct Qdisc *sch)
+ struct Qdisc *child = q->qdisc;
+ struct sk_buff *skb;
+
+- skb = child->dequeue(q->qdisc);
++ skb = qdisc_dequeue_peeked(child);
+
+ if (skb) {
+ qdisc_bstats_update(sch, skb);
+--
+2.53.0
+
--- /dev/null
+net-sched-cls_fw-fix-null-dereference-of-old-filters.patch
+net-mctp-ensure-our-nlmsg-responses-are-initialised.patch
+net-sched-sch_sfb-replace-direct-dequeue-call-with-p.patch
+drm-remove-plane-hsub-vsub-alignment-requirement-for.patch
+net-cpsw_new-fix-potential-unregister-of-netdev-that.patch
--- /dev/null
+From 17c66a6670c62932ac125ce694477bd575a37318 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:25:54 +0200
+Subject: arm64: debug: always unmask interrupts in el0_softstp()
+
+From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+
+[ Upstream commit ea0d55ae4b3207c33691a73da3443b1fd379f1d2 ]
+
+We intend that EL0 exception handlers unmask all DAIF exceptions
+before calling exit_to_user_mode().
+
+When completing single-step of a suspended breakpoint, we do not call
+local_daif_restore(DAIF_PROCCTX) before calling exit_to_user_mode(),
+leaving all DAIF exceptions masked.
+
+When pseudo-NMIs are not in use this is benign.
+
+When pseudo-NMIs are in use, this is unsound. At this point interrupts
+are masked by both DAIF.IF and PMR_EL1, and subsequent irq flag
+manipulation may not work correctly. For example, a subsequent
+local_irq_enable() within exit_to_user_mode_loop() will only unmask
+interrupts via PMR_EL1 (leaving those masked via DAIF.IF), and
+anything depending on interrupts being unmasked (e.g. delivery of
+signals) will not work correctly.
+
+This was detected by CONFIG_ARM64_DEBUG_PRIORITY_MASKING.
+
+Move the call to `try_step_suspended_breakpoints()` outside of the check
+so that interrupts can be unmasked even if we don't call the step handler.
+
+Fixes: 0ac7584c08ce ("arm64: debug: split single stepping exception entry")
+Cc: <stable@vger.kernel.org> # 6.17
+Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+[catalin.marinas@arm.com: added Mark's rewritten commit log and some whitespace]
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/kernel/entry-common.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
+index b98d6d1a1dfd63..ea3876d99c2ec5 100644
+--- a/arch/arm64/kernel/entry-common.c
++++ b/arch/arm64/kernel/entry-common.c
+@@ -796,6 +796,8 @@ static void noinstr el0_breakpt(struct pt_regs *regs, unsigned long esr)
+
+ static void noinstr el0_softstp(struct pt_regs *regs, unsigned long esr)
+ {
++ bool step_done;
++
+ if (!is_ttbr0_addr(regs->pc))
+ arm64_apply_bp_hardening();
+
+@@ -806,10 +808,10 @@ static void noinstr el0_softstp(struct pt_regs *regs, unsigned long esr)
+ * If we are stepping a suspended breakpoint there's nothing more to do:
+ * the single-step is complete.
+ */
+- if (!try_step_suspended_breakpoints(regs)) {
+- local_daif_restore(DAIF_PROCCTX);
++ step_done = try_step_suspended_breakpoints(regs);
++ local_daif_restore(DAIF_PROCCTX);
++ if (!step_done)
+ do_el0_softstep(esr, regs);
+- }
+ exit_to_user_mode(regs);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From e0ad41f855475ceff58d110677a66e1b9f2d7b7a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:25:43 +0200
+Subject: arm64: debug: call software breakpoint handlers statically
+
+From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+
+[ Upstream commit 6adfdc5e2ef9c71a76d8d127a2eb54f0fbe9be5e ]
+
+Software breakpoints pass an immediate value in ESR ("comment") that can
+be used to call a specialized handler (KGDB, KASAN...).
+We do so in two different ways :
+ - During early boot, `early_brk64` statically checks against known
+ immediates and calls the corresponding handler,
+ - During init, handlers are dynamically registered into a list. When
+ called, the generic software breakpoint handler will iterate over
+ the list to find the appropriate handler.
+
+The dynamic registration does not provide any benefit here as it is not
+exported and all its uses are within the arm64 tree. It also depends on an
+RCU list, whose safe access currently relies on the non-preemptible state
+of `do_debug_exception`.
+
+Replace the list iteration logic in `call_break_hooks` to call
+the breakpoint handlers statically if they are enabled, like in
+`early_brk64`.
+Expose the handlers in their respective headers to be reachable from
+`arch/arm64/kernel/debug-monitors.c` at link time.
+
+Unify the naming of the software breakpoint handlers to XXX_brk_handler(),
+making it clear they are related and to differentiate from the
+hardware breakpoints.
+
+Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Tested-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Reviewed-by: Will Deacon <will@kernel.org>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Link: https://lore.kernel.org/r/20250707114109.35672-4-ada.coupriediaz@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/kgdb.h | 3 +
+ arch/arm64/include/asm/kprobes.h | 8 +++
+ arch/arm64/include/asm/traps.h | 6 ++
+ arch/arm64/include/asm/uprobes.h | 2 +
+ arch/arm64/kernel/debug-monitors.c | 53 +++++++++++++----
+ arch/arm64/kernel/kgdb.c | 22 ++-----
+ arch/arm64/kernel/probes/kprobes.c | 31 ++--------
+ arch/arm64/kernel/probes/kprobes_trampoline.S | 2 +-
+ arch/arm64/kernel/probes/uprobes.c | 9 +--
+ arch/arm64/kernel/traps.c | 59 ++++---------------
+ 10 files changed, 82 insertions(+), 113 deletions(-)
+
+diff --git a/arch/arm64/include/asm/kgdb.h b/arch/arm64/include/asm/kgdb.h
+index 21fc85e9d2bed8..82a76b2102fb61 100644
+--- a/arch/arm64/include/asm/kgdb.h
++++ b/arch/arm64/include/asm/kgdb.h
+@@ -24,6 +24,9 @@ static inline void arch_kgdb_breakpoint(void)
+ extern void kgdb_handle_bus_error(void);
+ extern int kgdb_fault_expected;
+
++int kgdb_brk_handler(struct pt_regs *regs, unsigned long esr);
++int kgdb_compiled_brk_handler(struct pt_regs *regs, unsigned long esr);
++
+ #endif /* !__ASSEMBLY__ */
+
+ /*
+diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
+index be7a3680dadff7..f2782560647bef 100644
+--- a/arch/arm64/include/asm/kprobes.h
++++ b/arch/arm64/include/asm/kprobes.h
+@@ -41,4 +41,12 @@ void __kretprobe_trampoline(void);
+ void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
+
+ #endif /* CONFIG_KPROBES */
++
++int __kprobes kprobe_brk_handler(struct pt_regs *regs,
++ unsigned long esr);
++int __kprobes kprobe_ss_brk_handler(struct pt_regs *regs,
++ unsigned long esr);
++int __kprobes kretprobe_brk_handler(struct pt_regs *regs,
++ unsigned long esr);
++
+ #endif /* _ARM_KPROBES_H */
+diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
+index 82cf1f879c61df..e3e8944a71c3e6 100644
+--- a/arch/arm64/include/asm/traps.h
++++ b/arch/arm64/include/asm/traps.h
+@@ -29,6 +29,12 @@ void arm64_force_sig_fault_pkey(unsigned long far, const char *str, int pkey);
+ void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str);
+ void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far, const char *str);
+
++int bug_brk_handler(struct pt_regs *regs, unsigned long esr);
++int cfi_brk_handler(struct pt_regs *regs, unsigned long esr);
++int reserved_fault_brk_handler(struct pt_regs *regs, unsigned long esr);
++int kasan_brk_handler(struct pt_regs *regs, unsigned long esr);
++int ubsan_brk_handler(struct pt_regs *regs, unsigned long esr);
++
+ int early_brk64(unsigned long addr, unsigned long esr, struct pt_regs *regs);
+
+ /*
+diff --git a/arch/arm64/include/asm/uprobes.h b/arch/arm64/include/asm/uprobes.h
+index 014b02897f8e22..3659a79a9f325f 100644
+--- a/arch/arm64/include/asm/uprobes.h
++++ b/arch/arm64/include/asm/uprobes.h
+@@ -28,4 +28,6 @@ struct arch_uprobe {
+ bool simulate;
+ };
+
++int uprobe_brk_handler(struct pt_regs *regs, unsigned long esr);
++
+ #endif
+diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
+index 8275b7f5754626..5e892448030005 100644
+--- a/arch/arm64/kernel/debug-monitors.c
++++ b/arch/arm64/kernel/debug-monitors.c
+@@ -21,8 +21,11 @@
+ #include <asm/cputype.h>
+ #include <asm/daifflags.h>
+ #include <asm/debug-monitors.h>
++#include <asm/kgdb.h>
++#include <asm/kprobes.h>
+ #include <asm/system_misc.h>
+ #include <asm/traps.h>
++#include <asm/uprobes.h>
+
+ /* Determine debug architecture. */
+ u8 debug_monitors_arch(void)
+@@ -299,22 +302,48 @@ void unregister_kernel_break_hook(struct break_hook *hook)
+
+ static int call_break_hook(struct pt_regs *regs, unsigned long esr)
+ {
+- struct break_hook *hook;
+- struct list_head *list;
+- int (*fn)(struct pt_regs *regs, unsigned long esr) = NULL;
++ if (user_mode(regs)) {
++ if (IS_ENABLED(CONFIG_UPROBES) &&
++ esr_brk_comment(esr) == UPROBES_BRK_IMM)
++ return uprobe_brk_handler(regs, esr);
++ return DBG_HOOK_ERROR;
++ }
+
+- list = user_mode(regs) ? &user_break_hook : &kernel_break_hook;
++ if (esr_brk_comment(esr) == BUG_BRK_IMM)
++ return bug_brk_handler(regs, esr);
+
+- /*
+- * Since brk exception disables interrupt, this function is
+- * entirely not preemptible, and we can use rcu list safely here.
+- */
+- list_for_each_entry_rcu(hook, list, node) {
+- if ((esr_brk_comment(esr) & ~hook->mask) == hook->imm)
+- fn = hook->fn;
++ if (IS_ENABLED(CONFIG_CFI_CLANG) && esr_is_cfi_brk(esr))
++ return cfi_brk_handler(regs, esr);
++
++ if (esr_brk_comment(esr) == FAULT_BRK_IMM)
++ return reserved_fault_brk_handler(regs, esr);
++
++ if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) &&
++ (esr_brk_comment(esr) & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
++ return kasan_brk_handler(regs, esr);
++
++ if (IS_ENABLED(CONFIG_UBSAN_TRAP) && esr_is_ubsan_brk(esr))
++ return ubsan_brk_handler(regs, esr);
++
++ if (IS_ENABLED(CONFIG_KGDB)) {
++ if (esr_brk_comment(esr) == KGDB_DYN_DBG_BRK_IMM)
++ return kgdb_brk_handler(regs, esr);
++ if (esr_brk_comment(esr) == KGDB_COMPILED_DBG_BRK_IMM)
++ return kgdb_compiled_brk_handler(regs, esr);
+ }
+
+- return fn ? fn(regs, esr) : DBG_HOOK_ERROR;
++ if (IS_ENABLED(CONFIG_KPROBES)) {
++ if (esr_brk_comment(esr) == KPROBES_BRK_IMM)
++ return kprobe_brk_handler(regs, esr);
++ if (esr_brk_comment(esr) == KPROBES_BRK_SS_IMM)
++ return kprobe_ss_brk_handler(regs, esr);
++ }
++
++ if (IS_ENABLED(CONFIG_KRETPROBES) &&
++ esr_brk_comment(esr) == KRETPROBES_BRK_IMM)
++ return kretprobe_brk_handler(regs, esr);
++
++ return DBG_HOOK_ERROR;
+ }
+ NOKPROBE_SYMBOL(call_break_hook);
+
+diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
+index 4e1f983df3d1c2..e3c9e6e11a318c 100644
+--- a/arch/arm64/kernel/kgdb.c
++++ b/arch/arm64/kernel/kgdb.c
+@@ -234,21 +234,21 @@ int kgdb_arch_handle_exception(int exception_vector, int signo,
+ return err;
+ }
+
+-static int kgdb_brk_fn(struct pt_regs *regs, unsigned long esr)
++int kgdb_brk_handler(struct pt_regs *regs, unsigned long esr)
+ {
+ kgdb_handle_exception(1, SIGTRAP, 0, regs);
+ return DBG_HOOK_HANDLED;
+ }
+-NOKPROBE_SYMBOL(kgdb_brk_fn)
++NOKPROBE_SYMBOL(kgdb_brk_handler)
+
+-static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned long esr)
++int kgdb_compiled_brk_handler(struct pt_regs *regs, unsigned long esr)
+ {
+ compiled_break = 1;
+ kgdb_handle_exception(1, SIGTRAP, 0, regs);
+
+ return DBG_HOOK_HANDLED;
+ }
+-NOKPROBE_SYMBOL(kgdb_compiled_brk_fn);
++NOKPROBE_SYMBOL(kgdb_compiled_brk_handler);
+
+ static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned long esr)
+ {
+@@ -260,16 +260,6 @@ static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned long esr)
+ }
+ NOKPROBE_SYMBOL(kgdb_step_brk_fn);
+
+-static struct break_hook kgdb_brkpt_hook = {
+- .fn = kgdb_brk_fn,
+- .imm = KGDB_DYN_DBG_BRK_IMM,
+-};
+-
+-static struct break_hook kgdb_compiled_brkpt_hook = {
+- .fn = kgdb_compiled_brk_fn,
+- .imm = KGDB_COMPILED_DBG_BRK_IMM,
+-};
+-
+ static struct step_hook kgdb_step_hook = {
+ .fn = kgdb_step_brk_fn
+ };
+@@ -316,8 +306,6 @@ int kgdb_arch_init(void)
+ if (ret != 0)
+ return ret;
+
+- register_kernel_break_hook(&kgdb_brkpt_hook);
+- register_kernel_break_hook(&kgdb_compiled_brkpt_hook);
+ register_kernel_step_hook(&kgdb_step_hook);
+ return 0;
+ }
+@@ -329,8 +317,6 @@ int kgdb_arch_init(void)
+ */
+ void kgdb_arch_exit(void)
+ {
+- unregister_kernel_break_hook(&kgdb_brkpt_hook);
+- unregister_kernel_break_hook(&kgdb_compiled_brkpt_hook);
+ unregister_kernel_step_hook(&kgdb_step_hook);
+ unregister_die_notifier(&kgdb_notifier);
+ }
+diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
+index b0e0f0aed748a8..8661cd4064732a 100644
+--- a/arch/arm64/kernel/probes/kprobes.c
++++ b/arch/arm64/kernel/probes/kprobes.c
+@@ -306,8 +306,8 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
+ return 0;
+ }
+
+-static int __kprobes
+-kprobe_breakpoint_handler(struct pt_regs *regs, unsigned long esr)
++int __kprobes
++kprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
+ {
+ struct kprobe *p, *cur_kprobe;
+ struct kprobe_ctlblk *kcb;
+@@ -350,13 +350,8 @@ kprobe_breakpoint_handler(struct pt_regs *regs, unsigned long esr)
+ return DBG_HOOK_HANDLED;
+ }
+
+-static struct break_hook kprobes_break_hook = {
+- .imm = KPROBES_BRK_IMM,
+- .fn = kprobe_breakpoint_handler,
+-};
+-
+-static int __kprobes
+-kprobe_breakpoint_ss_handler(struct pt_regs *regs, unsigned long esr)
++int __kprobes
++kprobe_ss_brk_handler(struct pt_regs *regs, unsigned long esr)
+ {
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ unsigned long addr = instruction_pointer(regs);
+@@ -374,13 +369,8 @@ kprobe_breakpoint_ss_handler(struct pt_regs *regs, unsigned long esr)
+ return DBG_HOOK_ERROR;
+ }
+
+-static struct break_hook kprobes_break_ss_hook = {
+- .imm = KPROBES_BRK_SS_IMM,
+- .fn = kprobe_breakpoint_ss_handler,
+-};
+-
+-static int __kprobes
+-kretprobe_breakpoint_handler(struct pt_regs *regs, unsigned long esr)
++int __kprobes
++kretprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
+ {
+ if (regs->pc != (unsigned long)__kretprobe_trampoline)
+ return DBG_HOOK_ERROR;
+@@ -389,11 +379,6 @@ kretprobe_breakpoint_handler(struct pt_regs *regs, unsigned long esr)
+ return DBG_HOOK_HANDLED;
+ }
+
+-static struct break_hook kretprobes_break_hook = {
+- .imm = KRETPROBES_BRK_IMM,
+- .fn = kretprobe_breakpoint_handler,
+-};
+-
+ /*
+ * Provide a blacklist of symbols identifying ranges which cannot be kprobed.
+ * This blacklist is exposed to userspace via debugfs (kprobes/blacklist).
+@@ -436,9 +421,5 @@ int __kprobes arch_trampoline_kprobe(struct kprobe *p)
+
+ int __init arch_init_kprobes(void)
+ {
+- register_kernel_break_hook(&kprobes_break_hook);
+- register_kernel_break_hook(&kprobes_break_ss_hook);
+- register_kernel_break_hook(&kretprobes_break_hook);
+-
+ return 0;
+ }
+diff --git a/arch/arm64/kernel/probes/kprobes_trampoline.S b/arch/arm64/kernel/probes/kprobes_trampoline.S
+index a362f3dbb3d117..b60739d3983f60 100644
+--- a/arch/arm64/kernel/probes/kprobes_trampoline.S
++++ b/arch/arm64/kernel/probes/kprobes_trampoline.S
+@@ -12,7 +12,7 @@
+ SYM_CODE_START(__kretprobe_trampoline)
+ /*
+ * Trigger a breakpoint exception. The PC will be adjusted by
+- * kretprobe_breakpoint_handler(), and no subsequent instructions will
++ * kretprobe_brk_handler(), and no subsequent instructions will
+ * be executed from the trampoline.
+ */
+ brk #KRETPROBES_BRK_IMM
+diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c
+index a2f137a595fc1c..fc1bd19c827e6f 100644
+--- a/arch/arm64/kernel/probes/uprobes.c
++++ b/arch/arm64/kernel/probes/uprobes.c
+@@ -165,7 +165,7 @@ int arch_uprobe_exception_notify(struct notifier_block *self,
+ return NOTIFY_DONE;
+ }
+
+-static int uprobe_breakpoint_handler(struct pt_regs *regs,
++int uprobe_brk_handler(struct pt_regs *regs,
+ unsigned long esr)
+ {
+ if (uprobe_pre_sstep_notifier(regs))
+@@ -186,12 +186,6 @@ static int uprobe_single_step_handler(struct pt_regs *regs,
+ return DBG_HOOK_ERROR;
+ }
+
+-/* uprobe breakpoint handler hook */
+-static struct break_hook uprobes_break_hook = {
+- .imm = UPROBES_BRK_IMM,
+- .fn = uprobe_breakpoint_handler,
+-};
+-
+ /* uprobe single step handler hook */
+ static struct step_hook uprobes_step_hook = {
+ .fn = uprobe_single_step_handler,
+@@ -199,7 +193,6 @@ static struct step_hook uprobes_step_hook = {
+
+ static int __init arch_init_uprobes(void)
+ {
+- register_user_break_hook(&uprobes_break_hook);
+ register_user_step_hook(&uprobes_step_hook);
+
+ return 0;
+diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
+index c38ebf715be764..013159bc0882ee 100644
+--- a/arch/arm64/kernel/traps.c
++++ b/arch/arm64/kernel/traps.c
+@@ -978,7 +978,7 @@ void do_serror(struct pt_regs *regs, unsigned long esr)
+ int is_valid_bugaddr(unsigned long addr)
+ {
+ /*
+- * bug_handler() only called for BRK #BUG_BRK_IMM.
++ * bug_brk_handler() only called for BRK #BUG_BRK_IMM.
+ * So the answer is trivial -- any spurious instances with no
+ * bug table entry will be rejected by report_bug() and passed
+ * back to the debug-monitors code and handled as a fatal
+@@ -988,7 +988,7 @@ int is_valid_bugaddr(unsigned long addr)
+ }
+ #endif
+
+-static int bug_handler(struct pt_regs *regs, unsigned long esr)
++int bug_brk_handler(struct pt_regs *regs, unsigned long esr)
+ {
+ switch (report_bug(regs->pc, regs)) {
+ case BUG_TRAP_TYPE_BUG:
+@@ -1008,13 +1008,8 @@ static int bug_handler(struct pt_regs *regs, unsigned long esr)
+ return DBG_HOOK_HANDLED;
+ }
+
+-static struct break_hook bug_break_hook = {
+- .fn = bug_handler,
+- .imm = BUG_BRK_IMM,
+-};
+-
+ #ifdef CONFIG_CFI_CLANG
+-static int cfi_handler(struct pt_regs *regs, unsigned long esr)
++int cfi_brk_handler(struct pt_regs *regs, unsigned long esr)
+ {
+ unsigned long target;
+ u32 type;
+@@ -1037,15 +1032,9 @@ static int cfi_handler(struct pt_regs *regs, unsigned long esr)
+ arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
+ return DBG_HOOK_HANDLED;
+ }
+-
+-static struct break_hook cfi_break_hook = {
+- .fn = cfi_handler,
+- .imm = CFI_BRK_IMM_BASE,
+- .mask = CFI_BRK_IMM_MASK,
+-};
+ #endif /* CONFIG_CFI_CLANG */
+
+-static int reserved_fault_handler(struct pt_regs *regs, unsigned long esr)
++int reserved_fault_brk_handler(struct pt_regs *regs, unsigned long esr)
+ {
+ pr_err("%s generated an invalid instruction at %pS!\n",
+ "Kernel text patching",
+@@ -1055,11 +1044,6 @@ static int reserved_fault_handler(struct pt_regs *regs, unsigned long esr)
+ return DBG_HOOK_ERROR;
+ }
+
+-static struct break_hook fault_break_hook = {
+- .fn = reserved_fault_handler,
+- .imm = FAULT_BRK_IMM,
+-};
+-
+ #ifdef CONFIG_KASAN_SW_TAGS
+
+ #define KASAN_ESR_RECOVER 0x20
+@@ -1067,7 +1051,7 @@ static struct break_hook fault_break_hook = {
+ #define KASAN_ESR_SIZE_MASK 0x0f
+ #define KASAN_ESR_SIZE(esr) (1 << ((esr) & KASAN_ESR_SIZE_MASK))
+
+-static int kasan_handler(struct pt_regs *regs, unsigned long esr)
++int kasan_brk_handler(struct pt_regs *regs, unsigned long esr)
+ {
+ bool recover = esr & KASAN_ESR_RECOVER;
+ bool write = esr & KASAN_ESR_WRITE;
+@@ -1098,26 +1082,14 @@ static int kasan_handler(struct pt_regs *regs, unsigned long esr)
+ arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
+ return DBG_HOOK_HANDLED;
+ }
+-
+-static struct break_hook kasan_break_hook = {
+- .fn = kasan_handler,
+- .imm = KASAN_BRK_IMM,
+- .mask = KASAN_BRK_MASK,
+-};
+ #endif
+
+ #ifdef CONFIG_UBSAN_TRAP
+-static int ubsan_handler(struct pt_regs *regs, unsigned long esr)
++int ubsan_brk_handler(struct pt_regs *regs, unsigned long esr)
+ {
+ die(report_ubsan_failure(regs, esr & UBSAN_BRK_MASK), regs, esr);
+ return DBG_HOOK_HANDLED;
+ }
+-
+-static struct break_hook ubsan_break_hook = {
+- .fn = ubsan_handler,
+- .imm = UBSAN_BRK_IMM,
+- .mask = UBSAN_BRK_MASK,
+-};
+ #endif
+
+ /*
+@@ -1129,31 +1101,20 @@ int __init early_brk64(unsigned long addr, unsigned long esr,
+ {
+ #ifdef CONFIG_CFI_CLANG
+ if (esr_is_cfi_brk(esr))
+- return cfi_handler(regs, esr) != DBG_HOOK_HANDLED;
++ return cfi_brk_handler(regs, esr) != DBG_HOOK_HANDLED;
+ #endif
+ #ifdef CONFIG_KASAN_SW_TAGS
+ if ((esr_brk_comment(esr) & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
+- return kasan_handler(regs, esr) != DBG_HOOK_HANDLED;
++ return kasan_brk_handler(regs, esr) != DBG_HOOK_HANDLED;
+ #endif
+ #ifdef CONFIG_UBSAN_TRAP
+ if (esr_is_ubsan_brk(esr))
+- return ubsan_handler(regs, esr) != DBG_HOOK_HANDLED;
++ return ubsan_brk_handler(regs, esr) != DBG_HOOK_HANDLED;
+ #endif
+- return bug_handler(regs, esr) != DBG_HOOK_HANDLED;
++ return bug_brk_handler(regs, esr) != DBG_HOOK_HANDLED;
+ }
+
+ void __init trap_init(void)
+ {
+- register_kernel_break_hook(&bug_break_hook);
+-#ifdef CONFIG_CFI_CLANG
+- register_kernel_break_hook(&cfi_break_hook);
+-#endif
+- register_kernel_break_hook(&fault_break_hook);
+-#ifdef CONFIG_KASAN_SW_TAGS
+- register_kernel_break_hook(&kasan_break_hook);
+-#endif
+-#ifdef CONFIG_UBSAN_TRAP
+- register_kernel_break_hook(&ubsan_break_hook);
+-#endif
+ debug_traps_init();
+ }
+--
+2.53.0
+
--- /dev/null
+From 322065ec410b7e9895c61592efc665ecfed4ba94 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:25:44 +0200
+Subject: arm64: debug: call step handlers statically
+
+From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+
+[ Upstream commit 403b48aad5b3e857b8c2576ce6a421f3d23dd6a6 ]
+
+Software stepping checks for the correct handler by iterating over a list
+of dynamically registered handlers and calling all of them until one
+handles the exception.
+
+This is the only generic way to handle software stepping handlers in arm64
+as the exception does not provide an immediate that could be checked,
+contrary to software breakpoints.
+
+However, the registration mechanism is not exported and has only
+two current users : the KGDB stepping handler, and the uprobe single step
+handler.
+Given that one comes from user mode and the other from kernel mode, call
+the appropriate one by checking the source EL of the exception.
+Add a stand-in that returns DBG_HOOK_ERROR when the configuration
+options are not enabled.
+
+Remove `arch_init_uprobes()` as it is not useful anymore and is
+specific to arm64.
+
+Unify the naming of the handler to XXX_single_step_handler(), making it
+clear they are related.
+
+Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Tested-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Reviewed-by: Will Deacon <will@kernel.org>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Link: https://lore.kernel.org/r/20250707114109.35672-5-ada.coupriediaz@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/kgdb.h | 9 +++++++++
+ arch/arm64/include/asm/uprobes.h | 9 +++++++++
+ arch/arm64/kernel/debug-monitors.c | 25 ++++++-------------------
+ arch/arm64/kernel/kgdb.c | 17 +++--------------
+ arch/arm64/kernel/probes/uprobes.c | 15 +--------------
+ 5 files changed, 28 insertions(+), 47 deletions(-)
+
+diff --git a/arch/arm64/include/asm/kgdb.h b/arch/arm64/include/asm/kgdb.h
+index 82a76b2102fb61..3184f5d1e3ae49 100644
+--- a/arch/arm64/include/asm/kgdb.h
++++ b/arch/arm64/include/asm/kgdb.h
+@@ -26,6 +26,15 @@ extern int kgdb_fault_expected;
+
+ int kgdb_brk_handler(struct pt_regs *regs, unsigned long esr);
+ int kgdb_compiled_brk_handler(struct pt_regs *regs, unsigned long esr);
++#ifdef CONFIG_KGDB
++int kgdb_single_step_handler(struct pt_regs *regs, unsigned long esr);
++#else
++static inline int kgdb_single_step_handler(struct pt_regs *regs,
++ unsigned long esr)
++{
++ return DBG_HOOK_ERROR;
++}
++#endif
+
+ #endif /* !__ASSEMBLY__ */
+
+diff --git a/arch/arm64/include/asm/uprobes.h b/arch/arm64/include/asm/uprobes.h
+index 3659a79a9f325f..89bfb0213a500c 100644
+--- a/arch/arm64/include/asm/uprobes.h
++++ b/arch/arm64/include/asm/uprobes.h
+@@ -29,5 +29,14 @@ struct arch_uprobe {
+ };
+
+ int uprobe_brk_handler(struct pt_regs *regs, unsigned long esr);
++#ifdef CONFIG_UPROBES
++int uprobe_single_step_handler(struct pt_regs *regs, unsigned long esr);
++#else
++static inline int uprobe_single_step_handler(struct pt_regs *regs,
++ unsigned long esr)
++{
++ return DBG_HOOK_ERROR;
++}
++#endif
+
+ #endif
+diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
+index 5e892448030005..f929b107840de6 100644
+--- a/arch/arm64/kernel/debug-monitors.c
++++ b/arch/arm64/kernel/debug-monitors.c
+@@ -200,30 +200,17 @@ void unregister_kernel_step_hook(struct step_hook *hook)
+ }
+
+ /*
+- * Call registered single step handlers
++ * Call single step handlers
+ * There is no Syndrome info to check for determining the handler.
+- * So we call all the registered handlers, until the right handler is
+- * found which returns zero.
++ * However, there is only one possible handler for user and kernel modes, so
++ * check and call the appropriate one.
+ */
+ static int call_step_hook(struct pt_regs *regs, unsigned long esr)
+ {
+- struct step_hook *hook;
+- struct list_head *list;
+- int retval = DBG_HOOK_ERROR;
++ if (user_mode(regs))
++ return uprobe_single_step_handler(regs, esr);
+
+- list = user_mode(regs) ? &user_step_hook : &kernel_step_hook;
+-
+- /*
+- * Since single-step exception disables interrupt, this function is
+- * entirely not preemptible, and we can use rcu list safely here.
+- */
+- list_for_each_entry_rcu(hook, list, node) {
+- retval = hook->fn(regs, esr);
+- if (retval == DBG_HOOK_HANDLED)
+- break;
+- }
+-
+- return retval;
++ return kgdb_single_step_handler(regs, esr);
+ }
+ NOKPROBE_SYMBOL(call_step_hook);
+
+diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
+index e3c9e6e11a318c..f8eaf6084c3d5a 100644
+--- a/arch/arm64/kernel/kgdb.c
++++ b/arch/arm64/kernel/kgdb.c
+@@ -250,7 +250,7 @@ int kgdb_compiled_brk_handler(struct pt_regs *regs, unsigned long esr)
+ }
+ NOKPROBE_SYMBOL(kgdb_compiled_brk_handler);
+
+-static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned long esr)
++int kgdb_single_step_handler(struct pt_regs *regs, unsigned long esr)
+ {
+ if (!kgdb_single_step)
+ return DBG_HOOK_ERROR;
+@@ -258,11 +258,7 @@ static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned long esr)
+ kgdb_handle_exception(0, SIGTRAP, 0, regs);
+ return DBG_HOOK_HANDLED;
+ }
+-NOKPROBE_SYMBOL(kgdb_step_brk_fn);
+-
+-static struct step_hook kgdb_step_hook = {
+- .fn = kgdb_step_brk_fn
+-};
++NOKPROBE_SYMBOL(kgdb_single_step_handler);
+
+ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+ {
+@@ -301,13 +297,7 @@ static struct notifier_block kgdb_notifier = {
+ */
+ int kgdb_arch_init(void)
+ {
+- int ret = register_die_notifier(&kgdb_notifier);
+-
+- if (ret != 0)
+- return ret;
+-
+- register_kernel_step_hook(&kgdb_step_hook);
+- return 0;
++ return register_die_notifier(&kgdb_notifier);
+ }
+
+ /*
+@@ -317,7 +307,6 @@ int kgdb_arch_init(void)
+ */
+ void kgdb_arch_exit(void)
+ {
+- unregister_kernel_step_hook(&kgdb_step_hook);
+ unregister_die_notifier(&kgdb_notifier);
+ }
+
+diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c
+index fc1bd19c827e6f..6ae4396577d4a6 100644
+--- a/arch/arm64/kernel/probes/uprobes.c
++++ b/arch/arm64/kernel/probes/uprobes.c
+@@ -174,7 +174,7 @@ int uprobe_brk_handler(struct pt_regs *regs,
+ return DBG_HOOK_ERROR;
+ }
+
+-static int uprobe_single_step_handler(struct pt_regs *regs,
++int uprobe_single_step_handler(struct pt_regs *regs,
+ unsigned long esr)
+ {
+ struct uprobe_task *utask = current->utask;
+@@ -186,16 +186,3 @@ static int uprobe_single_step_handler(struct pt_regs *regs,
+ return DBG_HOOK_ERROR;
+ }
+
+-/* uprobe single step handler hook */
+-static struct step_hook uprobes_step_hook = {
+- .fn = uprobe_single_step_handler,
+-};
+-
+-static int __init arch_init_uprobes(void)
+-{
+- register_user_step_hook(&uprobes_step_hook);
+-
+- return 0;
+-}
+-
+-device_initcall(arch_init_uprobes);
+--
+2.53.0
+
--- /dev/null
+From 97b8f48a02154f7313ebda4199bed6a881ae1d90 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:25:41 +0200
+Subject: arm64: debug: clean up single_step_handler logic
+
+From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+
+[ Upstream commit ad8b22648b7d0bc6f84230508436b1aafc2e2516 ]
+
+Remove the unnecessary boolean which always checks if the handler was found
+and return early instead.
+
+Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Tested-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Reviewed-by: Will Deacon <will@kernel.org>
+Link: https://lore.kernel.org/r/20250707114109.35672-2-ada.coupriediaz@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/kernel/debug-monitors.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
+index 024a7b245056a8..b7a2155bca42b1 100644
+--- a/arch/arm64/kernel/debug-monitors.c
++++ b/arch/arm64/kernel/debug-monitors.c
+@@ -241,8 +241,6 @@ static void send_user_sigtrap(int si_code)
+ static int single_step_handler(unsigned long unused, unsigned long esr,
+ struct pt_regs *regs)
+ {
+- bool handler_found = false;
+-
+ /*
+ * If we are stepping a pending breakpoint, call the hw_breakpoint
+ * handler first.
+@@ -250,10 +248,10 @@ static int single_step_handler(unsigned long unused, unsigned long esr,
+ if (!reinstall_suspended_bps(regs))
+ return 0;
+
+- if (!handler_found && call_step_hook(regs, esr) == DBG_HOOK_HANDLED)
+- handler_found = true;
++ if (call_step_hook(regs, esr) == DBG_HOOK_HANDLED)
++ return 0;
+
+- if (!handler_found && user_mode(regs)) {
++ if (user_mode(regs)) {
+ send_user_sigtrap(TRAP_TRACE);
+
+ /*
+@@ -263,7 +261,7 @@ static int single_step_handler(unsigned long unused, unsigned long esr,
+ * to the active-not-pending state).
+ */
+ user_rewind_single_step(current);
+- } else if (!handler_found) {
++ } else {
+ pr_warn("Unexpected kernel single-step exception at EL1\n");
+ /*
+ * Re-enable stepping since we know that we will be
+--
+2.53.0
+
--- /dev/null
+From e750d255f943d56545a39d9f07a907c9895df714 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:25:48 +0200
+Subject: arm64: debug: refactor reinstall_suspended_bps()
+
+From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+
+[ Upstream commit 80691d35523de3292b64c2ffa444aab3d55e51ba ]
+
+`reinstall_suspended_bps()` plays a key part in the stepping process
+when we have hardware breakpoints and watchpoints enabled.
+It checks if we need to step one, will re-enable it if it has
+been handled and will return whether or not we need to proceed with
+a single-step.
+
+However, the current naming and return values make it harder to understand
+the logic and goal of the function.
+
+Rename it `try_step_suspended_breakpoints()` and change the return value
+to a boolean, aligning it with similar functions used in
+`do_el0_undef()` like `try_emulate_mrs()`, and making its behaviour
+more obvious.
+
+Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Tested-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
+Reviewed-by: Will Deacon <will@kernel.org>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Link: https://lore.kernel.org/r/20250707114109.35672-9-ada.coupriediaz@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/debug-monitors.h | 6 +++---
+ arch/arm64/kernel/debug-monitors.c | 2 +-
+ arch/arm64/kernel/hw_breakpoint.c | 25 ++++++++++++-------------
+ 3 files changed, 16 insertions(+), 17 deletions(-)
+
+diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
+index 5319da0f0ca4ea..24c7981abeb0b9 100644
+--- a/arch/arm64/include/asm/debug-monitors.h
++++ b/arch/arm64/include/asm/debug-monitors.h
+@@ -83,11 +83,11 @@ int kernel_active_single_step(void);
+ void kernel_rewind_single_step(struct pt_regs *regs);
+
+ #ifdef CONFIG_HAVE_HW_BREAKPOINT
+-int reinstall_suspended_bps(struct pt_regs *regs);
++bool try_step_suspended_breakpoints(struct pt_regs *regs);
+ #else
+-static inline int reinstall_suspended_bps(struct pt_regs *regs)
++static inline bool try_step_suspended_breakpoints(struct pt_regs *regs)
+ {
+- return -ENODEV;
++ return false;
+ }
+ #endif
+
+diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
+index a28482e25c4c31..b95a135ef10a99 100644
+--- a/arch/arm64/kernel/debug-monitors.c
++++ b/arch/arm64/kernel/debug-monitors.c
+@@ -195,7 +195,7 @@ static int single_step_handler(unsigned long unused, unsigned long esr,
+ * If we are stepping a pending breakpoint, call the hw_breakpoint
+ * handler first.
+ */
+- if (!reinstall_suspended_bps(regs))
++ if (try_step_suspended_breakpoints(regs))
+ return 0;
+
+ if (call_step_hook(regs, esr) == DBG_HOOK_HANDLED)
+diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
+index d7eede5d869c2b..309ae24d454805 100644
+--- a/arch/arm64/kernel/hw_breakpoint.c
++++ b/arch/arm64/kernel/hw_breakpoint.c
+@@ -847,36 +847,35 @@ NOKPROBE_SYMBOL(watchpoint_handler);
+ /*
+ * Handle single-step exception.
+ */
+-int reinstall_suspended_bps(struct pt_regs *regs)
++bool try_step_suspended_breakpoints(struct pt_regs *regs)
+ {
+ struct debug_info *debug_info = ¤t->thread.debug;
+- int handled_exception = 0, *kernel_step;
+-
+- kernel_step = this_cpu_ptr(&stepping_kernel_bp);
++ int *kernel_step = this_cpu_ptr(&stepping_kernel_bp);
++ bool handled_exception = false;
+
+ /*
+ * Called from single-step exception handler.
+- * Return 0 if execution can resume, 1 if a SIGTRAP should be
+- * reported.
++ * Return true if we stepped a breakpoint and can resume execution,
++ * false if we need to handle a single-step.
+ */
+ if (user_mode(regs)) {
+ if (debug_info->bps_disabled) {
+ debug_info->bps_disabled = 0;
+ toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL0, 1);
+- handled_exception = 1;
++ handled_exception = true;
+ }
+
+ if (debug_info->wps_disabled) {
+ debug_info->wps_disabled = 0;
+ toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL0, 1);
+- handled_exception = 1;
++ handled_exception = true;
+ }
+
+ if (handled_exception) {
+ if (debug_info->suspended_step) {
+ debug_info->suspended_step = 0;
+ /* Allow exception handling to fall-through. */
+- handled_exception = 0;
++ handled_exception = false;
+ } else {
+ user_disable_single_step(current);
+ }
+@@ -890,17 +889,17 @@ int reinstall_suspended_bps(struct pt_regs *regs)
+
+ if (*kernel_step != ARM_KERNEL_STEP_SUSPEND) {
+ kernel_disable_single_step();
+- handled_exception = 1;
++ handled_exception = true;
+ } else {
+- handled_exception = 0;
++ handled_exception = false;
+ }
+
+ *kernel_step = ARM_KERNEL_STEP_NONE;
+ }
+
+- return !handled_exception;
++ return handled_exception;
+ }
+-NOKPROBE_SYMBOL(reinstall_suspended_bps);
++NOKPROBE_SYMBOL(try_step_suspended_breakpoints);
+
+ /*
+ * Context-switcher for restoring suspended breakpoints.
+--
+2.53.0
+
--- /dev/null
+From ea8b41531689ddff22defdb4c11a2060cb0d43c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:25:45 +0200
+Subject: arm64: debug: remove break/step handler registration infrastructure
+
+From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+
+[ Upstream commit d4e0b12620946a4011ad695490211fc38bf5cb42 ]
+
+Remove all infrastructure for the dynamic registration previously used by
+software breakpoints and stepping handlers.
+
+Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Tested-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
+Reviewed-by: Will Deacon <will@kernel.org>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Link: https://lore.kernel.org/r/20250707114109.35672-6-ada.coupriediaz@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/debug-monitors.h | 24 ----------
+ arch/arm64/kernel/debug-monitors.c | 63 -------------------------
+ 2 files changed, 87 deletions(-)
+
+diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
+index 3eeea1c9f06664..5319da0f0ca4ea 100644
+--- a/arch/arm64/include/asm/debug-monitors.h
++++ b/arch/arm64/include/asm/debug-monitors.h
+@@ -62,30 +62,6 @@ struct task_struct;
+ #define DBG_HOOK_HANDLED 0
+ #define DBG_HOOK_ERROR 1
+
+-struct step_hook {
+- struct list_head node;
+- int (*fn)(struct pt_regs *regs, unsigned long esr);
+-};
+-
+-void register_user_step_hook(struct step_hook *hook);
+-void unregister_user_step_hook(struct step_hook *hook);
+-
+-void register_kernel_step_hook(struct step_hook *hook);
+-void unregister_kernel_step_hook(struct step_hook *hook);
+-
+-struct break_hook {
+- struct list_head node;
+- int (*fn)(struct pt_regs *regs, unsigned long esr);
+- u16 imm;
+- u16 mask; /* These bits are ignored when comparing with imm */
+-};
+-
+-void register_user_break_hook(struct break_hook *hook);
+-void unregister_user_break_hook(struct break_hook *hook);
+-
+-void register_kernel_break_hook(struct break_hook *hook);
+-void unregister_kernel_break_hook(struct break_hook *hook);
+-
+ u8 debug_monitors_arch(void);
+
+ enum dbg_active_el {
+diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
+index f929b107840de6..a28482e25c4c31 100644
+--- a/arch/arm64/kernel/debug-monitors.c
++++ b/arch/arm64/kernel/debug-monitors.c
+@@ -159,46 +159,6 @@ NOKPROBE_SYMBOL(clear_user_regs_spsr_ss);
+ #define set_regs_spsr_ss(r) set_user_regs_spsr_ss(&(r)->user_regs)
+ #define clear_regs_spsr_ss(r) clear_user_regs_spsr_ss(&(r)->user_regs)
+
+-static DEFINE_SPINLOCK(debug_hook_lock);
+-static LIST_HEAD(user_step_hook);
+-static LIST_HEAD(kernel_step_hook);
+-
+-static void register_debug_hook(struct list_head *node, struct list_head *list)
+-{
+- spin_lock(&debug_hook_lock);
+- list_add_rcu(node, list);
+- spin_unlock(&debug_hook_lock);
+-
+-}
+-
+-static void unregister_debug_hook(struct list_head *node)
+-{
+- spin_lock(&debug_hook_lock);
+- list_del_rcu(node);
+- spin_unlock(&debug_hook_lock);
+- synchronize_rcu();
+-}
+-
+-void register_user_step_hook(struct step_hook *hook)
+-{
+- register_debug_hook(&hook->node, &user_step_hook);
+-}
+-
+-void unregister_user_step_hook(struct step_hook *hook)
+-{
+- unregister_debug_hook(&hook->node);
+-}
+-
+-void register_kernel_step_hook(struct step_hook *hook)
+-{
+- register_debug_hook(&hook->node, &kernel_step_hook);
+-}
+-
+-void unregister_kernel_step_hook(struct step_hook *hook)
+-{
+- unregister_debug_hook(&hook->node);
+-}
+-
+ /*
+ * Call single step handlers
+ * There is no Syndrome info to check for determining the handler.
+@@ -264,29 +224,6 @@ static int single_step_handler(unsigned long unused, unsigned long esr,
+ }
+ NOKPROBE_SYMBOL(single_step_handler);
+
+-static LIST_HEAD(user_break_hook);
+-static LIST_HEAD(kernel_break_hook);
+-
+-void register_user_break_hook(struct break_hook *hook)
+-{
+- register_debug_hook(&hook->node, &user_break_hook);
+-}
+-
+-void unregister_user_break_hook(struct break_hook *hook)
+-{
+- unregister_debug_hook(&hook->node);
+-}
+-
+-void register_kernel_break_hook(struct break_hook *hook)
+-{
+- register_debug_hook(&hook->node, &kernel_break_hook);
+-}
+-
+-void unregister_kernel_break_hook(struct break_hook *hook)
+-{
+- unregister_debug_hook(&hook->node);
+-}
+-
+ static int call_break_hook(struct pt_regs *regs, unsigned long esr)
+ {
+ if (user_mode(regs)) {
+--
+2.53.0
+
--- /dev/null
+From 6f897c500d0f4b7ac2ac85792f60f292bdc2eeb2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:25:53 +0200
+Subject: arm64: debug: remove debug exception registration infrastructure
+
+From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+
+[ Upstream commit a8b8cce9d96d65dfe3d89abf02033151f8b7d670 ]
+
+Now that debug exceptions are handled individually and without the need
+for dynamic registration, remove the unused registration infrastructure.
+
+This removes the external caller for `debug_exception_enter()` and
+`debug_exception_exit()`.
+Make them static again and remove them from the header.
+
+Remove `early_brk64()` as it has been made redundant by
+(arm64: debug: split brk64 exception entry) and is not used anymore.
+Note : in `early_brk64()` `bug_brk_handler()` is called unconditionally
+as a fall-through, but now `call_break_hook()` only calls it if the
+immediate matches.
+This does not change the behaviour in early boot, as if
+`bug_brk_handler()` was called on a non-BUG immediate it would return
+DBG_HOOK_ERROR anyway, which `call_break_hook()` will do if no immediate
+matches.
+
+Remove `trap_init()`, as it would be empty and a weak definition already
+exists in `init/main.c`.
+
+Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Tested-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Reviewed-by: Will Deacon <will@kernel.org>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Link: https://lore.kernel.org/r/20250707114109.35672-14-ada.coupriediaz@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/debug-monitors.h | 2 -
+ arch/arm64/include/asm/exception.h | 6 ---
+ arch/arm64/include/asm/system_misc.h | 4 --
+ arch/arm64/kernel/debug-monitors.c | 3 --
+ arch/arm64/kernel/entry-common.c | 4 +-
+ arch/arm64/kernel/traps.c | 27 -------------
+ arch/arm64/mm/fault.c | 53 -------------------------
+ 7 files changed, 2 insertions(+), 97 deletions(-)
+
+diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
+index 24c7981abeb0b9..4f3901884c5d85 100644
+--- a/arch/arm64/include/asm/debug-monitors.h
++++ b/arch/arm64/include/asm/debug-monitors.h
+@@ -93,7 +93,5 @@ static inline bool try_step_suspended_breakpoints(struct pt_regs *regs)
+
+ bool try_handle_aarch32_break(struct pt_regs *regs);
+
+-void debug_traps_init(void);
+-
+ #endif /* __ASSEMBLY */
+ #endif /* __ASM_DEBUG_MONITORS_H */
+diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
+index 9b05c6f487ccf1..50c5329ff2edae 100644
+--- a/arch/arm64/include/asm/exception.h
++++ b/arch/arm64/include/asm/exception.h
+@@ -57,8 +57,6 @@ void do_el0_undef(struct pt_regs *regs, unsigned long esr);
+ void do_el1_undef(struct pt_regs *regs, unsigned long esr);
+ void do_el0_bti(struct pt_regs *regs);
+ void do_el1_bti(struct pt_regs *regs, unsigned long esr);
+-void do_debug_exception(unsigned long addr_if_watchpoint, unsigned long esr,
+- struct pt_regs *regs);
+ #ifdef CONFIG_HAVE_HW_BREAKPOINT
+ void do_breakpoint(unsigned long esr, struct pt_regs *regs);
+ void do_watchpoint(unsigned long addr, unsigned long esr,
+@@ -91,8 +89,4 @@ void do_serror(struct pt_regs *regs, unsigned long esr);
+ void do_signal(struct pt_regs *regs);
+
+ void __noreturn panic_bad_stack(struct pt_regs *regs, unsigned long esr, unsigned long far);
+-
+-void debug_exception_enter(struct pt_regs *regs);
+-void debug_exception_exit(struct pt_regs *regs);
+-
+ #endif /* __ASM_EXCEPTION_H */
+diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
+index c343442567625d..344b1c1a4bbb69 100644
+--- a/arch/arm64/include/asm/system_misc.h
++++ b/arch/arm64/include/asm/system_misc.h
+@@ -25,10 +25,6 @@ void arm64_notify_die(const char *str, struct pt_regs *regs,
+ int signo, int sicode, unsigned long far,
+ unsigned long err);
+
+-void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned long,
+- struct pt_regs *),
+- int sig, int code, const char *name);
+-
+ struct mm_struct;
+ extern void __show_regs(struct pt_regs *);
+
+diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
+index ed03270fa34375..16390fd4ba5edd 100644
+--- a/arch/arm64/kernel/debug-monitors.c
++++ b/arch/arm64/kernel/debug-monitors.c
+@@ -316,9 +316,6 @@ bool try_handle_aarch32_break(struct pt_regs *regs)
+ }
+ NOKPROBE_SYMBOL(try_handle_aarch32_break);
+
+-void __init debug_traps_init(void)
+-{}
+-
+ /* Re-enable single step for syscall restarting. */
+ void user_rewind_single_step(struct task_struct *task)
+ {
+diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
+index 9a1ea5a6e6b72a..b98d6d1a1dfd63 100644
+--- a/arch/arm64/kernel/entry-common.c
++++ b/arch/arm64/kernel/entry-common.c
+@@ -448,7 +448,7 @@ static __always_inline void fpsimd_syscall_exit(void)
+ * accidentally schedule in exception context and it will force a warning
+ * if we somehow manage to schedule by accident.
+ */
+-void debug_exception_enter(struct pt_regs *regs)
++static void debug_exception_enter(struct pt_regs *regs)
+ {
+ preempt_disable();
+
+@@ -457,7 +457,7 @@ void debug_exception_enter(struct pt_regs *regs)
+ }
+ NOKPROBE_SYMBOL(debug_exception_enter);
+
+-void debug_exception_exit(struct pt_regs *regs)
++static void debug_exception_exit(struct pt_regs *regs)
+ {
+ preempt_enable_no_resched();
+ }
+diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
+index 013159bc0882ee..e6e815ef03c777 100644
+--- a/arch/arm64/kernel/traps.c
++++ b/arch/arm64/kernel/traps.c
+@@ -1091,30 +1091,3 @@ int ubsan_brk_handler(struct pt_regs *regs, unsigned long esr)
+ return DBG_HOOK_HANDLED;
+ }
+ #endif
+-
+-/*
+- * Initial handler for AArch64 BRK exceptions
+- * This handler only used until debug_traps_init().
+- */
+-int __init early_brk64(unsigned long addr, unsigned long esr,
+- struct pt_regs *regs)
+-{
+-#ifdef CONFIG_CFI_CLANG
+- if (esr_is_cfi_brk(esr))
+- return cfi_brk_handler(regs, esr) != DBG_HOOK_HANDLED;
+-#endif
+-#ifdef CONFIG_KASAN_SW_TAGS
+- if ((esr_brk_comment(esr) & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
+- return kasan_brk_handler(regs, esr) != DBG_HOOK_HANDLED;
+-#endif
+-#ifdef CONFIG_UBSAN_TRAP
+- if (esr_is_ubsan_brk(esr))
+- return ubsan_brk_handler(regs, esr) != DBG_HOOK_HANDLED;
+-#endif
+- return bug_brk_handler(regs, esr) != DBG_HOOK_HANDLED;
+-}
+-
+-void __init trap_init(void)
+-{
+- debug_traps_init();
+-}
+diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
+index 7c87d2b3b06eaa..9ee5a2d2b32151 100644
+--- a/arch/arm64/mm/fault.c
++++ b/arch/arm64/mm/fault.c
+@@ -53,18 +53,12 @@ struct fault_info {
+ };
+
+ static const struct fault_info fault_info[];
+-static struct fault_info debug_fault_info[];
+
+ static inline const struct fault_info *esr_to_fault_info(unsigned long esr)
+ {
+ return fault_info + (esr & ESR_ELx_FSC);
+ }
+
+-static inline const struct fault_info *esr_to_debug_fault_info(unsigned long esr)
+-{
+- return debug_fault_info + DBG_ESR_EVT(esr);
+-}
+-
+ static void data_abort_decode(unsigned long esr)
+ {
+ unsigned long iss2 = ESR_ELx_ISS2(esr);
+@@ -911,53 +905,6 @@ void do_sp_pc_abort(unsigned long addr, unsigned long esr, struct pt_regs *regs)
+ }
+ NOKPROBE_SYMBOL(do_sp_pc_abort);
+
+-/*
+- * __refdata because early_brk64 is __init, but the reference to it is
+- * clobbered at arch_initcall time.
+- * See traps.c and debug-monitors.c:debug_traps_init().
+- */
+-static struct fault_info __refdata debug_fault_info[] = {
+- { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware breakpoint" },
+- { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware single-step" },
+- { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware watchpoint" },
+- { do_bad, SIGKILL, SI_KERNEL, "unknown 3" },
+- { do_bad, SIGTRAP, TRAP_BRKPT, "aarch32 BKPT" },
+- { do_bad, SIGKILL, SI_KERNEL, "aarch32 vector catch" },
+- { early_brk64, SIGTRAP, TRAP_BRKPT, "aarch64 BRK" },
+- { do_bad, SIGKILL, SI_KERNEL, "unknown 7" },
+-};
+-
+-void __init hook_debug_fault_code(int nr,
+- int (*fn)(unsigned long, unsigned long, struct pt_regs *),
+- int sig, int code, const char *name)
+-{
+- BUG_ON(nr < 0 || nr >= ARRAY_SIZE(debug_fault_info));
+-
+- debug_fault_info[nr].fn = fn;
+- debug_fault_info[nr].sig = sig;
+- debug_fault_info[nr].code = code;
+- debug_fault_info[nr].name = name;
+-}
+-
+-void do_debug_exception(unsigned long addr_if_watchpoint, unsigned long esr,
+- struct pt_regs *regs)
+-{
+- const struct fault_info *inf = esr_to_debug_fault_info(esr);
+- unsigned long pc = instruction_pointer(regs);
+-
+- debug_exception_enter(regs);
+-
+- if (user_mode(regs) && !is_ttbr0_addr(pc))
+- arm64_apply_bp_hardening();
+-
+- if (inf->fn(addr_if_watchpoint, esr, regs)) {
+- arm64_notify_die(inf->name, regs, inf->sig, inf->code, pc, esr);
+- }
+-
+- debug_exception_exit(regs);
+-}
+-NOKPROBE_SYMBOL(do_debug_exception);
+-
+ /*
+ * Used during anonymous page fault handling.
+ */
+--
+2.53.0
+
--- /dev/null
+From 41f7de14999f10ff56b1abf68e1184c1b73d243f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:25:52 +0200
+Subject: arm64: debug: split bkpt32 exception entry
+
+From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+
+[ Upstream commit fc5e5d0477c532054ce8692fd16fdaab2cb8946f ]
+
+Currently all debug exceptions share common entry code and are routed
+to `do_debug_exception()`, which calls dynamically-registered
+handlers for each specific debug exception. This is unfortunate as
+different debug exceptions have different entry handling requirements,
+and it would be better to handle these distinct requirements earlier.
+
+The BKPT32 exception can only be triggered by a BKPT instruction. Thus,
+we know that the PC is a legitimate address and isn't being used to train
+a branch predictor with a bogus address : we don't need to call
+`arm64_apply_bp_hardening()`.
+
+The handler for this exception only pends a signal and doesn't depend
+on any per-CPU state : we don't need to inhibit preemption, nor do we
+need to keep the DAIF exceptions masked, so we can unmask them earlier.
+
+Split the BKPT32 exception entry and adjust function signatures and its
+behaviour to match its relaxed constraints compared to other
+debug exceptions.
+We can also remove `NOKRPOBE_SYMBOL`, as this cannot lead to a kprobe
+recursion.
+
+This replaces the last usage of `el0_dbg()`, so remove it.
+
+Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Tested-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Reviewed-by: Will Deacon <will@kernel.org>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Link: https://lore.kernel.org/r/20250707114109.35672-13-ada.coupriediaz@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/exception.h | 1 +
+ arch/arm64/kernel/debug-monitors.c | 7 +++++++
+ arch/arm64/kernel/entry-common.c | 22 +++++++++-------------
+ 3 files changed, 17 insertions(+), 13 deletions(-)
+
+diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
+index 7bc79602840fd0..9b05c6f487ccf1 100644
+--- a/arch/arm64/include/asm/exception.h
++++ b/arch/arm64/include/asm/exception.h
+@@ -72,6 +72,7 @@ void do_el0_softstep(unsigned long esr, struct pt_regs *regs);
+ void do_el1_softstep(unsigned long esr, struct pt_regs *regs);
+ void do_el0_brk64(unsigned long esr, struct pt_regs *regs);
+ void do_el1_brk64(unsigned long esr, struct pt_regs *regs);
++void do_bkpt32(unsigned long esr, struct pt_regs *regs);
+ void do_fpsimd_acc(unsigned long esr, struct pt_regs *regs);
+ void do_sve_acc(unsigned long esr, struct pt_regs *regs);
+ void do_sme_acc(unsigned long esr, struct pt_regs *regs);
+diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
+index 45e0dbe17c82fd..ed03270fa34375 100644
+--- a/arch/arm64/kernel/debug-monitors.c
++++ b/arch/arm64/kernel/debug-monitors.c
+@@ -270,6 +270,13 @@ void do_el1_brk64(unsigned long esr, struct pt_regs *regs)
+ }
+ NOKPROBE_SYMBOL(do_el1_brk64);
+
++#ifdef CONFIG_COMPAT
++void do_bkpt32(unsigned long esr, struct pt_regs *regs)
++{
++ arm64_notify_die("aarch32 BKPT", regs, SIGTRAP, TRAP_BRKPT, regs->pc, esr);
++}
++#endif /* CONFIG_COMPAT */
++
+ bool try_handle_aarch32_break(struct pt_regs *regs)
+ {
+ u32 arm_instr;
+diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
+index ba114bfdb32b5a..9a1ea5a6e6b72a 100644
+--- a/arch/arm64/kernel/entry-common.c
++++ b/arch/arm64/kernel/entry-common.c
+@@ -834,18 +834,6 @@ static void noinstr el0_brk64(struct pt_regs *regs, unsigned long esr)
+ exit_to_user_mode(regs);
+ }
+
+-static void noinstr __maybe_unused
+-el0_dbg(struct pt_regs *regs, unsigned long esr)
+-{
+- /* Only watchpoints write FAR_EL1, otherwise its UNKNOWN */
+- unsigned long far = read_sysreg(far_el1);
+-
+- enter_from_user_mode(regs);
+- do_debug_exception(far, esr, regs);
+- local_daif_restore(DAIF_PROCCTX);
+- exit_to_user_mode(regs);
+-}
+-
+ static void noinstr el0_svc(struct pt_regs *regs)
+ {
+ enter_from_user_mode(regs);
+@@ -1003,6 +991,14 @@ static void noinstr el0_svc_compat(struct pt_regs *regs)
+ exit_to_user_mode(regs);
+ }
+
++static void noinstr el0_bkpt32(struct pt_regs *regs, unsigned long esr)
++{
++ enter_from_user_mode(regs);
++ local_daif_restore(DAIF_PROCCTX);
++ do_bkpt32(esr, regs);
++ exit_to_user_mode(regs);
++}
++
+ asmlinkage void noinstr el0t_32_sync_handler(struct pt_regs *regs)
+ {
+ unsigned long esr = read_sysreg(esr_el1);
+@@ -1046,7 +1042,7 @@ asmlinkage void noinstr el0t_32_sync_handler(struct pt_regs *regs)
+ el0_watchpt(regs, esr);
+ break;
+ case ESR_ELx_EC_BKPT32:
+- el0_dbg(regs, esr);
++ el0_bkpt32(regs, esr);
+ break;
+ default:
+ el0_inv(regs, esr);
+--
+2.53.0
+
--- /dev/null
+From 522c9125740a098c684585636b6959dab66c5865 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:25:51 +0200
+Subject: arm64: debug: split brk64 exception entry
+
+From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+
+[ Upstream commit 31575e11ecf7e44face72d1e624cb147a9283733 ]
+
+Currently all debug exceptions share common entry code and are routed
+to `do_debug_exception()`, which calls dynamically-registered
+handlers for each specific debug exception. This is unfortunate as
+different debug exceptions have different entry handling requirements,
+and it would be better to handle these distinct requirements earlier.
+
+The BRK64 instruction can only be triggered by a BRK instruction. Thus,
+we know that the PC is a legitimate address and isn't being used to train
+a branch predictor with a bogus address : we don't need to call
+`arm64_apply_bp_hardening()`.
+
+We do not need to handle the Cortex-A76 erratum #1463225 either, as it
+only relevant for single stepping at EL1.
+BRK64 does not write FAR_EL1 either, as only hardware watchpoints do so.
+
+Split the BRK64 exception entry, adjust the function signature, and its
+behaviour to match the lack of needed mitigations.
+Further, as the EL0 and EL1 code paths are cleanly separated, we can split
+`do_brk64()` into `do_el0_brk64()` and `do_el1_brk64()`, and call them
+directly from the relevant entry paths.
+Use `die()` directly for the EL1 error path, as in `do_el1_bti()` and
+`do_el1_undef()`.
+We can also remove `NOKRPOBE_SYMBOL` for the EL0 path, as it cannot
+lead to a kprobe recursion.
+
+When taking a BRK64 exception from EL0, the exception handling is safely
+preemptible : the only possible handler is `uprobe_brk_handler()`.
+It only operates on task-local data and properly checks its validity,
+then raises a Thread Information Flag, processed before returning
+to userspace in `do_notify_resume()`, which is already preemptible.
+Thus we can safely unmask interrupts and enable preemption before
+handling the break itself, fixing a PREEMPT_RT issue where the handler
+could call a sleeping function with preemption disabled.
+
+Given that the break hook registration is handled statically in
+`call_break_hook` since
+(arm64: debug: call software break handlers statically)
+and that we now bypass the exception handler registration, this change
+renders `early_brk64` redundant : its functionality is now handled through
+the post-init path.
+
+This also removes the last usage of `el1_dbg()`.
+
+This also removes the last usage of `el0_dbg()` without `CONFIG_COMPAT`.
+Mark it `__maybe_unused`, to prevent a warning when building this patch
+without `CONFIG_COMPAT`, as the following patch removes `el0_dbg()`.
+
+Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Tested-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Reviewed-by: Will Deacon <will@kernel.org>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Link: https://lore.kernel.org/r/20250707114109.35672-12-ada.coupriediaz@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/exception.h | 2 ++
+ arch/arm64/kernel/debug-monitors.c | 46 ++++++++++++++----------------
+ arch/arm64/kernel/entry-common.c | 24 ++++++++++------
+ 3 files changed, 39 insertions(+), 33 deletions(-)
+
+diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
+index 594350e552e112..7bc79602840fd0 100644
+--- a/arch/arm64/include/asm/exception.h
++++ b/arch/arm64/include/asm/exception.h
+@@ -70,6 +70,8 @@ static inline void do_watchpoint(unsigned long addr, unsigned long esr,
+ #endif /* CONFIG_HAVE_HW_BREAKPOINT */
+ void do_el0_softstep(unsigned long esr, struct pt_regs *regs);
+ void do_el1_softstep(unsigned long esr, struct pt_regs *regs);
++void do_el0_brk64(unsigned long esr, struct pt_regs *regs);
++void do_el1_brk64(unsigned long esr, struct pt_regs *regs);
+ void do_fpsimd_acc(unsigned long esr, struct pt_regs *regs);
+ void do_sve_acc(unsigned long esr, struct pt_regs *regs);
+ void do_sme_acc(unsigned long esr, struct pt_regs *regs);
+diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
+index 10d2bc51a32f7c..45e0dbe17c82fd 100644
+--- a/arch/arm64/kernel/debug-monitors.c
++++ b/arch/arm64/kernel/debug-monitors.c
+@@ -207,15 +207,8 @@ void do_el1_softstep(unsigned long esr, struct pt_regs *regs)
+ }
+ NOKPROBE_SYMBOL(do_el1_softstep);
+
+-static int call_break_hook(struct pt_regs *regs, unsigned long esr)
++static int call_el1_break_hook(struct pt_regs *regs, unsigned long esr)
+ {
+- if (user_mode(regs)) {
+- if (IS_ENABLED(CONFIG_UPROBES) &&
+- esr_brk_comment(esr) == UPROBES_BRK_IMM)
+- return uprobe_brk_handler(regs, esr);
+- return DBG_HOOK_ERROR;
+- }
+-
+ if (esr_brk_comment(esr) == BUG_BRK_IMM)
+ return bug_brk_handler(regs, esr);
+
+@@ -252,24 +245,30 @@ static int call_break_hook(struct pt_regs *regs, unsigned long esr)
+
+ return DBG_HOOK_ERROR;
+ }
+-NOKPROBE_SYMBOL(call_break_hook);
++NOKPROBE_SYMBOL(call_el1_break_hook);
+
+-static int brk_handler(unsigned long unused, unsigned long esr,
+- struct pt_regs *regs)
++/*
++ * We have already unmasked interrupts and enabled preemption
++ * when calling do_el0_brk64() from entry-common.c.
++ */
++void do_el0_brk64(unsigned long esr, struct pt_regs *regs)
+ {
+- if (call_break_hook(regs, esr) == DBG_HOOK_HANDLED)
+- return 0;
++ if (IS_ENABLED(CONFIG_UPROBES) &&
++ esr_brk_comment(esr) == UPROBES_BRK_IMM &&
++ uprobe_brk_handler(regs, esr) == DBG_HOOK_HANDLED)
++ return;
+
+- if (user_mode(regs)) {
+- send_user_sigtrap(TRAP_BRKPT);
+- } else {
+- pr_warn("Unexpected kernel BRK exception at EL1\n");
+- return -EFAULT;
+- }
++ send_user_sigtrap(TRAP_BRKPT);
++}
+
+- return 0;
++void do_el1_brk64(unsigned long esr, struct pt_regs *regs)
++{
++ if (call_el1_break_hook(regs, esr) == DBG_HOOK_HANDLED)
++ return;
++
++ die("Oops - BRK", regs, esr);
+ }
+-NOKPROBE_SYMBOL(brk_handler);
++NOKPROBE_SYMBOL(do_el1_brk64);
+
+ bool try_handle_aarch32_break(struct pt_regs *regs)
+ {
+@@ -311,10 +310,7 @@ bool try_handle_aarch32_break(struct pt_regs *regs)
+ NOKPROBE_SYMBOL(try_handle_aarch32_break);
+
+ void __init debug_traps_init(void)
+-{
+- hook_debug_fault_code(DBG_ESR_EVT_BRK, brk_handler, SIGTRAP,
+- TRAP_BRKPT, "BRK handler");
+-}
++{}
+
+ /* Re-enable single step for syscall restarting. */
+ void user_rewind_single_step(struct task_struct *task)
+diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
+index b90babcf2e2b10..ba114bfdb32b5a 100644
+--- a/arch/arm64/kernel/entry-common.c
++++ b/arch/arm64/kernel/entry-common.c
+@@ -547,13 +547,12 @@ static void noinstr el1_watchpt(struct pt_regs *regs, unsigned long esr)
+ arm64_exit_el1_dbg(regs);
+ }
+
+-static void noinstr el1_dbg(struct pt_regs *regs, unsigned long esr)
++static void noinstr el1_brk64(struct pt_regs *regs, unsigned long esr)
+ {
+- unsigned long far = read_sysreg(far_el1);
+-
+ arm64_enter_el1_dbg(regs);
+- if (!cortex_a76_erratum_1463225_debug_handler(regs))
+- do_debug_exception(far, esr, regs);
++ debug_exception_enter(regs);
++ do_el1_brk64(esr, regs);
++ debug_exception_exit(regs);
+ arm64_exit_el1_dbg(regs);
+ }
+
+@@ -599,7 +598,7 @@ asmlinkage void noinstr el1h_64_sync_handler(struct pt_regs *regs)
+ el1_watchpt(regs, esr);
+ break;
+ case ESR_ELx_EC_BRK64:
+- el1_dbg(regs, esr);
++ el1_brk64(regs, esr);
+ break;
+ case ESR_ELx_EC_FPAC:
+ el1_fpac(regs, esr);
+@@ -827,7 +826,16 @@ static void noinstr el0_watchpt(struct pt_regs *regs, unsigned long esr)
+ exit_to_user_mode(regs);
+ }
+
+-static void noinstr el0_dbg(struct pt_regs *regs, unsigned long esr)
++static void noinstr el0_brk64(struct pt_regs *regs, unsigned long esr)
++{
++ enter_from_user_mode(regs);
++ local_daif_restore(DAIF_PROCCTX);
++ do_el0_brk64(esr, regs);
++ exit_to_user_mode(regs);
++}
++
++static void noinstr __maybe_unused
++el0_dbg(struct pt_regs *regs, unsigned long esr)
+ {
+ /* Only watchpoints write FAR_EL1, otherwise its UNKNOWN */
+ unsigned long far = read_sysreg(far_el1);
+@@ -912,7 +920,7 @@ asmlinkage void noinstr el0t_64_sync_handler(struct pt_regs *regs)
+ el0_watchpt(regs, esr);
+ break;
+ case ESR_ELx_EC_BRK64:
+- el0_dbg(regs, esr);
++ el0_brk64(regs, esr);
+ break;
+ case ESR_ELx_EC_FPAC:
+ el0_fpac(regs, esr);
+--
+2.53.0
+
--- /dev/null
+From df0d2dd7be9c4c325300ca1c09e84c63d42c707a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:25:47 +0200
+Subject: arm64: debug: split hardware breakpoint exception entry
+
+From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+
+[ Upstream commit 43e2ae77fcab8a01101a2e5da528b5222b338e5f ]
+
+Currently all debug exceptions share common entry code and are routed
+to `do_debug_exception()`, which calls dynamically-registered
+handlers for each specific debug exception. This is unfortunate as
+different debug exceptions have different entry handling requirements,
+and it would be better to handle these distinct requirements earlier.
+
+Hardware breakpoints exceptions are generated by the hardware after user
+configuration. As such, they can be exploited when training branch
+predictors outside of the userspace VA range: they still need to call
+`arm64_apply_bp_hardening()` if needed to mitigate against this attack.
+
+However, they do not need to handle the Cortex-A76 erratum #1463225 as
+it only applies to single stepping exceptions.
+It does not set an address in FAR_EL1 either, only the hardware
+watchpoint does.
+
+As the hardware breakpoint handler only returns 0 and never triggers
+the call to `arm64_notify_die()`, we can call it directly from
+`entry-common.c`.
+Split the hardware breakpoint exception entry, adjust
+the function signature, and handling of the Cortex-A76 erratum to fit
+the behaviour of the exception.
+
+Move the call to `arm64_apply_bp_hardening()` to `entry-common.c` so that
+we can do it as early as possible, and only for the exceptions coming
+from EL0, where it is needed.
+This is safe to do as it is `noinstr`, as are all the functions it
+may call. `el0_ia()` and `el0_pc()` already call it this way.
+
+Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Tested-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Reviewed-by: Will Deacon <will@kernel.org>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Link: https://lore.kernel.org/r/20250707114109.35672-8-ada.coupriediaz@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/exception.h | 5 +++++
+ arch/arm64/kernel/entry-common.c | 28 ++++++++++++++++++++++++++++
+ arch/arm64/kernel/hw_breakpoint.c | 16 ++++++----------
+ 3 files changed, 39 insertions(+), 10 deletions(-)
+
+diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
+index b1d6a65f6d2256..94f46e96515160 100644
+--- a/arch/arm64/include/asm/exception.h
++++ b/arch/arm64/include/asm/exception.h
+@@ -59,6 +59,11 @@ void do_el0_bti(struct pt_regs *regs);
+ void do_el1_bti(struct pt_regs *regs, unsigned long esr);
+ void do_debug_exception(unsigned long addr_if_watchpoint, unsigned long esr,
+ struct pt_regs *regs);
++#ifdef CONFIG_HAVE_HW_BREAKPOINT
++void do_breakpoint(unsigned long esr, struct pt_regs *regs);
++#else
++static inline void do_breakpoint(unsigned long esr, struct pt_regs *regs) {}
++#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+ void do_fpsimd_acc(unsigned long esr, struct pt_regs *regs);
+ void do_sve_acc(unsigned long esr, struct pt_regs *regs);
+ void do_sme_acc(unsigned long esr, struct pt_regs *regs);
+diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
+index 2e04e04aaf2ad6..af0d7575dcfd92 100644
+--- a/arch/arm64/kernel/entry-common.c
++++ b/arch/arm64/kernel/entry-common.c
+@@ -508,6 +508,15 @@ static void noinstr el1_bti(struct pt_regs *regs, unsigned long esr)
+ exit_to_kernel_mode(regs);
+ }
+
++static void noinstr el1_breakpt(struct pt_regs *regs, unsigned long esr)
++{
++ arm64_enter_el1_dbg(regs);
++ debug_exception_enter(regs);
++ do_breakpoint(esr, regs);
++ debug_exception_exit(regs);
++ arm64_exit_el1_dbg(regs);
++}
++
+ static void noinstr el1_dbg(struct pt_regs *regs, unsigned long esr)
+ {
+ unsigned long far = read_sysreg(far_el1);
+@@ -551,6 +560,8 @@ asmlinkage void noinstr el1h_64_sync_handler(struct pt_regs *regs)
+ el1_bti(regs, esr);
+ break;
+ case ESR_ELx_EC_BREAKPT_CUR:
++ el1_breakpt(regs, esr);
++ break;
+ case ESR_ELx_EC_SOFTSTP_CUR:
+ case ESR_ELx_EC_WATCHPT_CUR:
+ case ESR_ELx_EC_BRK64:
+@@ -737,6 +748,19 @@ static void noinstr el0_inv(struct pt_regs *regs, unsigned long esr)
+ exit_to_user_mode(regs);
+ }
+
++static void noinstr el0_breakpt(struct pt_regs *regs, unsigned long esr)
++{
++ if (!is_ttbr0_addr(regs->pc))
++ arm64_apply_bp_hardening();
++
++ enter_from_user_mode(regs);
++ debug_exception_enter(regs);
++ do_breakpoint(esr, regs);
++ debug_exception_exit(regs);
++ local_daif_restore(DAIF_PROCCTX);
++ exit_to_user_mode(regs);
++}
++
+ static void noinstr el0_dbg(struct pt_regs *regs, unsigned long esr)
+ {
+ /* Only watchpoints write FAR_EL1, otherwise its UNKNOWN */
+@@ -813,6 +837,8 @@ asmlinkage void noinstr el0t_64_sync_handler(struct pt_regs *regs)
+ el0_mops(regs, esr);
+ break;
+ case ESR_ELx_EC_BREAKPT_LOW:
++ el0_breakpt(regs, esr);
++ break;
+ case ESR_ELx_EC_SOFTSTP_LOW:
+ case ESR_ELx_EC_WATCHPT_LOW:
+ case ESR_ELx_EC_BRK64:
+@@ -933,6 +959,8 @@ asmlinkage void noinstr el0t_32_sync_handler(struct pt_regs *regs)
+ el0_cp15(regs, esr);
+ break;
+ case ESR_ELx_EC_BREAKPT_LOW:
++ el0_breakpt(regs, esr);
++ break;
+ case ESR_ELx_EC_SOFTSTP_LOW:
+ case ESR_ELx_EC_WATCHPT_LOW:
+ case ESR_ELx_EC_BKPT32:
+diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
+index 722ac45f9f7b16..d7eede5d869c2b 100644
+--- a/arch/arm64/kernel/hw_breakpoint.c
++++ b/arch/arm64/kernel/hw_breakpoint.c
+@@ -22,6 +22,7 @@
+ #include <asm/current.h>
+ #include <asm/debug-monitors.h>
+ #include <asm/esr.h>
++#include <asm/exception.h>
+ #include <asm/hw_breakpoint.h>
+ #include <asm/traps.h>
+ #include <asm/cputype.h>
+@@ -618,8 +619,7 @@ NOKPROBE_SYMBOL(toggle_bp_registers);
+ /*
+ * Debug exception handlers.
+ */
+-static int breakpoint_handler(unsigned long unused, unsigned long esr,
+- struct pt_regs *regs)
++void do_breakpoint(unsigned long esr, struct pt_regs *regs)
+ {
+ int i, step = 0, *kernel_step;
+ u32 ctrl_reg;
+@@ -662,7 +662,7 @@ static int breakpoint_handler(unsigned long unused, unsigned long esr,
+ }
+
+ if (!step)
+- return 0;
++ return;
+
+ if (user_mode(regs)) {
+ debug_info->bps_disabled = 1;
+@@ -670,7 +670,7 @@ static int breakpoint_handler(unsigned long unused, unsigned long esr,
+
+ /* If we're already stepping a watchpoint, just return. */
+ if (debug_info->wps_disabled)
+- return 0;
++ return;
+
+ if (test_thread_flag(TIF_SINGLESTEP))
+ debug_info->suspended_step = 1;
+@@ -681,7 +681,7 @@ static int breakpoint_handler(unsigned long unused, unsigned long esr,
+ kernel_step = this_cpu_ptr(&stepping_kernel_bp);
+
+ if (*kernel_step != ARM_KERNEL_STEP_NONE)
+- return 0;
++ return;
+
+ if (kernel_active_single_step()) {
+ *kernel_step = ARM_KERNEL_STEP_SUSPEND;
+@@ -690,10 +690,8 @@ static int breakpoint_handler(unsigned long unused, unsigned long esr,
+ kernel_enable_single_step(regs);
+ }
+ }
+-
+- return 0;
+ }
+-NOKPROBE_SYMBOL(breakpoint_handler);
++NOKPROBE_SYMBOL(do_breakpoint);
+
+ /*
+ * Arm64 hardware does not always report a watchpoint hit address that matches
+@@ -988,8 +986,6 @@ static int __init arch_hw_breakpoint_init(void)
+ core_num_brps, core_num_wrps);
+
+ /* Register debug fault handlers. */
+- hook_debug_fault_code(DBG_ESR_EVT_HWBP, breakpoint_handler, SIGTRAP,
+- TRAP_HWBKPT, "hw-breakpoint handler");
+ hook_debug_fault_code(DBG_ESR_EVT_HWWP, watchpoint_handler, SIGTRAP,
+ TRAP_HWBKPT, "hw-watchpoint handler");
+
+--
+2.53.0
+
--- /dev/null
+From 6c640c1850f7bb22d42145f3660fde62fd0eb849 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:25:50 +0200
+Subject: arm64: debug: split hardware watchpoint exception entry
+
+From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+
+[ Upstream commit 413f0bba005dacf2484bb8ecce212fab9be79d81 ]
+
+Currently all debug exceptions share common entry code and are routed
+to `do_debug_exception()`, which calls dynamically-registered
+handlers for each specific debug exception. This is unfortunate as
+different debug exceptions have different entry handling requirements,
+and it would be better to handle these distinct requirements earlier.
+
+Hardware watchpoints are the only debug exceptions that will write
+FAR_EL1, so we need to preserve it and pass it down.
+However, they cannot be used to maliciously train branch predictors, so
+we can omit calling `arm64_bp_hardening()`, nor do they need to handle
+the Cortex-A76 erratum #1463225, as it only applies to single stepping
+exceptions.
+
+As the hardware watchpoint handler only returns 0 and never triggers
+the call to `arm64_notify_die()`, we can call it directly from
+`entry-common.c`.
+Split the hardware watchpoint exception entry and adjust the behaviour
+to match the lack of needed mitigations.
+
+Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Tested-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Reviewed-by: Will Deacon <will@kernel.org>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Link: https://lore.kernel.org/r/20250707114109.35672-11-ada.coupriediaz@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/exception.h | 4 ++++
+ arch/arm64/kernel/entry-common.c | 31 ++++++++++++++++++++++++++++++
+ arch/arm64/kernel/hw_breakpoint.c | 17 +++++-----------
+ 3 files changed, 40 insertions(+), 12 deletions(-)
+
+diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
+index 6d40efc28be401..594350e552e112 100644
+--- a/arch/arm64/include/asm/exception.h
++++ b/arch/arm64/include/asm/exception.h
+@@ -61,8 +61,12 @@ void do_debug_exception(unsigned long addr_if_watchpoint, unsigned long esr,
+ struct pt_regs *regs);
+ #ifdef CONFIG_HAVE_HW_BREAKPOINT
+ void do_breakpoint(unsigned long esr, struct pt_regs *regs);
++void do_watchpoint(unsigned long addr, unsigned long esr,
++ struct pt_regs *regs);
+ #else
+ static inline void do_breakpoint(unsigned long esr, struct pt_regs *regs) {}
++static inline void do_watchpoint(unsigned long addr, unsigned long esr,
++ struct pt_regs *regs) {}
+ #endif /* CONFIG_HAVE_HW_BREAKPOINT */
+ void do_el0_softstep(unsigned long esr, struct pt_regs *regs);
+ void do_el1_softstep(unsigned long esr, struct pt_regs *regs);
+diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
+index c22cc4d0052d54..b90babcf2e2b10 100644
+--- a/arch/arm64/kernel/entry-common.c
++++ b/arch/arm64/kernel/entry-common.c
+@@ -535,6 +535,18 @@ static void noinstr el1_softstp(struct pt_regs *regs, unsigned long esr)
+ arm64_exit_el1_dbg(regs);
+ }
+
++static void noinstr el1_watchpt(struct pt_regs *regs, unsigned long esr)
++{
++ /* Watchpoints are the only debug exception to write FAR_EL1 */
++ unsigned long far = read_sysreg(far_el1);
++
++ arm64_enter_el1_dbg(regs);
++ debug_exception_enter(regs);
++ do_watchpoint(far, esr, regs);
++ debug_exception_exit(regs);
++ arm64_exit_el1_dbg(regs);
++}
++
+ static void noinstr el1_dbg(struct pt_regs *regs, unsigned long esr)
+ {
+ unsigned long far = read_sysreg(far_el1);
+@@ -584,6 +596,8 @@ asmlinkage void noinstr el1h_64_sync_handler(struct pt_regs *regs)
+ el1_softstp(regs, esr);
+ break;
+ case ESR_ELx_EC_WATCHPT_CUR:
++ el1_watchpt(regs, esr);
++ break;
+ case ESR_ELx_EC_BRK64:
+ el1_dbg(regs, esr);
+ break;
+@@ -800,6 +814,19 @@ static void noinstr el0_softstp(struct pt_regs *regs, unsigned long esr)
+ exit_to_user_mode(regs);
+ }
+
++static void noinstr el0_watchpt(struct pt_regs *regs, unsigned long esr)
++{
++ /* Watchpoints are the only debug exception to write FAR_EL1 */
++ unsigned long far = read_sysreg(far_el1);
++
++ enter_from_user_mode(regs);
++ debug_exception_enter(regs);
++ do_watchpoint(far, esr, regs);
++ debug_exception_exit(regs);
++ local_daif_restore(DAIF_PROCCTX);
++ exit_to_user_mode(regs);
++}
++
+ static void noinstr el0_dbg(struct pt_regs *regs, unsigned long esr)
+ {
+ /* Only watchpoints write FAR_EL1, otherwise its UNKNOWN */
+@@ -882,6 +909,8 @@ asmlinkage void noinstr el0t_64_sync_handler(struct pt_regs *regs)
+ el0_softstp(regs, esr);
+ break;
+ case ESR_ELx_EC_WATCHPT_LOW:
++ el0_watchpt(regs, esr);
++ break;
+ case ESR_ELx_EC_BRK64:
+ el0_dbg(regs, esr);
+ break;
+@@ -1006,6 +1035,8 @@ asmlinkage void noinstr el0t_32_sync_handler(struct pt_regs *regs)
+ el0_softstp(regs, esr);
+ break;
+ case ESR_ELx_EC_WATCHPT_LOW:
++ el0_watchpt(regs, esr);
++ break;
+ case ESR_ELx_EC_BKPT32:
+ el0_dbg(regs, esr);
+ break;
+diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
+index 8a80e13347c88f..ab76b36dce820b 100644
+--- a/arch/arm64/kernel/hw_breakpoint.c
++++ b/arch/arm64/kernel/hw_breakpoint.c
+@@ -750,8 +750,7 @@ static int watchpoint_report(struct perf_event *wp, unsigned long addr,
+ return step;
+ }
+
+-static int watchpoint_handler(unsigned long addr, unsigned long esr,
+- struct pt_regs *regs)
++void do_watchpoint(unsigned long addr, unsigned long esr, struct pt_regs *regs)
+ {
+ int i, step = 0, *kernel_step, access, closest_match = 0;
+ u64 min_dist = -1, dist;
+@@ -806,7 +805,7 @@ static int watchpoint_handler(unsigned long addr, unsigned long esr,
+ rcu_read_unlock();
+
+ if (!step)
+- return 0;
++ return;
+
+ /*
+ * We always disable EL0 watchpoints because the kernel can
+@@ -819,7 +818,7 @@ static int watchpoint_handler(unsigned long addr, unsigned long esr,
+
+ /* If we're already stepping a breakpoint, just return. */
+ if (debug_info->bps_disabled)
+- return 0;
++ return;
+
+ if (test_thread_flag(TIF_SINGLESTEP))
+ debug_info->suspended_step = 1;
+@@ -830,7 +829,7 @@ static int watchpoint_handler(unsigned long addr, unsigned long esr,
+ kernel_step = this_cpu_ptr(&stepping_kernel_bp);
+
+ if (*kernel_step != ARM_KERNEL_STEP_NONE)
+- return 0;
++ return;
+
+ if (kernel_active_single_step()) {
+ *kernel_step = ARM_KERNEL_STEP_SUSPEND;
+@@ -839,10 +838,8 @@ static int watchpoint_handler(unsigned long addr, unsigned long esr,
+ kernel_enable_single_step(regs);
+ }
+ }
+-
+- return 0;
+ }
+-NOKPROBE_SYMBOL(watchpoint_handler);
++NOKPROBE_SYMBOL(do_watchpoint);
+
+ /*
+ * Handle single-step exception.
+@@ -984,10 +981,6 @@ static int __init arch_hw_breakpoint_init(void)
+ pr_info("found %d breakpoint and %d watchpoint registers.\n",
+ core_num_brps, core_num_wrps);
+
+- /* Register debug fault handlers. */
+- hook_debug_fault_code(DBG_ESR_EVT_HWWP, watchpoint_handler, SIGTRAP,
+- TRAP_HWBKPT, "hw-watchpoint handler");
+-
+ /*
+ * Reset the breakpoint resources. We assume that a halting
+ * debugger will leave the world in a nice state for us.
+--
+2.53.0
+
--- /dev/null
+From 4f0e01d33f85d69272c4340964178d2b507620be Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:25:49 +0200
+Subject: arm64: debug: split single stepping exception entry
+
+From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+
+[ Upstream commit 0ac7584c08ceff13fc1e3082a0104548688d6b00 ]
+
+Currently all debug exceptions share common entry code and are routed
+to `do_debug_exception()`, which calls dynamically-registered
+handlers for each specific debug exception. This is unfortunate as
+different debug exceptions have different entry handling requirements,
+and it would be better to handle these distinct requirements earlier.
+
+The single stepping exception has the most constraints : it can be
+exploited to train branch predictors and it needs special handling at EL1
+for the Cortex-A76 erratum #1463225. We need to conserve all those
+mitigations.
+However, it does not write an address at FAR_EL1, as only hardware
+watchpoints do so.
+
+The single-step handler does its own signaling if it needs to and only
+returns 0, so we can call it directly from `entry-common.c`.
+
+Split the single stepping exception entry, adjust the function signature,
+keep the security mitigation and erratum handling.
+Further, as the EL0 and EL1 code paths are cleanly separated, we can split
+`do_softstep()` into `do_el0_softstep()` and `do_el1_softstep()` and
+call them directly from the relevant entry paths.
+We can also remove `NOKPROBE_SYMBOL` for the EL0 path, as it cannot
+lead to a kprobe recursion.
+
+Move the call to `arm64_apply_bp_hardening()` to `entry-common.c` so that
+we can do it as early as possible, and only for the exceptions coming
+from EL0, where it is needed.
+This is safe to do as it is `noinstr`, as are all the functions it
+may call. `el0_ia()` and `el0_pc()` already call it this way.
+
+When taking a soft-step exception from EL0, most of the single stepping
+handling is safely preemptible : the only possible handler is
+`uprobe_single_step_handler()`. It only operates on task-local data and
+properly checks its validity, then raises a Thread Information Flag,
+processed before returning to userspace in `do_notify_resume()`, which
+is already preemptible.
+However, the soft-step handler first calls `reinstall_suspended_bps()`
+to check if there is any hardware breakpoint or watchpoint pending
+or already stepped through.
+This cannot be preempted as it manipulates the hardware breakpoint and
+watchpoint registers.
+
+Move the call to `try_step_suspended_breakpoints()` to `entry-common.c`
+and adjust the relevant comments.
+We can now safely unmask interrupts before handling the step itself,
+fixing a PREEMPT_RT issue where the handler could call a sleeping function
+with preemption disabled.
+
+Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Closes: https://lore.kernel.org/linux-arm-kernel/Z6YW_Kx4S2tmj2BP@uudg.org/
+Tested-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Reviewed-by: Will Deacon <will@kernel.org>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Link: https://lore.kernel.org/r/20250707114109.35672-10-ada.coupriediaz@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/exception.h | 2 +
+ arch/arm64/kernel/debug-monitors.c | 73 +++++++++++-------------------
+ arch/arm64/kernel/entry-common.c | 43 ++++++++++++++++++
+ arch/arm64/kernel/hw_breakpoint.c | 2 +-
+ 4 files changed, 73 insertions(+), 47 deletions(-)
+
+diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
+index 94f46e96515160..6d40efc28be401 100644
+--- a/arch/arm64/include/asm/exception.h
++++ b/arch/arm64/include/asm/exception.h
+@@ -64,6 +64,8 @@ void do_breakpoint(unsigned long esr, struct pt_regs *regs);
+ #else
+ static inline void do_breakpoint(unsigned long esr, struct pt_regs *regs) {}
+ #endif /* CONFIG_HAVE_HW_BREAKPOINT */
++void do_el0_softstep(unsigned long esr, struct pt_regs *regs);
++void do_el1_softstep(unsigned long esr, struct pt_regs *regs);
+ void do_fpsimd_acc(unsigned long esr, struct pt_regs *regs);
+ void do_sve_acc(unsigned long esr, struct pt_regs *regs);
+ void do_sme_acc(unsigned long esr, struct pt_regs *regs);
+diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
+index b95a135ef10a99..10d2bc51a32f7c 100644
+--- a/arch/arm64/kernel/debug-monitors.c
++++ b/arch/arm64/kernel/debug-monitors.c
+@@ -21,6 +21,7 @@
+ #include <asm/cputype.h>
+ #include <asm/daifflags.h>
+ #include <asm/debug-monitors.h>
++#include <asm/exception.h>
+ #include <asm/kgdb.h>
+ #include <asm/kprobes.h>
+ #include <asm/system_misc.h>
+@@ -159,21 +160,6 @@ NOKPROBE_SYMBOL(clear_user_regs_spsr_ss);
+ #define set_regs_spsr_ss(r) set_user_regs_spsr_ss(&(r)->user_regs)
+ #define clear_regs_spsr_ss(r) clear_user_regs_spsr_ss(&(r)->user_regs)
+
+-/*
+- * Call single step handlers
+- * There is no Syndrome info to check for determining the handler.
+- * However, there is only one possible handler for user and kernel modes, so
+- * check and call the appropriate one.
+- */
+-static int call_step_hook(struct pt_regs *regs, unsigned long esr)
+-{
+- if (user_mode(regs))
+- return uprobe_single_step_handler(regs, esr);
+-
+- return kgdb_single_step_handler(regs, esr);
+-}
+-NOKPROBE_SYMBOL(call_step_hook);
+-
+ static void send_user_sigtrap(int si_code)
+ {
+ struct pt_regs *regs = current_pt_regs();
+@@ -188,41 +174,38 @@ static void send_user_sigtrap(int si_code)
+ "User debug trap");
+ }
+
+-static int single_step_handler(unsigned long unused, unsigned long esr,
+- struct pt_regs *regs)
++/*
++ * We have already unmasked interrupts and enabled preemption
++ * when calling do_el0_softstep() from entry-common.c.
++ */
++void do_el0_softstep(unsigned long esr, struct pt_regs *regs)
+ {
++ if (uprobe_single_step_handler(regs, esr) == DBG_HOOK_HANDLED)
++ return;
++
++ send_user_sigtrap(TRAP_TRACE);
+ /*
+- * If we are stepping a pending breakpoint, call the hw_breakpoint
+- * handler first.
++ * ptrace will disable single step unless explicitly
++ * asked to re-enable it. For other clients, it makes
++ * sense to leave it enabled (i.e. rewind the controls
++ * to the active-not-pending state).
+ */
+- if (try_step_suspended_breakpoints(regs))
+- return 0;
+-
+- if (call_step_hook(regs, esr) == DBG_HOOK_HANDLED)
+- return 0;
++ user_rewind_single_step(current);
++}
+
+- if (user_mode(regs)) {
+- send_user_sigtrap(TRAP_TRACE);
+-
+- /*
+- * ptrace will disable single step unless explicitly
+- * asked to re-enable it. For other clients, it makes
+- * sense to leave it enabled (i.e. rewind the controls
+- * to the active-not-pending state).
+- */
+- user_rewind_single_step(current);
+- } else {
+- pr_warn("Unexpected kernel single-step exception at EL1\n");
+- /*
+- * Re-enable stepping since we know that we will be
+- * returning to regs.
+- */
+- set_regs_spsr_ss(regs);
+- }
++void do_el1_softstep(unsigned long esr, struct pt_regs *regs)
++{
++ if (kgdb_single_step_handler(regs, esr) == DBG_HOOK_HANDLED)
++ return;
+
+- return 0;
++ pr_warn("Unexpected kernel single-step exception at EL1\n");
++ /*
++ * Re-enable stepping since we know that we will be
++ * returning to regs.
++ */
++ set_regs_spsr_ss(regs);
+ }
+-NOKPROBE_SYMBOL(single_step_handler);
++NOKPROBE_SYMBOL(do_el1_softstep);
+
+ static int call_break_hook(struct pt_regs *regs, unsigned long esr)
+ {
+@@ -329,8 +312,6 @@ NOKPROBE_SYMBOL(try_handle_aarch32_break);
+
+ void __init debug_traps_init(void)
+ {
+- hook_debug_fault_code(DBG_ESR_EVT_HWSS, single_step_handler, SIGTRAP,
+- TRAP_TRACE, "single-step handler");
+ hook_debug_fault_code(DBG_ESR_EVT_BRK, brk_handler, SIGTRAP,
+ TRAP_BRKPT, "BRK handler");
+ }
+diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
+index af0d7575dcfd92..c22cc4d0052d54 100644
+--- a/arch/arm64/kernel/entry-common.c
++++ b/arch/arm64/kernel/entry-common.c
+@@ -517,6 +517,24 @@ static void noinstr el1_breakpt(struct pt_regs *regs, unsigned long esr)
+ arm64_exit_el1_dbg(regs);
+ }
+
++static void noinstr el1_softstp(struct pt_regs *regs, unsigned long esr)
++{
++ arm64_enter_el1_dbg(regs);
++ if (!cortex_a76_erratum_1463225_debug_handler(regs)) {
++ debug_exception_enter(regs);
++ /*
++ * After handling a breakpoint, we suspend the breakpoint
++ * and use single-step to move to the next instruction.
++ * If we are stepping a suspended breakpoint there's nothing more to do:
++ * the single-step is complete.
++ */
++ if (!try_step_suspended_breakpoints(regs))
++ do_el1_softstep(esr, regs);
++ debug_exception_exit(regs);
++ }
++ arm64_exit_el1_dbg(regs);
++}
++
+ static void noinstr el1_dbg(struct pt_regs *regs, unsigned long esr)
+ {
+ unsigned long far = read_sysreg(far_el1);
+@@ -563,6 +581,8 @@ asmlinkage void noinstr el1h_64_sync_handler(struct pt_regs *regs)
+ el1_breakpt(regs, esr);
+ break;
+ case ESR_ELx_EC_SOFTSTP_CUR:
++ el1_softstp(regs, esr);
++ break;
+ case ESR_ELx_EC_WATCHPT_CUR:
+ case ESR_ELx_EC_BRK64:
+ el1_dbg(regs, esr);
+@@ -761,6 +781,25 @@ static void noinstr el0_breakpt(struct pt_regs *regs, unsigned long esr)
+ exit_to_user_mode(regs);
+ }
+
++static void noinstr el0_softstp(struct pt_regs *regs, unsigned long esr)
++{
++ if (!is_ttbr0_addr(regs->pc))
++ arm64_apply_bp_hardening();
++
++ enter_from_user_mode(regs);
++ /*
++ * After handling a breakpoint, we suspend the breakpoint
++ * and use single-step to move to the next instruction.
++ * If we are stepping a suspended breakpoint there's nothing more to do:
++ * the single-step is complete.
++ */
++ if (!try_step_suspended_breakpoints(regs)) {
++ local_daif_restore(DAIF_PROCCTX);
++ do_el0_softstep(esr, regs);
++ }
++ exit_to_user_mode(regs);
++}
++
+ static void noinstr el0_dbg(struct pt_regs *regs, unsigned long esr)
+ {
+ /* Only watchpoints write FAR_EL1, otherwise its UNKNOWN */
+@@ -840,6 +879,8 @@ asmlinkage void noinstr el0t_64_sync_handler(struct pt_regs *regs)
+ el0_breakpt(regs, esr);
+ break;
+ case ESR_ELx_EC_SOFTSTP_LOW:
++ el0_softstp(regs, esr);
++ break;
+ case ESR_ELx_EC_WATCHPT_LOW:
+ case ESR_ELx_EC_BRK64:
+ el0_dbg(regs, esr);
+@@ -962,6 +1003,8 @@ asmlinkage void noinstr el0t_32_sync_handler(struct pt_regs *regs)
+ el0_breakpt(regs, esr);
+ break;
+ case ESR_ELx_EC_SOFTSTP_LOW:
++ el0_softstp(regs, esr);
++ break;
+ case ESR_ELx_EC_WATCHPT_LOW:
+ case ESR_ELx_EC_BKPT32:
+ el0_dbg(regs, esr);
+diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
+index 309ae24d454805..8a80e13347c88f 100644
+--- a/arch/arm64/kernel/hw_breakpoint.c
++++ b/arch/arm64/kernel/hw_breakpoint.c
+@@ -854,7 +854,7 @@ bool try_step_suspended_breakpoints(struct pt_regs *regs)
+ bool handled_exception = false;
+
+ /*
+- * Called from single-step exception handler.
++ * Called from single-step exception entry.
+ * Return true if we stepped a breakpoint and can resume execution,
+ * false if we need to handle a single-step.
+ */
+--
+2.53.0
+
--- /dev/null
+From 7218b03de6b3f9077424926feccd628d2cd218a4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:25:46 +0200
+Subject: arm64: entry: Add entry and exit functions for debug exceptions
+
+From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+
+[ Upstream commit eaff68b3286116d499a3d4e513a36d772faba587 ]
+
+Move the `debug_exception_enter()` and `debug_exception_exit()`
+functions from mm/fault.c, as they are needed to split
+the debug exceptions entry paths from the current unified one.
+
+Make them externally visible in include/asm/exception.h until
+the caller in mm/fault.c is cleaned up.
+
+Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Tested-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
+Reviewed-by: Will Deacon <will@kernel.org>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Link: https://lore.kernel.org/r/20250707114109.35672-7-ada.coupriediaz@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/exception.h | 4 ++++
+ arch/arm64/kernel/entry-common.c | 22 ++++++++++++++++++++++
+ arch/arm64/mm/fault.c | 22 ----------------------
+ 3 files changed, 26 insertions(+), 22 deletions(-)
+
+diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
+index f296662590c7f8..b1d6a65f6d2256 100644
+--- a/arch/arm64/include/asm/exception.h
++++ b/arch/arm64/include/asm/exception.h
+@@ -77,4 +77,8 @@ void do_serror(struct pt_regs *regs, unsigned long esr);
+ void do_signal(struct pt_regs *regs);
+
+ void __noreturn panic_bad_stack(struct pt_regs *regs, unsigned long esr, unsigned long far);
++
++void debug_exception_enter(struct pt_regs *regs);
++void debug_exception_exit(struct pt_regs *regs);
++
+ #endif /* __ASM_EXCEPTION_H */
+diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
+index d23315ef7b679b..2e04e04aaf2ad6 100644
+--- a/arch/arm64/kernel/entry-common.c
++++ b/arch/arm64/kernel/entry-common.c
+@@ -441,6 +441,28 @@ static __always_inline void fpsimd_syscall_exit(void)
+ __this_cpu_write(fpsimd_last_state.to_save, FP_STATE_CURRENT);
+ }
+
++/*
++ * In debug exception context, we explicitly disable preemption despite
++ * having interrupts disabled.
++ * This serves two purposes: it makes it much less likely that we would
++ * accidentally schedule in exception context and it will force a warning
++ * if we somehow manage to schedule by accident.
++ */
++void debug_exception_enter(struct pt_regs *regs)
++{
++ preempt_disable();
++
++ /* This code is a bit fragile. Test it. */
++ RCU_LOCKDEP_WARN(!rcu_is_watching(), "exception_enter didn't work");
++}
++NOKPROBE_SYMBOL(debug_exception_enter);
++
++void debug_exception_exit(struct pt_regs *regs)
++{
++ preempt_enable_no_resched();
++}
++NOKPROBE_SYMBOL(debug_exception_exit);
++
+ UNHANDLED(el1t, 64, sync)
+ UNHANDLED(el1t, 64, irq)
+ UNHANDLED(el1t, 64, fiq)
+diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
+index 2d1ebc0c3437f2..7c87d2b3b06eaa 100644
+--- a/arch/arm64/mm/fault.c
++++ b/arch/arm64/mm/fault.c
+@@ -939,28 +939,6 @@ void __init hook_debug_fault_code(int nr,
+ debug_fault_info[nr].name = name;
+ }
+
+-/*
+- * In debug exception context, we explicitly disable preemption despite
+- * having interrupts disabled.
+- * This serves two purposes: it makes it much less likely that we would
+- * accidentally schedule in exception context and it will force a warning
+- * if we somehow manage to schedule by accident.
+- */
+-static void debug_exception_enter(struct pt_regs *regs)
+-{
+- preempt_disable();
+-
+- /* This code is a bit fragile. Test it. */
+- RCU_LOCKDEP_WARN(!rcu_is_watching(), "exception_enter didn't work");
+-}
+-NOKPROBE_SYMBOL(debug_exception_enter);
+-
+-static void debug_exception_exit(struct pt_regs *regs)
+-{
+- preempt_enable_no_resched();
+-}
+-NOKPROBE_SYMBOL(debug_exception_exit);
+-
+ void do_debug_exception(unsigned long addr_if_watchpoint, unsigned long esr,
+ struct pt_regs *regs)
+ {
+--
+2.53.0
+
--- /dev/null
+From 0015fe8d4fb74bfd8db7b5546545adc5bcb392d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:25:40 +0200
+Subject: arm64: Introduce esr_is_ubsan_brk()
+
+From: Mostafa Saleh <smostafa@google.com>
+
+[ Upstream commit dc1fd37a7f501731e488c1c6f86b2f591632a4ad ]
+
+Soon, KVM is going to use this logic for hypervisor panics,
+so add it in a wrapper that can be used by the hypervisor exit
+handler to decode hyp panics.
+
+Signed-off-by: Mostafa Saleh <smostafa@google.com>
+Reviewed-by: Kees Cook <kees@kernel.org>
+Link: https://lore.kernel.org/r/20250430162713.1997569-2-smostafa@google.com
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/esr.h | 5 +++++
+ arch/arm64/kernel/traps.c | 2 +-
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
+index 5f4dc6364dbb9d..b0520b18192c5a 100644
+--- a/arch/arm64/include/asm/esr.h
++++ b/arch/arm64/include/asm/esr.h
+@@ -409,6 +409,11 @@ static inline bool esr_is_cfi_brk(unsigned long esr)
+ (esr_brk_comment(esr) & ~CFI_BRK_IMM_MASK) == CFI_BRK_IMM_BASE;
+ }
+
++static inline bool esr_is_ubsan_brk(unsigned long esr)
++{
++ return (esr_brk_comment(esr) & ~UBSAN_BRK_MASK) == UBSAN_BRK_IMM;
++}
++
+ static inline bool esr_fsc_is_translation_fault(unsigned long esr)
+ {
+ esr = esr & ESR_ELx_FSC;
+diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
+index e2e8ffa65aa586..5e138cf5d4ade3 100644
+--- a/arch/arm64/kernel/traps.c
++++ b/arch/arm64/kernel/traps.c
+@@ -1136,7 +1136,7 @@ int __init early_brk64(unsigned long addr, unsigned long esr,
+ return kasan_handler(regs, esr) != DBG_HOOK_HANDLED;
+ #endif
+ #ifdef CONFIG_UBSAN_TRAP
+- if ((esr_brk_comment(esr) & ~UBSAN_BRK_MASK) == UBSAN_BRK_IMM)
++ if (esr_is_ubsan_brk(esr))
+ return ubsan_handler(regs, esr) != DBG_HOOK_HANDLED;
+ #endif
+ return bug_handler(regs, esr) != DBG_HOOK_HANDLED;
+--
+2.53.0
+
--- /dev/null
+From fbce8389712b338c681afcdbaf131ecf23e15da4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 12:25:42 +0200
+Subject: arm64: refactor aarch32_break_handler()
+
+From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+
+[ Upstream commit b1e2d95524e4d0f5b643394c739212869e95cf6a ]
+
+`aarch32_break_handler()` is called in `do_el0_undef()` when we
+are trying to handle an exception whose Exception Syndrome is unknown.
+It checks if the instruction hit might be a 32-bit arm break (be it
+A32 or T2), and sends a SIGTRAP to userspace if it is so that it can
+be handled.
+
+However, this is badly represented in the naming of the function, and
+is not consistent with the other functions called with the same logic
+in `do_el0_undef()`.
+
+Rename it `try_handle_aarch32_break()` and change the return value to
+a boolean to align with the logic of the other tentative handlers in
+`do_el0_undef()`, the previous error code being ignored anyway.
+
+Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Tested-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Reviewed-by: Will Deacon <will@kernel.org>
+Link: https://lore.kernel.org/r/20250707114109.35672-3-ada.coupriediaz@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/debug-monitors.h | 2 +-
+ arch/arm64/kernel/debug-monitors.c | 10 +++++-----
+ arch/arm64/kernel/traps.c | 2 +-
+ 3 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
+index 13d437bcbf58c2..3eeea1c9f06664 100644
+--- a/arch/arm64/include/asm/debug-monitors.h
++++ b/arch/arm64/include/asm/debug-monitors.h
+@@ -115,7 +115,7 @@ static inline int reinstall_suspended_bps(struct pt_regs *regs)
+ }
+ #endif
+
+-int aarch32_break_handler(struct pt_regs *regs);
++bool try_handle_aarch32_break(struct pt_regs *regs);
+
+ void debug_traps_init(void);
+
+diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
+index b7a2155bca42b1..8275b7f5754626 100644
+--- a/arch/arm64/kernel/debug-monitors.c
++++ b/arch/arm64/kernel/debug-monitors.c
+@@ -335,7 +335,7 @@ static int brk_handler(unsigned long unused, unsigned long esr,
+ }
+ NOKPROBE_SYMBOL(brk_handler);
+
+-int aarch32_break_handler(struct pt_regs *regs)
++bool try_handle_aarch32_break(struct pt_regs *regs)
+ {
+ u32 arm_instr;
+ u16 thumb_instr;
+@@ -343,7 +343,7 @@ int aarch32_break_handler(struct pt_regs *regs)
+ void __user *pc = (void __user *)instruction_pointer(regs);
+
+ if (!compat_user_mode(regs))
+- return -EFAULT;
++ return false;
+
+ if (compat_thumb_mode(regs)) {
+ /* get 16-bit Thumb instruction */
+@@ -367,12 +367,12 @@ int aarch32_break_handler(struct pt_regs *regs)
+ }
+
+ if (!bp)
+- return -EFAULT;
++ return false;
+
+ send_user_sigtrap(TRAP_BRKPT);
+- return 0;
++ return true;
+ }
+-NOKPROBE_SYMBOL(aarch32_break_handler);
++NOKPROBE_SYMBOL(try_handle_aarch32_break);
+
+ void __init debug_traps_init(void)
+ {
+diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
+index 5e138cf5d4ade3..c38ebf715be764 100644
+--- a/arch/arm64/kernel/traps.c
++++ b/arch/arm64/kernel/traps.c
+@@ -462,7 +462,7 @@ void do_el0_undef(struct pt_regs *regs, unsigned long esr)
+ u32 insn;
+
+ /* check for AArch32 breakpoint instructions */
+- if (!aarch32_break_handler(regs))
++ if (try_handle_aarch32_break(regs))
+ return;
+
+ if (user_insn_read(regs, &insn))
+--
+2.53.0
+
--- /dev/null
+From 545ac76f1abc68e59dd9a70bd8c62e4f25e4e305 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Apr 2026 12:21:35 +0800
+Subject: bcache: fix uninitialized closure object
+
+From: Mingzhe Zou <mingzhe.zou@easystack.cn>
+
+[ Upstream commit 20a8e451ec1c7e99060b1bbaaad03ce88c39ddb8 ]
+
+In the previous patch ("bcache: fix cached_dev.sb_bio use-after-free and
+crash"), we adopted a simple modification suggestion from AI to fix the
+use-after-free.
+
+But in actual testing, we found an extreme case where the device is
+stopped before calling bch_write_bdev_super().
+
+At this point, struct closure sb_write has not been initialized yet.
+For this patch, we ensure that sb_bio has been completed via
+sb_write_mutex.
+
+Signed-off-by: Mingzhe Zou <mingzhe.zou@easystack.cn>
+Signed-off-by: Coly Li <colyli@fnnas.com>
+Link: https://patch.msgid.link/20260403042135.2221247-1-colyli@fnnas.com
+Fixes: fec114a98b87 ("bcache: fix cached_dev.sb_bio use-after-free and crash")
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/bcache/super.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
+index 6e0ac0958c10b5..f969ea43492531 100644
+--- a/drivers/md/bcache/super.c
++++ b/drivers/md/bcache/super.c
+@@ -1378,7 +1378,8 @@ static CLOSURE_CALLBACK(cached_dev_free)
+ * The sb_bio is embedded in struct cached_dev, so we must
+ * ensure no I/O is in progress.
+ */
+- closure_sync(&dc->sb_write);
++ down(&dc->sb_write_mutex);
++ up(&dc->sb_write_mutex);
+
+ if (dc->sb_disk)
+ put_page(virt_to_page(dc->sb_disk));
+--
+2.53.0
+
--- /dev/null
+From 437dc0ec19a0c2c386662a1033fd7055d9a92a8f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 18:02:01 -0300
+Subject: drm/v3d: Fix use-after-free of CPU job query arrays on error path
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: MaÃra Canal <mcanal@igalia.com>
+
+[ Upstream commit b0fe80c0b9250b35e2211bf3117e7aca814a21b0 ]
+
+The CPU job ioctl's fail label calls kvfree() on cpu_job's timestamp and
+performance query arrays after v3d_job_cleanup(), which drops the job's
+last reference and frees cpu_job. Reading cpu_job at that point is a
+use-after-free. Also, on the early v3d_job_init() failure path, it is a
+NULL dereference, since v3d_job_deallocate() zeroes the local pointer.
+
+In the success path, the arrays are released from the scheduler's
+.free_job callback, but on the error path, they are freed manually, as
+the job was never pushed to the scheduler. While the success path deals
+with this correctly, the fail path doesn't.
+
+On top of that, the manual kvfree() calls only free the array storage;
+they don't drm_syncobj_put() the per-query syncobjs that
+v3d_timestamp_query_info_free() and v3d_performance_query_info_free()
+release on the success path. So the same fail path that triggers the
+use-after-free also leaks one syncobj reference per query.
+
+Unify the CPU job teardown into the CPU job's kref destructor, mirroring
+v3d_render_job_free(). The scheduler's .free_job slot reverts to the
+generic v3d_sched_job_free() and the fail label drops the manual
+kvfree() calls, leaving a single teardown path that is reached from both
+the scheduler and the ioctl error path. That removes the use-after-free,
+the NULL dereference, and the syncobj leak by construction.
+
+Cc: stable@vger.kernel.org
+Fixes: 9ba0ff3e083f ("drm/v3d: Create a CPU job extension for the timestamp query job")
+Assisted-by: Claude:claude-opus-4.7
+Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
+Link: https://patch.msgid.link/20260515-v3d-cpu-job-leaks-v1-1-7f147cbbf935@igalia.com
+Signed-off-by: MaÃra Canal <mcanal@igalia.com>
+Signed-off-by: MaÃra Canal <mcanal@igalia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/v3d/v3d_sched.c | 16 +---------------
+ drivers/gpu/drm/v3d/v3d_submit.c | 19 ++++++++++++++++---
+ 2 files changed, 17 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
+index c9c88d3ad6698f..90eef062766c8d 100644
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -103,20 +103,6 @@ v3d_performance_query_info_free(struct v3d_performance_query_info *query_info,
+ }
+ }
+
+-static void
+-v3d_cpu_job_free(struct drm_sched_job *sched_job)
+-{
+- struct v3d_cpu_job *job = to_cpu_job(sched_job);
+-
+- v3d_timestamp_query_info_free(&job->timestamp_query,
+- job->timestamp_query.count);
+-
+- v3d_performance_query_info_free(&job->performance_query,
+- job->performance_query.count);
+-
+- v3d_job_cleanup(&job->base);
+-}
+-
+ static void
+ v3d_switch_perfmon(struct v3d_dev *v3d, struct v3d_job *job)
+ {
+@@ -846,7 +832,7 @@ static const struct drm_sched_backend_ops v3d_cache_clean_sched_ops = {
+ static const struct drm_sched_backend_ops v3d_cpu_sched_ops = {
+ .run_job = v3d_cpu_job_run,
+ .timedout_job = v3d_generic_job_timedout,
+- .free_job = v3d_cpu_job_free
++ .free_job = v3d_sched_job_free
+ };
+
+ int
+diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c
+index ddc20191a1ceef..40c21aaade0d67 100644
+--- a/drivers/gpu/drm/v3d/v3d_submit.c
++++ b/drivers/gpu/drm/v3d/v3d_submit.c
+@@ -118,6 +118,21 @@ v3d_render_job_free(struct kref *ref)
+ v3d_job_free(ref);
+ }
+
++static void
++v3d_cpu_job_free(struct kref *ref)
++{
++ struct v3d_cpu_job *job = container_of(ref, struct v3d_cpu_job,
++ base.refcount);
++
++ v3d_timestamp_query_info_free(&job->timestamp_query,
++ job->timestamp_query.count);
++
++ v3d_performance_query_info_free(&job->performance_query,
++ job->performance_query.count);
++
++ v3d_job_free(ref);
++}
++
+ void v3d_job_cleanup(struct v3d_job *job)
+ {
+ if (!job)
+@@ -1310,7 +1325,7 @@ v3d_submit_cpu_ioctl(struct drm_device *dev, void *data,
+ trace_v3d_submit_cpu_ioctl(&v3d->drm, cpu_job->job_type);
+
+ ret = v3d_job_init(v3d, file_priv, &cpu_job->base,
+- v3d_job_free, 0, &se, V3D_CPU);
++ v3d_cpu_job_free, 0, &se, V3D_CPU);
+ if (ret) {
+ v3d_job_deallocate((void *)&cpu_job);
+ goto fail;
+@@ -1393,8 +1408,6 @@ v3d_submit_cpu_ioctl(struct drm_device *dev, void *data,
+ v3d_job_cleanup((void *)csd_job);
+ v3d_job_cleanup(clean_job);
+ v3d_put_multisync_post_deps(&se);
+- kvfree(cpu_job->timestamp_query.queries);
+- kvfree(cpu_job->performance_query.queries);
+
+ return ret;
+ }
+--
+2.53.0
+
--- /dev/null
+From ac324089f2969ff248d230dd8c5057d3833bc969 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 31 May 2026 18:02:02 -0300
+Subject: drm/v3d: Release indirect CSD GEM reference on CPU job free
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: MaÃra Canal <mcanal@igalia.com>
+
+[ Upstream commit 6eb6e5acafa46854d4363e6c34981289995f3ace ]
+
+v3d_get_cpu_indirect_csd_params() takes a reference to the indirect BO via
+drm_gem_object_lookup() and stashes it in cpu_job->indirect_csd.indirect,
+but nothing on the CPU job teardown path ever drops that reference.
+
+Drop the extra reference in v3d_cpu_job_free(). The NULL check covers ioctl
+errors before the lookup ran and CPU job types other than
+V3D_CPU_JOB_TYPE_INDIRECT_CSD, which leave the field zero-initialised.
+
+Cc: stable@vger.kernel.org
+Fixes: 18b8413b25b7 ("drm/v3d: Create a CPU job extension for a indirect CSD job")
+Assisted-by: Claude:claude-opus-4.7
+Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
+Link: https://patch.msgid.link/20260515-v3d-cpu-job-leaks-v1-2-7f147cbbf935@igalia.com
+Signed-off-by: MaÃra Canal <mcanal@igalia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/v3d/v3d_submit.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c
+index 40c21aaade0d67..23472c7af41a96 100644
+--- a/drivers/gpu/drm/v3d/v3d_submit.c
++++ b/drivers/gpu/drm/v3d/v3d_submit.c
+@@ -130,6 +130,9 @@ v3d_cpu_job_free(struct kref *ref)
+ v3d_performance_query_info_free(&job->performance_query,
+ job->performance_query.count);
+
++ if (job->indirect_csd.indirect)
++ drm_gem_object_put(job->indirect_csd.indirect);
++
+ v3d_job_free(ref);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From ce9afcfe3b2fbb17ba1b8c32a9af013c3770474c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 15:37:08 +0800
+Subject: net: cpsw_new: Fix potential unregister of netdev that has not been
+ registered yet
+
+From: Kevin Hao <haokexin@gmail.com>
+
+[ Upstream commit 9d724b34fbe13b71865ad0906a4be97571f19cf5 ]
+
+If an error occurs during register_netdev() for the first MAC in
+cpsw_register_ports(), even though cpsw->slaves[0].ndev is set to NULL,
+cpsw->slaves[1].ndev would remain unchanged. This could later cause
+cpsw_unregister_ports() to attempt unregistering the second MAC.
+To address this, add a check for ndev->reg_state before calling
+unregister_netdev(). With this change, setting cpsw->slaves[i].ndev
+to NULL becomes unnecessary and can be removed accordingly.
+
+Fixes: ed3525eda4c4 ("net: ethernet: ti: introduce cpsw switchdev based driver part 1 - dual-emac")
+Signed-off-by: Kevin Hao <haokexin@gmail.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
+Link: https://patch.msgid.link/20260205-cpsw-error-path-v1-2-6e58bae6b299@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Wenshan Lan <jetlan9@163.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ti/cpsw_new.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
+index a74caaca94d110..fa161a10960459 100644
+--- a/drivers/net/ethernet/ti/cpsw_new.c
++++ b/drivers/net/ethernet/ti/cpsw_new.c
+@@ -1443,7 +1443,8 @@ static void cpsw_unregister_ports(struct cpsw_common *cpsw)
+ int i = 0;
+
+ for (i = 0; i < cpsw->data.slaves; i++) {
+- if (!cpsw->slaves[i].ndev)
++ if (!cpsw->slaves[i].ndev ||
++ cpsw->slaves[i].ndev->reg_state != NETREG_REGISTERED)
+ continue;
+
+ unregister_netdev(cpsw->slaves[i].ndev);
+@@ -1463,7 +1464,6 @@ static int cpsw_register_ports(struct cpsw_common *cpsw)
+ if (ret) {
+ dev_err(cpsw->dev,
+ "cpsw: err registering net device%d\n", i);
+- cpsw->slaves[i].ndev = NULL;
+ break;
+ }
+ }
+--
+2.53.0
+
--- /dev/null
+From 817d04a6ee8eb3b53cb5c3d93cf7712429210558 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 15:35:48 +0800
+Subject: net: mctp: ensure our nlmsg responses are initialised
+
+From: Jeremy Kerr <jk@codeconstruct.com.au>
+
+[ Upstream commit a6a9bc544b675d8b5180f2718ec985ad267b5cbf ]
+
+Syed Faraz Abrar (@farazsth98) from Zellic, and Pumpkin (@u1f383) from
+DEVCORE Research Team working with Trend Micro Zero Day Initiative
+report that a RTM_GETNEIGH will return uninitalised data in the pad
+bytes of the ndmsg data.
+
+Ensure we're initialising the netlink data to zero, in the link, addr
+and neigh response messages.
+
+Fixes: 831119f88781 ("mctp: Add neighbour netlink interface")
+Fixes: 06d2f4c583a7 ("mctp: Add netlink route management")
+Fixes: 583be982d934 ("mctp: Add device handling and netlink interface")
+Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260209-dev-mctp-nlmsg-v1-1-f1e30c346a43@codeconstruct.com.au
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Li hongliang <1468888505@139.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mctp/device.c | 1 +
+ net/mctp/neigh.c | 1 +
+ net/mctp/route.c | 1 +
+ 3 files changed, 3 insertions(+)
+
+diff --git a/net/mctp/device.c b/net/mctp/device.c
+index 8d1386601bbe06..67576cb2728ece 100644
+--- a/net/mctp/device.c
++++ b/net/mctp/device.c
+@@ -70,6 +70,7 @@ static int mctp_fill_addrinfo(struct sk_buff *skb,
+ return -EMSGSIZE;
+
+ hdr = nlmsg_data(nlh);
++ memset(hdr, 0, sizeof(*hdr));
+ hdr->ifa_family = AF_MCTP;
+ hdr->ifa_prefixlen = 0;
+ hdr->ifa_flags = 0;
+diff --git a/net/mctp/neigh.c b/net/mctp/neigh.c
+index 590f642413e4ef..c0151a69d2b7c2 100644
+--- a/net/mctp/neigh.c
++++ b/net/mctp/neigh.c
+@@ -218,6 +218,7 @@ static int mctp_fill_neigh(struct sk_buff *skb, u32 portid, u32 seq, int event,
+ return -EMSGSIZE;
+
+ hdr = nlmsg_data(nlh);
++ memset(hdr, 0, sizeof(*hdr));
+ hdr->ndm_family = AF_MCTP;
+ hdr->ndm_ifindex = dev->ifindex;
+ hdr->ndm_state = 0; // TODO other state bits?
+diff --git a/net/mctp/route.c b/net/mctp/route.c
+index ccba2abbbbfbcc..35a0681123a33f 100644
+--- a/net/mctp/route.c
++++ b/net/mctp/route.c
+@@ -1405,6 +1405,7 @@ static int mctp_fill_rtinfo(struct sk_buff *skb, struct mctp_route *rt,
+ return -EMSGSIZE;
+
+ hdr = nlmsg_data(nlh);
++ memset(hdr, 0, sizeof(*hdr));
+ hdr->rtm_family = AF_MCTP;
+
+ /* we use the _len fields as a number of EIDs, rather than
+--
+2.53.0
+
--- /dev/null
+From 18d804eba01a851c9be8784ff63557dc0d9a044f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Apr 2026 17:24:36 +0200
+Subject: net/sched: cls_fw: fix NULL dereference of "old" filters before
+ change()
+
+From: Davide Caratti <dcaratti@redhat.com>
+
+[ Upstream commit 65782b2db7321d5f97c16718c4c7f6c7205a56be ]
+
+Like pointed out by Sashiko [1], since commit ed76f5edccc9 ("net: sched:
+protect filter_chain list with filter_chain_lock mutex") TC filters are
+added to a shared block and published to datapath before their ->change()
+function is called. This is a problem for cls_fw: an invalid filter
+created with the "old" method can still classify some packets before it
+is destroyed by the validation logic added by Xiang.
+Therefore, insisting with repeated runs of the following script:
+
+ # ip link add dev crash0 type dummy
+ # ip link set dev crash0 up
+ # mausezahn crash0 -c 100000 -P 10 \
+ > -A 4.3.2.1 -B 1.2.3.4 -t udp "dp=1234" -q &
+ # sleep 1
+ # tc qdisc add dev crash0 egress_block 1 clsact
+ # tc filter add block 1 protocol ip prio 1 matchall \
+ > action skbedit mark 65536 continue
+ # tc filter add block 1 protocol ip prio 2 fw
+ # ip link del dev crash0
+
+can still make fw_classify() hit the WARN_ON() in [2]:
+
+ WARNING: ./include/net/pkt_cls.h:88 at fw_classify+0x244/0x250 [cls_fw], CPU#18: mausezahn/1399
+ Modules linked in: cls_fw(E) act_skbedit(E)
+ CPU: 18 UID: 0 PID: 1399 Comm: mausezahn Tainted: G E 7.0.0-rc6-virtme #17 PREEMPT(full)
+ Tainted: [E]=UNSIGNED_MODULE
+ Hardware name: Red Hat KVM, BIOS 1.16.3-2.el9 04/01/2014
+ RIP: 0010:fw_classify+0x244/0x250 [cls_fw]
+ Code: 5c 49 c7 45 00 00 00 00 00 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 5b b8 ff ff ff ff 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 90 <0f> 0b 90 eb a0 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90
+ RSP: 0018:ffffd1b7026bf8a8 EFLAGS: 00010202
+ RAX: ffff8c5ac9c60800 RBX: ffff8c5ac99322c0 RCX: 0000000000000004
+ RDX: 0000000000000001 RSI: ffff8c5b74d7a000 RDI: ffff8c5ac8284f40
+ RBP: ffffd1b7026bf8d0 R08: 0000000000000000 R09: ffffd1b7026bf9b0
+ R10: 00000000ffffffff R11: 0000000000000000 R12: 0000000000010000
+ R13: ffffd1b7026bf930 R14: ffff8c5ac8284f40 R15: 0000000000000000
+ FS: 00007fca40c37740(0000) GS:ffff8c5b74d7a000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 00007fca40e822a0 CR3: 0000000005ca0001 CR4: 0000000000172ef0
+ Call Trace:
+ <TASK>
+ tcf_classify+0x17d/0x5c0
+ tc_run+0x9d/0x150
+ __dev_queue_xmit+0x2ab/0x14d0
+ ip_finish_output2+0x340/0x8f0
+ ip_output+0xa4/0x250
+ raw_sendmsg+0x147d/0x14b0
+ __sys_sendto+0x1cc/0x1f0
+ __x64_sys_sendto+0x24/0x30
+ do_syscall_64+0x126/0xf80
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+ RIP: 0033:0x7fca40e822ba
+ Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb b8 0f 1f 00 f3 0f 1e fa 41 89 ca 64 8b 04 25 18 00 00 00 85 c0 75 15 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 7e c3 0f 1f 44 00 00 41 54 48 83 ec 30 44 89
+ RSP: 002b:00007ffc248a42c8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
+ RAX: ffffffffffffffda RBX: 000055ef233289d0 RCX: 00007fca40e822ba
+ RDX: 000000000000001e RSI: 000055ef23328c30 RDI: 0000000000000003
+ RBP: 000055ef233289d0 R08: 00007ffc248a42d0 R09: 0000000000000010
+ R10: 0000000000000000 R11: 0000000000000246 R12: 000000000000001e
+ R13: 00000000000186a0 R14: 0000000000000000 R15: 00007fca41043000
+ </TASK>
+ irq event stamp: 1045778
+ hardirqs last enabled at (1045784): [<ffffffff864ec042>] __up_console_sem+0x52/0x60
+ hardirqs last disabled at (1045789): [<ffffffff864ec027>] __up_console_sem+0x37/0x60
+ softirqs last enabled at (1045426): [<ffffffff874d48c7>] __alloc_skb+0x207/0x260
+ softirqs last disabled at (1045434): [<ffffffff874fe8f8>] __dev_queue_xmit+0x78/0x14d0
+
+Then, because of the value in the packet's mark, dereference on 'q->handle'
+with NULL 'q' occurs:
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000038
+ [...]
+ RIP: 0010:fw_classify+0x1fe/0x250 [cls_fw]
+ [...]
+
+Skip "old-style" classification on shared blocks, so that the NULL
+dereference is fixed and WARN_ON() is not hit anymore in the short
+lifetime of invalid cls_fw "old-style" filters.
+
+[1] https://sashiko.dev/#/patchset/20260331050217.504278-1-xmei5%40asu.edu
+[2] https://elixir.bootlin.com/linux/v7.0-rc6/source/include/net/pkt_cls.h#L86
+
+Fixes: faeea8bbf6e9 ("net/sched: cls_fw: fix NULL pointer dereference on shared blocks")
+Fixes: ed76f5edccc9 ("net: sched: protect filter_chain list with filter_chain_lock mutex")
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: Davide Caratti <dcaratti@redhat.com>
+Link: https://patch.msgid.link/e39cbd3103a337f1e515d186fe697b4459d24757.1775661704.git.dcaratti@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_fw.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
+index 83a7372ea15c2a..fd9c6c2815a1c2 100644
+--- a/net/sched/cls_fw.c
++++ b/net/sched/cls_fw.c
+@@ -74,9 +74,13 @@ TC_INDIRECT_SCOPE int fw_classify(struct sk_buff *skb,
+ }
+ }
+ } else {
+- struct Qdisc *q = tcf_block_q(tp->chain->block);
++ struct Qdisc *q;
+
+ /* Old method: classify the packet using its skb mark. */
++ if (tcf_block_shared(tp->chain->block))
++ return -1;
++
++ q = tcf_block_q(tp->chain->block);
+ if (id && (TC_H_MAJ(id) == 0 ||
+ !(TC_H_MAJ(id ^ q->handle)))) {
+ res->classid = id;
+--
+2.53.0
+
--- /dev/null
+From aa6d397b43eb8ec02f2bdc53da51b59add84fed0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Apr 2026 11:29:56 -0400
+Subject: net/sched: sch_sfb: Replace direct dequeue call with peek and
+ qdisc_dequeue_peeked
+
+From: Victor Nogueria <victor@mojatatu.com>
+
+[ Upstream commit 1b9bc71153b01dbde8045b9edede4240f4f5520e ]
+
+When sfb has children (eg qfq qdisc) whose peek() callback is
+qdisc_peek_dequeued(), we could get a kernel panic. When the parent of such
+qdiscs (eg illustrated in patch #3 as tbf) wants to retrieve an skb from
+its child (sfb in this case), it will do the following:
+ 1a. do a peek() - and when sensing there's an skb the child can offer, then
+ - the child in this case(sfb) calls its child's (qfq) peek.
+ qfq does the right thing and will return the gso_skb queue packet.
+ Note: if there wasnt a gso_skb entry then qfq will store it there.
+ 1b. invoke a dequeue() on the child (sfb). And herein lies the problem.
+ - sfb will call the child's dequeue() which will essentially just
+ try to grab something of qfq's queue.
+
+[ 127.594489][ T453] KASAN: null-ptr-deref in range [0x0000000000000048-0x000000000000004f]
+[ 127.594741][ T453] CPU: 2 UID: 0 PID: 453 Comm: ping Not tainted 7.1.0-rc1-00035-gac961974495b-dirty #793 PREEMPT(full)
+[ 127.595059][ T453] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+[ 127.595254][ T453] RIP: 0010:qfq_dequeue+0x35c/0x1650 [sch_qfq]
+[ 127.595461][ T453] Code: 00 fc ff df 80 3c 02 00 0f 85 17 0e 00 00 4c 8d 73 48 48 89 9d b8 02 00 00 48 b8 00 00 00 00 00 fc ff df 4c 89 f2 48 c1 ea 03 <80> 3c 02 00 0f 85 76 0c 00 00 48 b8 00 00 00 00 00 fc ff df 4c 8b
+[ 127.596081][ T453] RSP: 0018:ffff88810e5af440 EFLAGS: 00010216
+[ 127.596337][ T453] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: dffffc0000000000
+[ 127.596623][ T453] RDX: 0000000000000009 RSI: 0000001880000000 RDI: ffff888104fd82b0
+[ 127.596917][ T453] RBP: ffff888104fd8000 R08: ffff888104fd8280 R09: 1ffff110211893a3
+[ 127.597165][ T453] R10: 1ffff110211893a6 R11: 1ffff110211893a7 R12: 0000001880000000
+[ 127.597404][ T453] R13: ffff888104fd82b8 R14: 0000000000000048 R15: 0000000040000000
+[ 127.597644][ T453] FS: 00007fc380cbfc40(0000) GS:ffff88816f2a8000(0000) knlGS:0000000000000000
+[ 127.597956][ T453] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 127.598160][ T453] CR2: 00005610aa9890a8 CR3: 000000010369e000 CR4: 0000000000750ef0
+[ 127.598390][ T453] PKRU: 55555554
+[ 127.598509][ T453] Call Trace:
+[ 127.598629][ T453] <TASK>
+[ 127.598718][ T453] ? mark_held_locks+0x40/0x70
+[ 127.598890][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599053][ T453] sfb_dequeue+0x88/0x4d0
+[ 127.599174][ T453] ? ktime_get+0x137/0x230
+[ 127.599328][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599480][ T453] ? qdisc_peek_dequeued+0x7b/0x350 [sch_qfq]
+[ 127.599670][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599831][ T453] tbf_dequeue+0x6b1/0x1098 [sch_tbf]
+[ 127.599988][ T453] __qdisc_run+0x169/0x1900
+
+The right thing to do in #1b is to grab the skb off gso_skb queue.
+This patchset fixes that issue by changing #1b to use qdisc_dequeue_peeked()
+method instead.
+
+Fixes: e13e02a3c68d ("net_sched: SFB flow scheduler")
+Signed-off-by: Victor Nogueria <victor@mojatatu.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260430152957.194015-3-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_sfb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
+index c36725f0870d46..9a2edaf8352adc 100644
+--- a/net/sched/sch_sfb.c
++++ b/net/sched/sch_sfb.c
+@@ -439,7 +439,7 @@ static struct sk_buff *sfb_dequeue(struct Qdisc *sch)
+ struct Qdisc *child = q->qdisc;
+ struct sk_buff *skb;
+
+- skb = child->dequeue(q->qdisc);
++ skb = qdisc_dequeue_peeked(child);
+
+ if (skb) {
+ qdisc_bstats_update(sch, skb);
+--
+2.53.0
+
--- /dev/null
+drm-v3d-fix-use-after-free-of-cpu-job-query-arrays-o.patch
+drm-v3d-release-indirect-csd-gem-reference-on-cpu-jo.patch
+net-sched-cls_fw-fix-null-dereference-of-old-filters.patch
+net-mctp-ensure-our-nlmsg-responses-are-initialised.patch
+xfrm-move-policy_bydst-rcu-sync-from-per-netns-.exit.patch
+net-sched-sch_sfb-replace-direct-dequeue-call-with-p.patch
+bcache-fix-uninitialized-closure-object.patch
+net-cpsw_new-fix-potential-unregister-of-netdev-that.patch
+arm64-introduce-esr_is_ubsan_brk.patch
+arm64-debug-clean-up-single_step_handler-logic.patch
+arm64-refactor-aarch32_break_handler.patch
+arm64-debug-call-software-breakpoint-handlers-static.patch
+arm64-debug-call-step-handlers-statically.patch
+arm64-debug-remove-break-step-handler-registration-i.patch
+arm64-entry-add-entry-and-exit-functions-for-debug-e.patch
+arm64-debug-split-hardware-breakpoint-exception-entr.patch
+arm64-debug-refactor-reinstall_suspended_bps.patch
+arm64-debug-split-single-stepping-exception-entry.patch
+arm64-debug-split-hardware-watchpoint-exception-entr.patch
+arm64-debug-split-brk64-exception-entry.patch
+arm64-debug-split-bkpt32-exception-entry.patch
+arm64-debug-remove-debug-exception-registration-infr.patch
+arm64-debug-always-unmask-interrupts-in-el0_softstp.patch
--- /dev/null
+From 3da1eccc11d9fc9d5eaec90cffe24e5603d30b5e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 03:29:26 -0700
+Subject: xfrm: move policy_bydst RCU sync from per-netns .exit to .pre_exit
+
+From: Usama Arif <usama.arif@linux.dev>
+
+[ Upstream commit 3e52417318473782012b236d0325bf7d2266a597 ]
+
+The struct pernet_operations docstring in include/net/net_namespace.h
+explicitly warns against blocking RCU primitives in .exit handlers:
+
+ Exit methods using blocking RCU primitives, such as
+ synchronize_rcu(), should be implemented via exit_batch.
+ [...]
+ Please, avoid synchronize_rcu() at all, where it's possible.
+
+ Note that a combination of pre_exit() and exit() can
+ be used, since a synchronize_rcu() is guaranteed between
+ the calls.
+
+xfrm_policy_fini() violates this: it calls synchronize_rcu() before
+freeing the policy_bydst hash tables (so no RCU reader is mid-
+traversal at free time), but runs from xfrm_net_ops.exit -- once per
+namespace -- so a cleanup_net() of N namespaces pays N full RCU
+grace periods serially.
+
+Use the documented pre_exit/exit split. Move the policy flush (and
+the workqueue drains it depends on) into a new .pre_exit handler;
+xfrm_policy_fini() then runs in .exit and frees the hash tables
+after the synchronize_rcu_expedited() that cleanup_net() guarantees
+between the two phases. Providing O(1) RCU grace periods per batch
+instead of O(N).
+
+Observed on Linux 6.18 with a workload doing unshare(CLONE_NEWNET)
+at ~13/sec sustained: cleanup_net() and the netns_wq rescuer kthread
+both stuck in xfrm_policy_fini()'s synchronize_rcu(), >300k struct
+net accumulated in the cleanup queue, Percpu in /proc/meminfo climbed
+to 130+ GB on 256-CPU hosts, and memcg OOMs followed. setup_net and
+__put_net counts were balanced, ruling out a refcount leak.
+
+Fixes: 069daad4f2ae ("xfrm: Wait for RCU readers during policy netns exit")
+Signed-off-by: Usama Arif <usama.arif@linux.dev>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_policy.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
+index fca07f8e60749a..863e37d3d7f0f7 100644
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -4264,21 +4264,21 @@ static int __net_init xfrm_policy_init(struct net *net)
+ return -ENOMEM;
+ }
+
+-static void xfrm_policy_fini(struct net *net)
++static void __net_exit xfrm_net_pre_exit(struct net *net)
+ {
+- struct xfrm_pol_inexact_bin *b, *t;
+- unsigned int sz;
+- int dir;
+-
+ disable_work_sync(&net->xfrm.policy_hthresh.work);
+-
+ flush_work(&net->xfrm.policy_hash_work);
+ #ifdef CONFIG_XFRM_SUB_POLICY
+ xfrm_policy_flush(net, XFRM_POLICY_TYPE_SUB, false);
+ #endif
+ xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, false);
++}
+
+- synchronize_rcu();
++static void xfrm_policy_fini(struct net *net)
++{
++ struct xfrm_pol_inexact_bin *b, *t;
++ unsigned int sz;
++ int dir;
+
+ WARN_ON(!list_empty(&net->xfrm.policy_all));
+
+@@ -4356,6 +4356,7 @@ static void __net_exit xfrm_net_exit(struct net *net)
+
+ static struct pernet_operations __net_initdata xfrm_net_ops = {
+ .init = xfrm_net_init,
++ .pre_exit = xfrm_net_pre_exit,
+ .exit = xfrm_net_exit,
+ };
+
+--
+2.53.0
+
--- /dev/null
+From 2ec0dc826a72242ecdea8d0ec183a6684d00e40a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Apr 2026 12:21:35 +0800
+Subject: bcache: fix uninitialized closure object
+
+From: Mingzhe Zou <mingzhe.zou@easystack.cn>
+
+[ Upstream commit 20a8e451ec1c7e99060b1bbaaad03ce88c39ddb8 ]
+
+In the previous patch ("bcache: fix cached_dev.sb_bio use-after-free and
+crash"), we adopted a simple modification suggestion from AI to fix the
+use-after-free.
+
+But in actual testing, we found an extreme case where the device is
+stopped before calling bch_write_bdev_super().
+
+At this point, struct closure sb_write has not been initialized yet.
+For this patch, we ensure that sb_bio has been completed via
+sb_write_mutex.
+
+Signed-off-by: Mingzhe Zou <mingzhe.zou@easystack.cn>
+Signed-off-by: Coly Li <colyli@fnnas.com>
+Link: https://patch.msgid.link/20260403042135.2221247-1-colyli@fnnas.com
+Fixes: fec114a98b87 ("bcache: fix cached_dev.sb_bio use-after-free and crash")
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/bcache/super.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
+index 2f06945533d673..d4ebd13a59f820 100644
+--- a/drivers/md/bcache/super.c
++++ b/drivers/md/bcache/super.c
+@@ -1378,7 +1378,8 @@ static CLOSURE_CALLBACK(cached_dev_free)
+ * The sb_bio is embedded in struct cached_dev, so we must
+ * ensure no I/O is in progress.
+ */
+- closure_sync(&dc->sb_write);
++ down(&dc->sb_write_mutex);
++ up(&dc->sb_write_mutex);
+
+ if (dc->sb_disk)
+ folio_put(virt_to_folio(dc->sb_disk));
+--
+2.53.0
+
--- /dev/null
+From 653831a4cbf606d60c0f3e59418189975074a464 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 15:34:28 +0800
+Subject: net: mctp: ensure our nlmsg responses are initialised
+
+From: Jeremy Kerr <jk@codeconstruct.com.au>
+
+[ Upstream commit a6a9bc544b675d8b5180f2718ec985ad267b5cbf ]
+
+Syed Faraz Abrar (@farazsth98) from Zellic, and Pumpkin (@u1f383) from
+DEVCORE Research Team working with Trend Micro Zero Day Initiative
+report that a RTM_GETNEIGH will return uninitalised data in the pad
+bytes of the ndmsg data.
+
+Ensure we're initialising the netlink data to zero, in the link, addr
+and neigh response messages.
+
+Fixes: 831119f88781 ("mctp: Add neighbour netlink interface")
+Fixes: 06d2f4c583a7 ("mctp: Add netlink route management")
+Fixes: 583be982d934 ("mctp: Add device handling and netlink interface")
+Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260209-dev-mctp-nlmsg-v1-1-f1e30c346a43@codeconstruct.com.au
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Li hongliang <1468888505@139.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mctp/device.c | 1 +
+ net/mctp/neigh.c | 1 +
+ net/mctp/route.c | 1 +
+ 3 files changed, 3 insertions(+)
+
+diff --git a/net/mctp/device.c b/net/mctp/device.c
+index 4d404edd7446e1..04c5570bacff69 100644
+--- a/net/mctp/device.c
++++ b/net/mctp/device.c
+@@ -70,6 +70,7 @@ static int mctp_fill_addrinfo(struct sk_buff *skb,
+ return -EMSGSIZE;
+
+ hdr = nlmsg_data(nlh);
++ memset(hdr, 0, sizeof(*hdr));
+ hdr->ifa_family = AF_MCTP;
+ hdr->ifa_prefixlen = 0;
+ hdr->ifa_flags = 0;
+diff --git a/net/mctp/neigh.c b/net/mctp/neigh.c
+index 05b899f22d902b..fc85f0e6930143 100644
+--- a/net/mctp/neigh.c
++++ b/net/mctp/neigh.c
+@@ -218,6 +218,7 @@ static int mctp_fill_neigh(struct sk_buff *skb, u32 portid, u32 seq, int event,
+ return -EMSGSIZE;
+
+ hdr = nlmsg_data(nlh);
++ memset(hdr, 0, sizeof(*hdr));
+ hdr->ndm_family = AF_MCTP;
+ hdr->ndm_ifindex = dev->ifindex;
+ hdr->ndm_state = 0; // TODO other state bits?
+diff --git a/net/mctp/route.c b/net/mctp/route.c
+index d4fdaac8037aba..eb817f1eb5c8eb 100644
+--- a/net/mctp/route.c
++++ b/net/mctp/route.c
+@@ -1650,6 +1650,7 @@ static int mctp_fill_rtinfo(struct sk_buff *skb, struct mctp_route *rt,
+ return -EMSGSIZE;
+
+ hdr = nlmsg_data(nlh);
++ memset(hdr, 0, sizeof(*hdr));
+ hdr->rtm_family = AF_MCTP;
+
+ /* we use the _len fields as a number of EIDs, rather than
+--
+2.53.0
+
--- /dev/null
+From f0db3e191c173b5275d4245a60ef47188965a717 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Apr 2026 17:24:36 +0200
+Subject: net/sched: cls_fw: fix NULL dereference of "old" filters before
+ change()
+
+From: Davide Caratti <dcaratti@redhat.com>
+
+[ Upstream commit 65782b2db7321d5f97c16718c4c7f6c7205a56be ]
+
+Like pointed out by Sashiko [1], since commit ed76f5edccc9 ("net: sched:
+protect filter_chain list with filter_chain_lock mutex") TC filters are
+added to a shared block and published to datapath before their ->change()
+function is called. This is a problem for cls_fw: an invalid filter
+created with the "old" method can still classify some packets before it
+is destroyed by the validation logic added by Xiang.
+Therefore, insisting with repeated runs of the following script:
+
+ # ip link add dev crash0 type dummy
+ # ip link set dev crash0 up
+ # mausezahn crash0 -c 100000 -P 10 \
+ > -A 4.3.2.1 -B 1.2.3.4 -t udp "dp=1234" -q &
+ # sleep 1
+ # tc qdisc add dev crash0 egress_block 1 clsact
+ # tc filter add block 1 protocol ip prio 1 matchall \
+ > action skbedit mark 65536 continue
+ # tc filter add block 1 protocol ip prio 2 fw
+ # ip link del dev crash0
+
+can still make fw_classify() hit the WARN_ON() in [2]:
+
+ WARNING: ./include/net/pkt_cls.h:88 at fw_classify+0x244/0x250 [cls_fw], CPU#18: mausezahn/1399
+ Modules linked in: cls_fw(E) act_skbedit(E)
+ CPU: 18 UID: 0 PID: 1399 Comm: mausezahn Tainted: G E 7.0.0-rc6-virtme #17 PREEMPT(full)
+ Tainted: [E]=UNSIGNED_MODULE
+ Hardware name: Red Hat KVM, BIOS 1.16.3-2.el9 04/01/2014
+ RIP: 0010:fw_classify+0x244/0x250 [cls_fw]
+ Code: 5c 49 c7 45 00 00 00 00 00 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 5b b8 ff ff ff ff 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 90 <0f> 0b 90 eb a0 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90
+ RSP: 0018:ffffd1b7026bf8a8 EFLAGS: 00010202
+ RAX: ffff8c5ac9c60800 RBX: ffff8c5ac99322c0 RCX: 0000000000000004
+ RDX: 0000000000000001 RSI: ffff8c5b74d7a000 RDI: ffff8c5ac8284f40
+ RBP: ffffd1b7026bf8d0 R08: 0000000000000000 R09: ffffd1b7026bf9b0
+ R10: 00000000ffffffff R11: 0000000000000000 R12: 0000000000010000
+ R13: ffffd1b7026bf930 R14: ffff8c5ac8284f40 R15: 0000000000000000
+ FS: 00007fca40c37740(0000) GS:ffff8c5b74d7a000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 00007fca40e822a0 CR3: 0000000005ca0001 CR4: 0000000000172ef0
+ Call Trace:
+ <TASK>
+ tcf_classify+0x17d/0x5c0
+ tc_run+0x9d/0x150
+ __dev_queue_xmit+0x2ab/0x14d0
+ ip_finish_output2+0x340/0x8f0
+ ip_output+0xa4/0x250
+ raw_sendmsg+0x147d/0x14b0
+ __sys_sendto+0x1cc/0x1f0
+ __x64_sys_sendto+0x24/0x30
+ do_syscall_64+0x126/0xf80
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+ RIP: 0033:0x7fca40e822ba
+ Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb b8 0f 1f 00 f3 0f 1e fa 41 89 ca 64 8b 04 25 18 00 00 00 85 c0 75 15 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 7e c3 0f 1f 44 00 00 41 54 48 83 ec 30 44 89
+ RSP: 002b:00007ffc248a42c8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
+ RAX: ffffffffffffffda RBX: 000055ef233289d0 RCX: 00007fca40e822ba
+ RDX: 000000000000001e RSI: 000055ef23328c30 RDI: 0000000000000003
+ RBP: 000055ef233289d0 R08: 00007ffc248a42d0 R09: 0000000000000010
+ R10: 0000000000000000 R11: 0000000000000246 R12: 000000000000001e
+ R13: 00000000000186a0 R14: 0000000000000000 R15: 00007fca41043000
+ </TASK>
+ irq event stamp: 1045778
+ hardirqs last enabled at (1045784): [<ffffffff864ec042>] __up_console_sem+0x52/0x60
+ hardirqs last disabled at (1045789): [<ffffffff864ec027>] __up_console_sem+0x37/0x60
+ softirqs last enabled at (1045426): [<ffffffff874d48c7>] __alloc_skb+0x207/0x260
+ softirqs last disabled at (1045434): [<ffffffff874fe8f8>] __dev_queue_xmit+0x78/0x14d0
+
+Then, because of the value in the packet's mark, dereference on 'q->handle'
+with NULL 'q' occurs:
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000038
+ [...]
+ RIP: 0010:fw_classify+0x1fe/0x250 [cls_fw]
+ [...]
+
+Skip "old-style" classification on shared blocks, so that the NULL
+dereference is fixed and WARN_ON() is not hit anymore in the short
+lifetime of invalid cls_fw "old-style" filters.
+
+[1] https://sashiko.dev/#/patchset/20260331050217.504278-1-xmei5%40asu.edu
+[2] https://elixir.bootlin.com/linux/v7.0-rc6/source/include/net/pkt_cls.h#L86
+
+Fixes: faeea8bbf6e9 ("net/sched: cls_fw: fix NULL pointer dereference on shared blocks")
+Fixes: ed76f5edccc9 ("net: sched: protect filter_chain list with filter_chain_lock mutex")
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: Davide Caratti <dcaratti@redhat.com>
+Link: https://patch.msgid.link/e39cbd3103a337f1e515d186fe697b4459d24757.1775661704.git.dcaratti@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_fw.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
+index 83a7372ea15c2a..fd9c6c2815a1c2 100644
+--- a/net/sched/cls_fw.c
++++ b/net/sched/cls_fw.c
+@@ -74,9 +74,13 @@ TC_INDIRECT_SCOPE int fw_classify(struct sk_buff *skb,
+ }
+ }
+ } else {
+- struct Qdisc *q = tcf_block_q(tp->chain->block);
++ struct Qdisc *q;
+
+ /* Old method: classify the packet using its skb mark. */
++ if (tcf_block_shared(tp->chain->block))
++ return -1;
++
++ q = tcf_block_q(tp->chain->block);
+ if (id && (TC_H_MAJ(id) == 0 ||
+ !(TC_H_MAJ(id ^ q->handle)))) {
+ res->classid = id;
+--
+2.53.0
+
--- /dev/null
+From a15b332e17f6bb7b34e8929ff451e86ed4710d3b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Apr 2026 11:29:56 -0400
+Subject: net/sched: sch_sfb: Replace direct dequeue call with peek and
+ qdisc_dequeue_peeked
+
+From: Victor Nogueria <victor@mojatatu.com>
+
+[ Upstream commit 1b9bc71153b01dbde8045b9edede4240f4f5520e ]
+
+When sfb has children (eg qfq qdisc) whose peek() callback is
+qdisc_peek_dequeued(), we could get a kernel panic. When the parent of such
+qdiscs (eg illustrated in patch #3 as tbf) wants to retrieve an skb from
+its child (sfb in this case), it will do the following:
+ 1a. do a peek() - and when sensing there's an skb the child can offer, then
+ - the child in this case(sfb) calls its child's (qfq) peek.
+ qfq does the right thing and will return the gso_skb queue packet.
+ Note: if there wasnt a gso_skb entry then qfq will store it there.
+ 1b. invoke a dequeue() on the child (sfb). And herein lies the problem.
+ - sfb will call the child's dequeue() which will essentially just
+ try to grab something of qfq's queue.
+
+[ 127.594489][ T453] KASAN: null-ptr-deref in range [0x0000000000000048-0x000000000000004f]
+[ 127.594741][ T453] CPU: 2 UID: 0 PID: 453 Comm: ping Not tainted 7.1.0-rc1-00035-gac961974495b-dirty #793 PREEMPT(full)
+[ 127.595059][ T453] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+[ 127.595254][ T453] RIP: 0010:qfq_dequeue+0x35c/0x1650 [sch_qfq]
+[ 127.595461][ T453] Code: 00 fc ff df 80 3c 02 00 0f 85 17 0e 00 00 4c 8d 73 48 48 89 9d b8 02 00 00 48 b8 00 00 00 00 00 fc ff df 4c 89 f2 48 c1 ea 03 <80> 3c 02 00 0f 85 76 0c 00 00 48 b8 00 00 00 00 00 fc ff df 4c 8b
+[ 127.596081][ T453] RSP: 0018:ffff88810e5af440 EFLAGS: 00010216
+[ 127.596337][ T453] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: dffffc0000000000
+[ 127.596623][ T453] RDX: 0000000000000009 RSI: 0000001880000000 RDI: ffff888104fd82b0
+[ 127.596917][ T453] RBP: ffff888104fd8000 R08: ffff888104fd8280 R09: 1ffff110211893a3
+[ 127.597165][ T453] R10: 1ffff110211893a6 R11: 1ffff110211893a7 R12: 0000001880000000
+[ 127.597404][ T453] R13: ffff888104fd82b8 R14: 0000000000000048 R15: 0000000040000000
+[ 127.597644][ T453] FS: 00007fc380cbfc40(0000) GS:ffff88816f2a8000(0000) knlGS:0000000000000000
+[ 127.597956][ T453] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 127.598160][ T453] CR2: 00005610aa9890a8 CR3: 000000010369e000 CR4: 0000000000750ef0
+[ 127.598390][ T453] PKRU: 55555554
+[ 127.598509][ T453] Call Trace:
+[ 127.598629][ T453] <TASK>
+[ 127.598718][ T453] ? mark_held_locks+0x40/0x70
+[ 127.598890][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599053][ T453] sfb_dequeue+0x88/0x4d0
+[ 127.599174][ T453] ? ktime_get+0x137/0x230
+[ 127.599328][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599480][ T453] ? qdisc_peek_dequeued+0x7b/0x350 [sch_qfq]
+[ 127.599670][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599831][ T453] tbf_dequeue+0x6b1/0x1098 [sch_tbf]
+[ 127.599988][ T453] __qdisc_run+0x169/0x1900
+
+The right thing to do in #1b is to grab the skb off gso_skb queue.
+This patchset fixes that issue by changing #1b to use qdisc_dequeue_peeked()
+method instead.
+
+Fixes: e13e02a3c68d ("net_sched: SFB flow scheduler")
+Signed-off-by: Victor Nogueria <victor@mojatatu.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260430152957.194015-3-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_sfb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
+index 00286c930b8de7..14ac8897784757 100644
+--- a/net/sched/sch_sfb.c
++++ b/net/sched/sch_sfb.c
+@@ -441,7 +441,7 @@ static struct sk_buff *sfb_dequeue(struct Qdisc *sch)
+ struct Qdisc *child = q->qdisc;
+ struct sk_buff *skb;
+
+- skb = child->dequeue(q->qdisc);
++ skb = qdisc_dequeue_peeked(child);
+
+ if (skb) {
+ qdisc_bstats_update(sch, skb);
+--
+2.53.0
+
--- /dev/null
+net-sched-cls_fw-fix-null-dereference-of-old-filters.patch
+net-mctp-ensure-our-nlmsg-responses-are-initialised.patch
+xfrm-move-policy_bydst-rcu-sync-from-per-netns-.exit.patch
+net-sched-sch_sfb-replace-direct-dequeue-call-with-p.patch
+bcache-fix-uninitialized-closure-object.patch
--- /dev/null
+From fd4ed4eb53969b3f249dfaedd05b0edb148902e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 03:29:26 -0700
+Subject: xfrm: move policy_bydst RCU sync from per-netns .exit to .pre_exit
+
+From: Usama Arif <usama.arif@linux.dev>
+
+[ Upstream commit 3e52417318473782012b236d0325bf7d2266a597 ]
+
+The struct pernet_operations docstring in include/net/net_namespace.h
+explicitly warns against blocking RCU primitives in .exit handlers:
+
+ Exit methods using blocking RCU primitives, such as
+ synchronize_rcu(), should be implemented via exit_batch.
+ [...]
+ Please, avoid synchronize_rcu() at all, where it's possible.
+
+ Note that a combination of pre_exit() and exit() can
+ be used, since a synchronize_rcu() is guaranteed between
+ the calls.
+
+xfrm_policy_fini() violates this: it calls synchronize_rcu() before
+freeing the policy_bydst hash tables (so no RCU reader is mid-
+traversal at free time), but runs from xfrm_net_ops.exit -- once per
+namespace -- so a cleanup_net() of N namespaces pays N full RCU
+grace periods serially.
+
+Use the documented pre_exit/exit split. Move the policy flush (and
+the workqueue drains it depends on) into a new .pre_exit handler;
+xfrm_policy_fini() then runs in .exit and frees the hash tables
+after the synchronize_rcu_expedited() that cleanup_net() guarantees
+between the two phases. Providing O(1) RCU grace periods per batch
+instead of O(N).
+
+Observed on Linux 6.18 with a workload doing unshare(CLONE_NEWNET)
+at ~13/sec sustained: cleanup_net() and the netns_wq rescuer kthread
+both stuck in xfrm_policy_fini()'s synchronize_rcu(), >300k struct
+net accumulated in the cleanup queue, Percpu in /proc/meminfo climbed
+to 130+ GB on 256-CPU hosts, and memcg OOMs followed. setup_net and
+__put_net counts were balanced, ruling out a refcount leak.
+
+Fixes: 069daad4f2ae ("xfrm: Wait for RCU readers during policy netns exit")
+Signed-off-by: Usama Arif <usama.arif@linux.dev>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_policy.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
+index 29c94ee0ceb256..96e9262c4b482a 100644
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -4276,21 +4276,21 @@ static int __net_init xfrm_policy_init(struct net *net)
+ return -ENOMEM;
+ }
+
+-static void xfrm_policy_fini(struct net *net)
++static void __net_exit xfrm_net_pre_exit(struct net *net)
+ {
+- struct xfrm_pol_inexact_bin *b, *t;
+- unsigned int sz;
+- int dir;
+-
+ disable_work_sync(&net->xfrm.policy_hthresh.work);
+-
+ flush_work(&net->xfrm.policy_hash_work);
+ #ifdef CONFIG_XFRM_SUB_POLICY
+ xfrm_policy_flush(net, XFRM_POLICY_TYPE_SUB, false);
+ #endif
+ xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, false);
++}
+
+- synchronize_rcu();
++static void xfrm_policy_fini(struct net *net)
++{
++ struct xfrm_pol_inexact_bin *b, *t;
++ unsigned int sz;
++ int dir;
+
+ WARN_ON(!list_empty(&net->xfrm.policy_all));
+
+@@ -4368,6 +4368,7 @@ static void __net_exit xfrm_net_exit(struct net *net)
+
+ static struct pernet_operations __net_initdata xfrm_net_ops = {
+ .init = xfrm_net_init,
++ .pre_exit = xfrm_net_pre_exit,
+ .exit = xfrm_net_exit,
+ };
+
+--
+2.53.0
+
--- /dev/null
+From ec99f33265443be31ab13be1e1ed366b65a77613 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Apr 2026 12:21:35 +0800
+Subject: bcache: fix uninitialized closure object
+
+From: Mingzhe Zou <mingzhe.zou@easystack.cn>
+
+[ Upstream commit 20a8e451ec1c7e99060b1bbaaad03ce88c39ddb8 ]
+
+In the previous patch ("bcache: fix cached_dev.sb_bio use-after-free and
+crash"), we adopted a simple modification suggestion from AI to fix the
+use-after-free.
+
+But in actual testing, we found an extreme case where the device is
+stopped before calling bch_write_bdev_super().
+
+At this point, struct closure sb_write has not been initialized yet.
+For this patch, we ensure that sb_bio has been completed via
+sb_write_mutex.
+
+Signed-off-by: Mingzhe Zou <mingzhe.zou@easystack.cn>
+Signed-off-by: Coly Li <colyli@fnnas.com>
+Link: https://patch.msgid.link/20260403042135.2221247-1-colyli@fnnas.com
+Fixes: fec114a98b87 ("bcache: fix cached_dev.sb_bio use-after-free and crash")
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/bcache/super.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
+index a66423cf12d0a7..6d9349f6f8fd75 100644
+--- a/drivers/md/bcache/super.c
++++ b/drivers/md/bcache/super.c
+@@ -1372,7 +1372,8 @@ static void cached_dev_free(struct closure *cl)
+ * The sb_bio is embedded in struct cached_dev, so we must
+ * ensure no I/O is in progress.
+ */
+- closure_sync(&dc->sb_write);
++ down(&dc->sb_write_mutex);
++ up(&dc->sb_write_mutex);
+
+ if (dc->sb_disk)
+ put_page(virt_to_page(dc->sb_disk));
+--
+2.53.0
+
--- /dev/null
+From 6c80855c9061b4952f412d43f319cfb70b0a909f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Sep 2023 11:15:18 -0300
+Subject: drm: Remove plane hsub/vsub alignment requirement for core helpers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Carlos Eduardo Gallo Filho <gcarlos@disroot.org>
+
+[ Upstream commit f2f455981a34ce8ca88a41458c09494b387d344f ]
+
+The drm_format_info_plane_{height,width} functions was implemented using
+regular division for the plane size calculation, which cause issues [1][2]
+when used on contexts where the dimensions are misaligned with relation
+to the subsampling factors. So, replace the regular division by the
+DIV_ROUND_UP macro.
+
+This allows these functions to be used in more drivers, making further
+work to bring more core presence on them possible.
+
+[1] http://patchwork.freedesktop.org/patch/msgid/20170321181218.10042-3-ville.syrjala@linux.intel.com
+[2] https://patchwork.freedesktop.org/patch/msgid/20211026225105.2783797-2-imre.deak@intel.com
+
+Signed-off-by: Carlos Eduardo Gallo Filho <gcarlos@disroot.org>
+Reviewed-by: André Almeida <andrealmeid@igalia.com>
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230926141519.9315-2-gcarlos@disroot.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/drm/drm_fourcc.h | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
+index 532ae78ca747e6..ccf91daa430702 100644
+--- a/include/drm/drm_fourcc.h
++++ b/include/drm/drm_fourcc.h
+@@ -22,6 +22,7 @@
+ #ifndef __DRM_FOURCC_H__
+ #define __DRM_FOURCC_H__
+
++#include <linux/math.h>
+ #include <linux/types.h>
+ #include <uapi/drm/drm_fourcc.h>
+
+@@ -279,7 +280,7 @@ int drm_format_info_plane_width(const struct drm_format_info *info, int width,
+ if (plane == 0)
+ return width;
+
+- return width / info->hsub;
++ return DIV_ROUND_UP(width, info->hsub);
+ }
+
+ /**
+@@ -301,7 +302,7 @@ int drm_format_info_plane_height(const struct drm_format_info *info, int height,
+ if (plane == 0)
+ return height;
+
+- return height / info->vsub;
++ return DIV_ROUND_UP(height, info->vsub);
+ }
+
+ const struct drm_format_info *__drm_format_info(u32 format);
+--
+2.53.0
+
--- /dev/null
+From deff77ef684f0c438cf436e8d1a4b7b39215154d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2026 15:37:35 +0800
+Subject: net: cpsw_new: Fix potential unregister of netdev that has not been
+ registered yet
+
+From: Kevin Hao <haokexin@gmail.com>
+
+[ Upstream commit 9d724b34fbe13b71865ad0906a4be97571f19cf5 ]
+
+If an error occurs during register_netdev() for the first MAC in
+cpsw_register_ports(), even though cpsw->slaves[0].ndev is set to NULL,
+cpsw->slaves[1].ndev would remain unchanged. This could later cause
+cpsw_unregister_ports() to attempt unregistering the second MAC.
+To address this, add a check for ndev->reg_state before calling
+unregister_netdev(). With this change, setting cpsw->slaves[i].ndev
+to NULL becomes unnecessary and can be removed accordingly.
+
+Fixes: ed3525eda4c4 ("net: ethernet: ti: introduce cpsw switchdev based driver part 1 - dual-emac")
+Signed-off-by: Kevin Hao <haokexin@gmail.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
+Link: https://patch.msgid.link/20260205-cpsw-error-path-v1-2-6e58bae6b299@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Wenshan Lan <jetlan9@163.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ti/cpsw_new.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
+index 1f98044b3666ff..64f527ba9a4746 100644
+--- a/drivers/net/ethernet/ti/cpsw_new.c
++++ b/drivers/net/ethernet/ti/cpsw_new.c
+@@ -1442,7 +1442,8 @@ static void cpsw_unregister_ports(struct cpsw_common *cpsw)
+ int i = 0;
+
+ for (i = 0; i < cpsw->data.slaves; i++) {
+- if (!cpsw->slaves[i].ndev)
++ if (!cpsw->slaves[i].ndev ||
++ cpsw->slaves[i].ndev->reg_state != NETREG_REGISTERED)
+ continue;
+
+ unregister_netdev(cpsw->slaves[i].ndev);
+@@ -1462,7 +1463,6 @@ static int cpsw_register_ports(struct cpsw_common *cpsw)
+ if (ret) {
+ dev_err(cpsw->dev,
+ "cpsw: err registering net device%d\n", i);
+- cpsw->slaves[i].ndev = NULL;
+ break;
+ }
+ }
+--
+2.53.0
+
--- /dev/null
+From 1e2b2fd93ff3e8dc619a04c0e3b71938b52641c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jun 2026 15:36:17 +0800
+Subject: net: mctp: ensure our nlmsg responses are initialised
+
+From: Jeremy Kerr <jk@codeconstruct.com.au>
+
+[ Upstream commit a6a9bc544b675d8b5180f2718ec985ad267b5cbf ]
+
+Syed Faraz Abrar (@farazsth98) from Zellic, and Pumpkin (@u1f383) from
+DEVCORE Research Team working with Trend Micro Zero Day Initiative
+report that a RTM_GETNEIGH will return uninitalised data in the pad
+bytes of the ndmsg data.
+
+Ensure we're initialising the netlink data to zero, in the link, addr
+and neigh response messages.
+
+Fixes: 831119f88781 ("mctp: Add neighbour netlink interface")
+Fixes: 06d2f4c583a7 ("mctp: Add netlink route management")
+Fixes: 583be982d934 ("mctp: Add device handling and netlink interface")
+Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260209-dev-mctp-nlmsg-v1-1-f1e30c346a43@codeconstruct.com.au
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Li hongliang <1468888505@139.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mctp/device.c | 1 +
+ net/mctp/neigh.c | 1 +
+ net/mctp/route.c | 1 +
+ 3 files changed, 3 insertions(+)
+
+diff --git a/net/mctp/device.c b/net/mctp/device.c
+index 8d1386601bbe06..67576cb2728ece 100644
+--- a/net/mctp/device.c
++++ b/net/mctp/device.c
+@@ -70,6 +70,7 @@ static int mctp_fill_addrinfo(struct sk_buff *skb,
+ return -EMSGSIZE;
+
+ hdr = nlmsg_data(nlh);
++ memset(hdr, 0, sizeof(*hdr));
+ hdr->ifa_family = AF_MCTP;
+ hdr->ifa_prefixlen = 0;
+ hdr->ifa_flags = 0;
+diff --git a/net/mctp/neigh.c b/net/mctp/neigh.c
+index 590f642413e4ef..c0151a69d2b7c2 100644
+--- a/net/mctp/neigh.c
++++ b/net/mctp/neigh.c
+@@ -218,6 +218,7 @@ static int mctp_fill_neigh(struct sk_buff *skb, u32 portid, u32 seq, int event,
+ return -EMSGSIZE;
+
+ hdr = nlmsg_data(nlh);
++ memset(hdr, 0, sizeof(*hdr));
+ hdr->ndm_family = AF_MCTP;
+ hdr->ndm_ifindex = dev->ifindex;
+ hdr->ndm_state = 0; // TODO other state bits?
+diff --git a/net/mctp/route.c b/net/mctp/route.c
+index a565cf2bc7330d..6d6e19c049396f 100644
+--- a/net/mctp/route.c
++++ b/net/mctp/route.c
+@@ -1332,6 +1332,7 @@ static int mctp_fill_rtinfo(struct sk_buff *skb, struct mctp_route *rt,
+ return -EMSGSIZE;
+
+ hdr = nlmsg_data(nlh);
++ memset(hdr, 0, sizeof(*hdr));
+ hdr->rtm_family = AF_MCTP;
+
+ /* we use the _len fields as a number of EIDs, rather than
+--
+2.53.0
+
--- /dev/null
+From c00564a7545ef50b432c28721bc42e3e244be12b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Apr 2026 17:24:36 +0200
+Subject: net/sched: cls_fw: fix NULL dereference of "old" filters before
+ change()
+
+From: Davide Caratti <dcaratti@redhat.com>
+
+[ Upstream commit 65782b2db7321d5f97c16718c4c7f6c7205a56be ]
+
+Like pointed out by Sashiko [1], since commit ed76f5edccc9 ("net: sched:
+protect filter_chain list with filter_chain_lock mutex") TC filters are
+added to a shared block and published to datapath before their ->change()
+function is called. This is a problem for cls_fw: an invalid filter
+created with the "old" method can still classify some packets before it
+is destroyed by the validation logic added by Xiang.
+Therefore, insisting with repeated runs of the following script:
+
+ # ip link add dev crash0 type dummy
+ # ip link set dev crash0 up
+ # mausezahn crash0 -c 100000 -P 10 \
+ > -A 4.3.2.1 -B 1.2.3.4 -t udp "dp=1234" -q &
+ # sleep 1
+ # tc qdisc add dev crash0 egress_block 1 clsact
+ # tc filter add block 1 protocol ip prio 1 matchall \
+ > action skbedit mark 65536 continue
+ # tc filter add block 1 protocol ip prio 2 fw
+ # ip link del dev crash0
+
+can still make fw_classify() hit the WARN_ON() in [2]:
+
+ WARNING: ./include/net/pkt_cls.h:88 at fw_classify+0x244/0x250 [cls_fw], CPU#18: mausezahn/1399
+ Modules linked in: cls_fw(E) act_skbedit(E)
+ CPU: 18 UID: 0 PID: 1399 Comm: mausezahn Tainted: G E 7.0.0-rc6-virtme #17 PREEMPT(full)
+ Tainted: [E]=UNSIGNED_MODULE
+ Hardware name: Red Hat KVM, BIOS 1.16.3-2.el9 04/01/2014
+ RIP: 0010:fw_classify+0x244/0x250 [cls_fw]
+ Code: 5c 49 c7 45 00 00 00 00 00 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 5b b8 ff ff ff ff 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 90 <0f> 0b 90 eb a0 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90
+ RSP: 0018:ffffd1b7026bf8a8 EFLAGS: 00010202
+ RAX: ffff8c5ac9c60800 RBX: ffff8c5ac99322c0 RCX: 0000000000000004
+ RDX: 0000000000000001 RSI: ffff8c5b74d7a000 RDI: ffff8c5ac8284f40
+ RBP: ffffd1b7026bf8d0 R08: 0000000000000000 R09: ffffd1b7026bf9b0
+ R10: 00000000ffffffff R11: 0000000000000000 R12: 0000000000010000
+ R13: ffffd1b7026bf930 R14: ffff8c5ac8284f40 R15: 0000000000000000
+ FS: 00007fca40c37740(0000) GS:ffff8c5b74d7a000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 00007fca40e822a0 CR3: 0000000005ca0001 CR4: 0000000000172ef0
+ Call Trace:
+ <TASK>
+ tcf_classify+0x17d/0x5c0
+ tc_run+0x9d/0x150
+ __dev_queue_xmit+0x2ab/0x14d0
+ ip_finish_output2+0x340/0x8f0
+ ip_output+0xa4/0x250
+ raw_sendmsg+0x147d/0x14b0
+ __sys_sendto+0x1cc/0x1f0
+ __x64_sys_sendto+0x24/0x30
+ do_syscall_64+0x126/0xf80
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+ RIP: 0033:0x7fca40e822ba
+ Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb b8 0f 1f 00 f3 0f 1e fa 41 89 ca 64 8b 04 25 18 00 00 00 85 c0 75 15 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 7e c3 0f 1f 44 00 00 41 54 48 83 ec 30 44 89
+ RSP: 002b:00007ffc248a42c8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
+ RAX: ffffffffffffffda RBX: 000055ef233289d0 RCX: 00007fca40e822ba
+ RDX: 000000000000001e RSI: 000055ef23328c30 RDI: 0000000000000003
+ RBP: 000055ef233289d0 R08: 00007ffc248a42d0 R09: 0000000000000010
+ R10: 0000000000000000 R11: 0000000000000246 R12: 000000000000001e
+ R13: 00000000000186a0 R14: 0000000000000000 R15: 00007fca41043000
+ </TASK>
+ irq event stamp: 1045778
+ hardirqs last enabled at (1045784): [<ffffffff864ec042>] __up_console_sem+0x52/0x60
+ hardirqs last disabled at (1045789): [<ffffffff864ec027>] __up_console_sem+0x37/0x60
+ softirqs last enabled at (1045426): [<ffffffff874d48c7>] __alloc_skb+0x207/0x260
+ softirqs last disabled at (1045434): [<ffffffff874fe8f8>] __dev_queue_xmit+0x78/0x14d0
+
+Then, because of the value in the packet's mark, dereference on 'q->handle'
+with NULL 'q' occurs:
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000038
+ [...]
+ RIP: 0010:fw_classify+0x1fe/0x250 [cls_fw]
+ [...]
+
+Skip "old-style" classification on shared blocks, so that the NULL
+dereference is fixed and WARN_ON() is not hit anymore in the short
+lifetime of invalid cls_fw "old-style" filters.
+
+[1] https://sashiko.dev/#/patchset/20260331050217.504278-1-xmei5%40asu.edu
+[2] https://elixir.bootlin.com/linux/v7.0-rc6/source/include/net/pkt_cls.h#L86
+
+Fixes: faeea8bbf6e9 ("net/sched: cls_fw: fix NULL pointer dereference on shared blocks")
+Fixes: ed76f5edccc9 ("net: sched: protect filter_chain list with filter_chain_lock mutex")
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: Davide Caratti <dcaratti@redhat.com>
+Link: https://patch.msgid.link/e39cbd3103a337f1e515d186fe697b4459d24757.1775661704.git.dcaratti@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_fw.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
+index 2e5e8df5ca55c4..bc007bb47432cd 100644
+--- a/net/sched/cls_fw.c
++++ b/net/sched/cls_fw.c
+@@ -74,9 +74,13 @@ TC_INDIRECT_SCOPE int fw_classify(struct sk_buff *skb,
+ }
+ }
+ } else {
+- struct Qdisc *q = tcf_block_q(tp->chain->block);
++ struct Qdisc *q;
+
+ /* Old method: classify the packet using its skb mark. */
++ if (tcf_block_shared(tp->chain->block))
++ return -1;
++
++ q = tcf_block_q(tp->chain->block);
+ if (id && (TC_H_MAJ(id) == 0 ||
+ !(TC_H_MAJ(id ^ q->handle)))) {
+ res->classid = id;
+--
+2.53.0
+
--- /dev/null
+From d4332c82eeae899732d2c35fe84130bfd2f1c093 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Apr 2026 11:29:56 -0400
+Subject: net/sched: sch_sfb: Replace direct dequeue call with peek and
+ qdisc_dequeue_peeked
+
+From: Victor Nogueria <victor@mojatatu.com>
+
+[ Upstream commit 1b9bc71153b01dbde8045b9edede4240f4f5520e ]
+
+When sfb has children (eg qfq qdisc) whose peek() callback is
+qdisc_peek_dequeued(), we could get a kernel panic. When the parent of such
+qdiscs (eg illustrated in patch #3 as tbf) wants to retrieve an skb from
+its child (sfb in this case), it will do the following:
+ 1a. do a peek() - and when sensing there's an skb the child can offer, then
+ - the child in this case(sfb) calls its child's (qfq) peek.
+ qfq does the right thing and will return the gso_skb queue packet.
+ Note: if there wasnt a gso_skb entry then qfq will store it there.
+ 1b. invoke a dequeue() on the child (sfb). And herein lies the problem.
+ - sfb will call the child's dequeue() which will essentially just
+ try to grab something of qfq's queue.
+
+[ 127.594489][ T453] KASAN: null-ptr-deref in range [0x0000000000000048-0x000000000000004f]
+[ 127.594741][ T453] CPU: 2 UID: 0 PID: 453 Comm: ping Not tainted 7.1.0-rc1-00035-gac961974495b-dirty #793 PREEMPT(full)
+[ 127.595059][ T453] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+[ 127.595254][ T453] RIP: 0010:qfq_dequeue+0x35c/0x1650 [sch_qfq]
+[ 127.595461][ T453] Code: 00 fc ff df 80 3c 02 00 0f 85 17 0e 00 00 4c 8d 73 48 48 89 9d b8 02 00 00 48 b8 00 00 00 00 00 fc ff df 4c 89 f2 48 c1 ea 03 <80> 3c 02 00 0f 85 76 0c 00 00 48 b8 00 00 00 00 00 fc ff df 4c 8b
+[ 127.596081][ T453] RSP: 0018:ffff88810e5af440 EFLAGS: 00010216
+[ 127.596337][ T453] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: dffffc0000000000
+[ 127.596623][ T453] RDX: 0000000000000009 RSI: 0000001880000000 RDI: ffff888104fd82b0
+[ 127.596917][ T453] RBP: ffff888104fd8000 R08: ffff888104fd8280 R09: 1ffff110211893a3
+[ 127.597165][ T453] R10: 1ffff110211893a6 R11: 1ffff110211893a7 R12: 0000001880000000
+[ 127.597404][ T453] R13: ffff888104fd82b8 R14: 0000000000000048 R15: 0000000040000000
+[ 127.597644][ T453] FS: 00007fc380cbfc40(0000) GS:ffff88816f2a8000(0000) knlGS:0000000000000000
+[ 127.597956][ T453] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 127.598160][ T453] CR2: 00005610aa9890a8 CR3: 000000010369e000 CR4: 0000000000750ef0
+[ 127.598390][ T453] PKRU: 55555554
+[ 127.598509][ T453] Call Trace:
+[ 127.598629][ T453] <TASK>
+[ 127.598718][ T453] ? mark_held_locks+0x40/0x70
+[ 127.598890][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599053][ T453] sfb_dequeue+0x88/0x4d0
+[ 127.599174][ T453] ? ktime_get+0x137/0x230
+[ 127.599328][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599480][ T453] ? qdisc_peek_dequeued+0x7b/0x350 [sch_qfq]
+[ 127.599670][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599831][ T453] tbf_dequeue+0x6b1/0x1098 [sch_tbf]
+[ 127.599988][ T453] __qdisc_run+0x169/0x1900
+
+The right thing to do in #1b is to grab the skb off gso_skb queue.
+This patchset fixes that issue by changing #1b to use qdisc_dequeue_peeked()
+method instead.
+
+Fixes: e13e02a3c68d ("net_sched: SFB flow scheduler")
+Signed-off-by: Victor Nogueria <victor@mojatatu.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260430152957.194015-3-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_sfb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
+index ce67826fdf9b6d..58bf4c803f7fee 100644
+--- a/net/sched/sch_sfb.c
++++ b/net/sched/sch_sfb.c
+@@ -439,7 +439,7 @@ static struct sk_buff *sfb_dequeue(struct Qdisc *sch)
+ struct Qdisc *child = q->qdisc;
+ struct sk_buff *skb;
+
+- skb = child->dequeue(q->qdisc);
++ skb = qdisc_dequeue_peeked(child);
+
+ if (skb) {
+ qdisc_bstats_update(sch, skb);
+--
+2.53.0
+
--- /dev/null
+net-sched-cls_fw-fix-null-dereference-of-old-filters.patch
+net-mctp-ensure-our-nlmsg-responses-are-initialised.patch
+net-sched-sch_sfb-replace-direct-dequeue-call-with-p.patch
+drm-remove-plane-hsub-vsub-alignment-requirement-for.patch
+bcache-fix-uninitialized-closure-object.patch
+net-cpsw_new-fix-potential-unregister-of-netdev-that.patch
--- /dev/null
+From 8d04ca0065c7a3c7aea2569b52af6e6a33b4b10f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:52:10 +0200
+Subject: ACPI: button: Enable wakeup GPEs for ACPI buttons at probe time
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ Upstream commit a004b8f0d3bc5d82d3f2c91ff93f4b4b7ccb8f76 ]
+
+Prior to commit 57c31e6d620f ("ACPI: scan: Use acpi_setup_gpe_for_wake()
+for buttons"), ACPI button wakeup GPEs having handler methods remained
+enabled after acpi_wakeup_gpe_init(), but currently they are not enabled
+because acpi_setup_gpe_for_wake() disables them.
+
+That causes function keys to stop working on some systems [1] and there
+may be other related issues elsewhere.
+
+To address that, make the ACPI button driver enable wakeup GPEs for ACPI
+buttons so long as they have handler methods. While this does not
+restore the old behavior exactly (the ACPI button driver needs to be
+bound to the button devices for the GPEs to be enabled), it should be
+sufficient to restore the missing functionality.
+
+For this purpose, introduce acpi_enable_gpe_cond() that enables
+a GPE if its dispatch type matches the supplied one and modify
+acpi_button_probe() to use that function for enabling the GPEs in
+question.
+
+Fixes: 57c31e6d620f ("ACPI: scan: Use acpi_setup_gpe_for_wake() for buttons")
+Reported-by: Nick <nick@kousu.ca>
+Closes: https://lore.kernel.org/linux-acpi/E2OXET.4X5GTP37VTNC3@kousu.ca/ [1]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Tested-by: Nick <nick@kousu.ca>
+Cc: 7.0+ <stable@vger.kernel.org> # 7.0+
+Link: https://patch.msgid.link/9629117.CDJkKcVGEf@rafael.j.wysocki
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/acpica/evxfgpe.c | 50 ++++++++++++++++++++++++++++-------
+ drivers/acpi/button.c | 22 +++++++++++++++
+ include/acpi/acpixf.h | 5 ++++
+ 3 files changed, 68 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
+index 60dacec1b121fd..4074b5908db308 100644
+--- a/drivers/acpi/acpica/evxfgpe.c
++++ b/drivers/acpi/acpica/evxfgpe.c
+@@ -78,18 +78,22 @@ ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
+
+ /*******************************************************************************
+ *
+- * FUNCTION: acpi_enable_gpe
++ * FUNCTION: acpi_enable_gpe_cond
+ *
+ * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
+ * gpe_number - GPE level within the GPE block
++ * dispatch_type - GPE dispatch type to match
+ *
+ * RETURN: Status
+ *
+- * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
+- * hardware-enabled.
++ * DESCRIPTION: Add a reference to a GPE so long as its dispatch type matches
++ * the supplied one, or it is different from ACPI_GPE_DISPATCH_NONE
++ * if the supplied one is ACPI_GPE_DISPATCH_MASK. On the first
++ * reference, the GPE is hardware-enabled.
+ *
+ ******************************************************************************/
+-acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
++acpi_status acpi_enable_gpe_cond(acpi_handle gpe_device, u32 gpe_number,
++ u8 dispatch_type)
+ {
+ acpi_status status = AE_BAD_PARAMETER;
+ struct acpi_gpe_event_info *gpe_event_info;
+@@ -100,14 +104,18 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+ /*
+- * Ensure that we have a valid GPE number and that there is some way
+- * of handling the GPE (handler or a GPE method). In other words, we
+- * won't allow a valid GPE to be enabled if there is no way to handle it.
++ * Ensure that we have a valid GPE number and that the dispatch type of
++ * the GPE matches the supplied one (or it is not ACPI_GPE_DISPATCH_NONE
++ * if the supplied one is ACPI_GPE_DISPATCH_MASK).
+ */
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
+ if (gpe_event_info) {
+- if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
+- ACPI_GPE_DISPATCH_NONE) {
++ if (dispatch_type == ACPI_GPE_DISPATCH_MASK)
++ dispatch_type = ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags);
++ else if (dispatch_type != ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags))
++ dispatch_type = ACPI_GPE_DISPATCH_NONE;
++
++ if (dispatch_type != ACPI_GPE_DISPATCH_NONE) {
+ status = acpi_ev_add_gpe_reference(gpe_event_info, TRUE);
+ if (ACPI_SUCCESS(status) &&
+ ACPI_GPE_IS_POLLING_NEEDED(gpe_event_info)) {
+@@ -128,6 +136,30 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+ return_ACPI_STATUS(status);
+ }
++ACPI_EXPORT_SYMBOL(acpi_enable_gpe_cond)
++
++/*******************************************************************************
++ *
++ * FUNCTION: acpi_enable_gpe
++ *
++ * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
++ * gpe_number - GPE level within the GPE block
++ *
++ * RETURN: Status
++ *
++ * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
++ * hardware-enabled.
++ *
++ ******************************************************************************/
++acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
++{
++ /*
++ * Ensure that there is some way of handling the GPE (handler or a GPE
++ * method). In other words, we won't allow a valid GPE to be enabled if
++ * there is no way to handle it.
++ */
++ return acpi_enable_gpe_cond(gpe_device, gpe_number, ACPI_GPE_DISPATCH_MASK);
++}
+ ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
+
+ /*******************************************************************************
+diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
+index 22f26d8fdb1f6e..0ddbcfd0b1040a 100644
+--- a/drivers/acpi/button.c
++++ b/drivers/acpi/button.c
+@@ -179,6 +179,7 @@ struct acpi_button {
+ ktime_t last_time;
+ bool suspended;
+ bool lid_state_initialized;
++ bool gpe_enabled;
+ };
+
+ static struct acpi_device *lid_device;
+@@ -647,6 +648,21 @@ static int acpi_button_probe(struct platform_device *pdev)
+ status = acpi_install_notify_handler(device->handle,
+ ACPI_ALL_NOTIFY, handler,
+ button);
++ if (ACPI_SUCCESS(status) && device->wakeup.flags.valid) {
++ acpi_status st;
++
++ /*
++ * If the wakeup GPE has a handler method, enable it in
++ * case it is also used for signaling runtime events.
++ */
++ st = acpi_enable_gpe_cond(device->wakeup.gpe_device,
++ device->wakeup.gpe_number,
++ ACPI_GPE_DISPATCH_METHOD);
++ button->gpe_enabled = ACPI_SUCCESS(st);
++ if (button->gpe_enabled)
++ dev_dbg(button->dev, "Enabled ACPI GPE%02llx\n",
++ device->wakeup.gpe_number);
++ }
+ break;
+ }
+ if (ACPI_FAILURE(status)) {
+@@ -690,6 +706,12 @@ static void acpi_button_remove(struct platform_device *pdev)
+ acpi_button_event);
+ break;
+ default:
++ if (button->gpe_enabled) {
++ dev_dbg(button->dev, "Disabling ACPI GPE%02llx\n",
++ adev->wakeup.gpe_number);
++ acpi_disable_gpe(adev->wakeup.gpe_device,
++ adev->wakeup.gpe_number);
++ }
+ acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY,
+ button->type == ACPI_BUTTON_TYPE_LID ?
+ acpi_lid_notify :
+diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
+index 49d1749f30bbc9..a4b56270015161 100644
+--- a/include/acpi/acpixf.h
++++ b/include/acpi/acpixf.h
+@@ -725,6 +725,11 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+ */
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_update_all_gpes(void))
+
++ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
++ acpi_enable_gpe_cond(acpi_handle gpe_device,
++ u32 gpe_number,
++ u8 dispatch_type))
++
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+ acpi_enable_gpe(acpi_handle gpe_device,
+ u32 gpe_number))
+--
+2.53.0
+
--- /dev/null
+From 44bd83bc081a7c89932ec792c9a77a1b37d84ca1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:49:44 +0200
+Subject: ACPI: button: Fix ACPI GPE handler leak during removal
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ Upstream commit fe80251152fed5b185f795ef2cd9f7fe9c3162e0 ]
+
+Commit a7e23ec17fee ("ACPI: button: Install notifier for system events
+as well") changed the ACPI notify handler type for ACPI buttons to
+ACPI_ALL_NOTIFY, but it forgot to update acpi_button_remove() to reflect
+that change. This leads to leaking the notify handler past driver
+removal, which may cause a kernel crash to occur if ACPI notify on
+the given device is triggered after removing the driver, and causes a
+subsequent probe of the given device with the same driver to fail.
+
+Address this by updating the acpi_remove_notify_handler() call in
+acpi_button_remove() as appropriate.
+
+Fixes: a7e23ec17fee ("ACPI: button: Install notifier for system events as well")
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
+Cc: 6.15+ <stable@vger.kernel.org> # 6.15+
+Link: https://patch.msgid.link/7954431.EvYhyI6sBW@rafael.j.wysocki
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/button.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
+index ff30f993b15062..22f26d8fdb1f6e 100644
+--- a/drivers/acpi/button.c
++++ b/drivers/acpi/button.c
+@@ -690,7 +690,7 @@ static void acpi_button_remove(struct platform_device *pdev)
+ acpi_button_event);
+ break;
+ default:
+- acpi_remove_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY,
++ acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY,
+ button->type == ACPI_BUTTON_TYPE_LID ?
+ acpi_lid_notify :
+ acpi_button_notify);
+--
+2.53.0
+
--- /dev/null
+From f55c2f9a2c213a2ea0e96d3b7fe50cb58fd79be5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Apr 2026 12:21:35 +0800
+Subject: bcache: fix uninitialized closure object
+
+From: Mingzhe Zou <mingzhe.zou@easystack.cn>
+
+[ Upstream commit 20a8e451ec1c7e99060b1bbaaad03ce88c39ddb8 ]
+
+In the previous patch ("bcache: fix cached_dev.sb_bio use-after-free and
+crash"), we adopted a simple modification suggestion from AI to fix the
+use-after-free.
+
+But in actual testing, we found an extreme case where the device is
+stopped before calling bch_write_bdev_super().
+
+At this point, struct closure sb_write has not been initialized yet.
+For this patch, we ensure that sb_bio has been completed via
+sb_write_mutex.
+
+Signed-off-by: Mingzhe Zou <mingzhe.zou@easystack.cn>
+Signed-off-by: Coly Li <colyli@fnnas.com>
+Link: https://patch.msgid.link/20260403042135.2221247-1-colyli@fnnas.com
+Fixes: fec114a98b87 ("bcache: fix cached_dev.sb_bio use-after-free and crash")
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/bcache/super.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
+index 6627a381f65ae7..97d9adb0bf96b0 100644
+--- a/drivers/md/bcache/super.c
++++ b/drivers/md/bcache/super.c
+@@ -1378,7 +1378,8 @@ static CLOSURE_CALLBACK(cached_dev_free)
+ * The sb_bio is embedded in struct cached_dev, so we must
+ * ensure no I/O is in progress.
+ */
+- closure_sync(&dc->sb_write);
++ down(&dc->sb_write_mutex);
++ up(&dc->sb_write_mutex);
+
+ if (dc->sb_disk)
+ folio_put(virt_to_folio(dc->sb_disk));
+--
+2.53.0
+
--- /dev/null
+From b4054f008dc9126b448ebf9f02cf81d1f0a2049b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Apr 2026 11:29:56 -0400
+Subject: net/sched: sch_sfb: Replace direct dequeue call with peek and
+ qdisc_dequeue_peeked
+
+From: Victor Nogueria <victor@mojatatu.com>
+
+[ Upstream commit 1b9bc71153b01dbde8045b9edede4240f4f5520e ]
+
+When sfb has children (eg qfq qdisc) whose peek() callback is
+qdisc_peek_dequeued(), we could get a kernel panic. When the parent of such
+qdiscs (eg illustrated in patch #3 as tbf) wants to retrieve an skb from
+its child (sfb in this case), it will do the following:
+ 1a. do a peek() - and when sensing there's an skb the child can offer, then
+ - the child in this case(sfb) calls its child's (qfq) peek.
+ qfq does the right thing and will return the gso_skb queue packet.
+ Note: if there wasnt a gso_skb entry then qfq will store it there.
+ 1b. invoke a dequeue() on the child (sfb). And herein lies the problem.
+ - sfb will call the child's dequeue() which will essentially just
+ try to grab something of qfq's queue.
+
+[ 127.594489][ T453] KASAN: null-ptr-deref in range [0x0000000000000048-0x000000000000004f]
+[ 127.594741][ T453] CPU: 2 UID: 0 PID: 453 Comm: ping Not tainted 7.1.0-rc1-00035-gac961974495b-dirty #793 PREEMPT(full)
+[ 127.595059][ T453] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+[ 127.595254][ T453] RIP: 0010:qfq_dequeue+0x35c/0x1650 [sch_qfq]
+[ 127.595461][ T453] Code: 00 fc ff df 80 3c 02 00 0f 85 17 0e 00 00 4c 8d 73 48 48 89 9d b8 02 00 00 48 b8 00 00 00 00 00 fc ff df 4c 89 f2 48 c1 ea 03 <80> 3c 02 00 0f 85 76 0c 00 00 48 b8 00 00 00 00 00 fc ff df 4c 8b
+[ 127.596081][ T453] RSP: 0018:ffff88810e5af440 EFLAGS: 00010216
+[ 127.596337][ T453] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: dffffc0000000000
+[ 127.596623][ T453] RDX: 0000000000000009 RSI: 0000001880000000 RDI: ffff888104fd82b0
+[ 127.596917][ T453] RBP: ffff888104fd8000 R08: ffff888104fd8280 R09: 1ffff110211893a3
+[ 127.597165][ T453] R10: 1ffff110211893a6 R11: 1ffff110211893a7 R12: 0000001880000000
+[ 127.597404][ T453] R13: ffff888104fd82b8 R14: 0000000000000048 R15: 0000000040000000
+[ 127.597644][ T453] FS: 00007fc380cbfc40(0000) GS:ffff88816f2a8000(0000) knlGS:0000000000000000
+[ 127.597956][ T453] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 127.598160][ T453] CR2: 00005610aa9890a8 CR3: 000000010369e000 CR4: 0000000000750ef0
+[ 127.598390][ T453] PKRU: 55555554
+[ 127.598509][ T453] Call Trace:
+[ 127.598629][ T453] <TASK>
+[ 127.598718][ T453] ? mark_held_locks+0x40/0x70
+[ 127.598890][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599053][ T453] sfb_dequeue+0x88/0x4d0
+[ 127.599174][ T453] ? ktime_get+0x137/0x230
+[ 127.599328][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599480][ T453] ? qdisc_peek_dequeued+0x7b/0x350 [sch_qfq]
+[ 127.599670][ T453] ? srso_alias_return_thunk+0x5/0xfbef5
+[ 127.599831][ T453] tbf_dequeue+0x6b1/0x1098 [sch_tbf]
+[ 127.599988][ T453] __qdisc_run+0x169/0x1900
+
+The right thing to do in #1b is to grab the skb off gso_skb queue.
+This patchset fixes that issue by changing #1b to use qdisc_dequeue_peeked()
+method instead.
+
+Fixes: e13e02a3c68d ("net_sched: SFB flow scheduler")
+Signed-off-by: Victor Nogueria <victor@mojatatu.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260430152957.194015-3-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_sfb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
+index 00286c930b8de7..14ac8897784757 100644
+--- a/net/sched/sch_sfb.c
++++ b/net/sched/sch_sfb.c
+@@ -441,7 +441,7 @@ static struct sk_buff *sfb_dequeue(struct Qdisc *sch)
+ struct Qdisc *child = q->qdisc;
+ struct sk_buff *skb;
+
+- skb = child->dequeue(q->qdisc);
++ skb = qdisc_dequeue_peeked(child);
+
+ if (skb) {
+ qdisc_bstats_update(sch, skb);
+--
+2.53.0
+
--- /dev/null
+acpi-button-fix-acpi-gpe-handler-leak-during-removal.patch
+acpi-button-enable-wakeup-gpes-for-acpi-buttons-at-p.patch
+xfrm-move-policy_bydst-rcu-sync-from-per-netns-.exit.patch
+net-sched-sch_sfb-replace-direct-dequeue-call-with-p.patch
+bcache-fix-uninitialized-closure-object.patch
--- /dev/null
+From eedaa7f770f77730fe2ac4a1e66ea906b244ceab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 03:29:26 -0700
+Subject: xfrm: move policy_bydst RCU sync from per-netns .exit to .pre_exit
+
+From: Usama Arif <usama.arif@linux.dev>
+
+[ Upstream commit 3e52417318473782012b236d0325bf7d2266a597 ]
+
+The struct pernet_operations docstring in include/net/net_namespace.h
+explicitly warns against blocking RCU primitives in .exit handlers:
+
+ Exit methods using blocking RCU primitives, such as
+ synchronize_rcu(), should be implemented via exit_batch.
+ [...]
+ Please, avoid synchronize_rcu() at all, where it's possible.
+
+ Note that a combination of pre_exit() and exit() can
+ be used, since a synchronize_rcu() is guaranteed between
+ the calls.
+
+xfrm_policy_fini() violates this: it calls synchronize_rcu() before
+freeing the policy_bydst hash tables (so no RCU reader is mid-
+traversal at free time), but runs from xfrm_net_ops.exit -- once per
+namespace -- so a cleanup_net() of N namespaces pays N full RCU
+grace periods serially.
+
+Use the documented pre_exit/exit split. Move the policy flush (and
+the workqueue drains it depends on) into a new .pre_exit handler;
+xfrm_policy_fini() then runs in .exit and frees the hash tables
+after the synchronize_rcu_expedited() that cleanup_net() guarantees
+between the two phases. Providing O(1) RCU grace periods per batch
+instead of O(N).
+
+Observed on Linux 6.18 with a workload doing unshare(CLONE_NEWNET)
+at ~13/sec sustained: cleanup_net() and the netns_wq rescuer kthread
+both stuck in xfrm_policy_fini()'s synchronize_rcu(), >300k struct
+net accumulated in the cleanup queue, Percpu in /proc/meminfo climbed
+to 130+ GB on 256-CPU hosts, and memcg OOMs followed. setup_net and
+__put_net counts were balanced, ruling out a refcount leak.
+
+Fixes: 069daad4f2ae ("xfrm: Wait for RCU readers during policy netns exit")
+Signed-off-by: Usama Arif <usama.arif@linux.dev>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_policy.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
+index a872af5610dc95..71bdb781cb0292 100644
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -4276,21 +4276,21 @@ static int __net_init xfrm_policy_init(struct net *net)
+ return -ENOMEM;
+ }
+
+-static void xfrm_policy_fini(struct net *net)
++static void __net_exit xfrm_net_pre_exit(struct net *net)
+ {
+- struct xfrm_pol_inexact_bin *b, *t;
+- unsigned int sz;
+- int dir;
+-
+ disable_work_sync(&net->xfrm.policy_hthresh.work);
+-
+ flush_work(&net->xfrm.policy_hash_work);
+ #ifdef CONFIG_XFRM_SUB_POLICY
+ xfrm_policy_flush(net, XFRM_POLICY_TYPE_SUB, false);
+ #endif
+ xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, false);
++}
+
+- synchronize_rcu();
++static void xfrm_policy_fini(struct net *net)
++{
++ struct xfrm_pol_inexact_bin *b, *t;
++ unsigned int sz;
++ int dir;
+
+ WARN_ON(!list_empty(&net->xfrm.policy_all));
+
+@@ -4368,6 +4368,7 @@ static void __net_exit xfrm_net_exit(struct net *net)
+
+ static struct pernet_operations __net_initdata xfrm_net_ops = {
+ .init = xfrm_net_init,
++ .pre_exit = xfrm_net_pre_exit,
+ .exit = xfrm_net_exit,
+ };
+
+--
+2.53.0
+