From 68b48ecc3a955bb644a7a01a2c3b0f727b767c20 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 27 Apr 2025 19:06:52 -0400 Subject: [PATCH] Fixes for 5.4 Signed-off-by: Sasha Levin --- ...-null-ptr-deref-in-scpi_cpufreq_get_.patch | 49 +++++++ queue-5.4/net-phy-leds-fix-memory-leak.patch | 101 ++++++++++++++ ...ix-a-potential-uaf-in-hfsc_dequeue-t.patch | 51 +++++++ ...ix-a-uaf-vulnerability-in-class-hand.patch | 70 ++++++++++ queue-5.4/series | 5 + ...inter-dereference-in-tipc_mon_reinit.patch | 125 ++++++++++++++++++ 6 files changed, 401 insertions(+) create mode 100644 queue-5.4/cpufreq-scpi-fix-null-ptr-deref-in-scpi_cpufreq_get_.patch create mode 100644 queue-5.4/net-phy-leds-fix-memory-leak.patch create mode 100644 queue-5.4/net_sched-hfsc-fix-a-potential-uaf-in-hfsc_dequeue-t.patch create mode 100644 queue-5.4/net_sched-hfsc-fix-a-uaf-vulnerability-in-class-hand.patch create mode 100644 queue-5.4/tipc-fix-null-pointer-dereference-in-tipc_mon_reinit.patch diff --git a/queue-5.4/cpufreq-scpi-fix-null-ptr-deref-in-scpi_cpufreq_get_.patch b/queue-5.4/cpufreq-scpi-fix-null-ptr-deref-in-scpi_cpufreq_get_.patch new file mode 100644 index 0000000000..1a4d008101 --- /dev/null +++ b/queue-5.4/cpufreq-scpi-fix-null-ptr-deref-in-scpi_cpufreq_get_.patch @@ -0,0 +1,49 @@ +From 77819df07391cac918c02379aa86580a9b0238b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Apr 2025 23:03:54 +0800 +Subject: cpufreq: scpi: Fix null-ptr-deref in scpi_cpufreq_get_rate() + +From: Henry Martin + +[ Upstream commit 73b24dc731731edf762f9454552cb3a5b7224949 ] + +cpufreq_cpu_get_raw() can return NULL when the target CPU is not present +in the policy->cpus mask. scpi_cpufreq_get_rate() does not check for +this case, which results in a NULL pointer dereference. + +Fixes: 343a8d17fa8d ("cpufreq: scpi: remove arm_big_little dependency") +Signed-off-by: Henry Martin +Acked-by: Sudeep Holla +Signed-off-by: Viresh Kumar +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/scpi-cpufreq.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c +index b341ffbf56bc3..73539f357c7ae 100644 +--- a/drivers/cpufreq/scpi-cpufreq.c ++++ b/drivers/cpufreq/scpi-cpufreq.c +@@ -39,9 +39,16 @@ static struct scpi_ops *scpi_ops; + + static unsigned int scpi_cpufreq_get_rate(unsigned int cpu) + { +- struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu); +- struct scpi_data *priv = policy->driver_data; +- unsigned long rate = clk_get_rate(priv->clk); ++ struct cpufreq_policy *policy; ++ struct scpi_data *priv; ++ unsigned long rate; ++ ++ policy = cpufreq_cpu_get_raw(cpu); ++ if (unlikely(!policy)) ++ return 0; ++ ++ priv = policy->driver_data; ++ rate = clk_get_rate(priv->clk); + + return rate / 1000; + } +-- +2.39.5 + diff --git a/queue-5.4/net-phy-leds-fix-memory-leak.patch b/queue-5.4/net-phy-leds-fix-memory-leak.patch new file mode 100644 index 0000000000..651a84ed14 --- /dev/null +++ b/queue-5.4/net-phy-leds-fix-memory-leak.patch @@ -0,0 +1,101 @@ +From 24000a9d81ca417105cc1fbd34aef2b3026906e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 11:25:56 +0800 +Subject: net: phy: leds: fix memory leak + +From: Qingfang Deng + +[ Upstream commit b7f0ee992adf601aa00c252418266177eb7ac2bc ] + +A network restart test on a router led to an out-of-memory condition, +which was traced to a memory leak in the PHY LED trigger code. + +The root cause is misuse of the devm API. The registration function +(phy_led_triggers_register) is called from phy_attach_direct, not +phy_probe, and the unregister function (phy_led_triggers_unregister) +is called from phy_detach, not phy_remove. This means the register and +unregister functions can be called multiple times for the same PHY +device, but devm-allocated memory is not freed until the driver is +unbound. + +This also prevents kmemleak from detecting the leak, as the devm API +internally stores the allocated pointer. + +Fix this by replacing devm_kzalloc/devm_kcalloc with standard +kzalloc/kcalloc, and add the corresponding kfree calls in the unregister +path. + +Fixes: 3928ee6485a3 ("net: phy: leds: Add support for "link" trigger") +Fixes: 2e0bc452f472 ("net: phy: leds: add support for led triggers on phy link state change") +Signed-off-by: Hao Guan +Signed-off-by: Qingfang Deng +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250417032557.2929427-1-dqfext@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/phy_led_triggers.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/phy/phy_led_triggers.c b/drivers/net/phy/phy_led_triggers.c +index 59a94e07e7c55..ae28aa2f9a392 100644 +--- a/drivers/net/phy/phy_led_triggers.c ++++ b/drivers/net/phy/phy_led_triggers.c +@@ -91,9 +91,8 @@ int phy_led_triggers_register(struct phy_device *phy) + if (!phy->phy_num_led_triggers) + return 0; + +- phy->led_link_trigger = devm_kzalloc(&phy->mdio.dev, +- sizeof(*phy->led_link_trigger), +- GFP_KERNEL); ++ phy->led_link_trigger = kzalloc(sizeof(*phy->led_link_trigger), ++ GFP_KERNEL); + if (!phy->led_link_trigger) { + err = -ENOMEM; + goto out_clear; +@@ -108,10 +107,9 @@ int phy_led_triggers_register(struct phy_device *phy) + if (err) + goto out_free_link; + +- phy->phy_led_triggers = devm_kcalloc(&phy->mdio.dev, +- phy->phy_num_led_triggers, +- sizeof(struct phy_led_trigger), +- GFP_KERNEL); ++ phy->phy_led_triggers = kcalloc(phy->phy_num_led_triggers, ++ sizeof(struct phy_led_trigger), ++ GFP_KERNEL); + if (!phy->phy_led_triggers) { + err = -ENOMEM; + goto out_unreg_link; +@@ -131,11 +129,11 @@ int phy_led_triggers_register(struct phy_device *phy) + out_unreg: + while (i--) + phy_led_trigger_unregister(&phy->phy_led_triggers[i]); +- devm_kfree(&phy->mdio.dev, phy->phy_led_triggers); ++ kfree(phy->phy_led_triggers); + out_unreg_link: + phy_led_trigger_unregister(phy->led_link_trigger); + out_free_link: +- devm_kfree(&phy->mdio.dev, phy->led_link_trigger); ++ kfree(phy->led_link_trigger); + phy->led_link_trigger = NULL; + out_clear: + phy->phy_num_led_triggers = 0; +@@ -149,8 +147,13 @@ void phy_led_triggers_unregister(struct phy_device *phy) + + for (i = 0; i < phy->phy_num_led_triggers; i++) + phy_led_trigger_unregister(&phy->phy_led_triggers[i]); ++ kfree(phy->phy_led_triggers); ++ phy->phy_led_triggers = NULL; + +- if (phy->led_link_trigger) ++ if (phy->led_link_trigger) { + phy_led_trigger_unregister(phy->led_link_trigger); ++ kfree(phy->led_link_trigger); ++ phy->led_link_trigger = NULL; ++ } + } + EXPORT_SYMBOL_GPL(phy_led_triggers_unregister); +-- +2.39.5 + diff --git a/queue-5.4/net_sched-hfsc-fix-a-potential-uaf-in-hfsc_dequeue-t.patch b/queue-5.4/net_sched-hfsc-fix-a-potential-uaf-in-hfsc_dequeue-t.patch new file mode 100644 index 0000000000..a52e7781c3 --- /dev/null +++ b/queue-5.4/net_sched-hfsc-fix-a-potential-uaf-in-hfsc_dequeue-t.patch @@ -0,0 +1,51 @@ +From 88c5ba77300c064d087918e63f18219d31e8a86c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 11:47:31 -0700 +Subject: net_sched: hfsc: Fix a potential UAF in hfsc_dequeue() too + +From: Cong Wang + +[ Upstream commit 6ccbda44e2cc3d26fd22af54c650d6d5d801addf ] + +Similarly to the previous patch, we need to safe guard hfsc_dequeue() +too. But for this one, we don't have a reliable reproducer. + +Fixes: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 ("Linux-2.6.12-rc2") +Reported-by: Gerrard Tai +Signed-off-by: Cong Wang +Reviewed-by: Jamal Hadi Salim +Link: https://patch.msgid.link/20250417184732.943057-3-xiyou.wangcong@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_hfsc.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c +index eabc62df6f4e4..79c63c4610d3a 100644 +--- a/net/sched/sch_hfsc.c ++++ b/net/sched/sch_hfsc.c +@@ -1645,10 +1645,16 @@ hfsc_dequeue(struct Qdisc *sch) + if (cl->qdisc->q.qlen != 0) { + /* update ed */ + next_len = qdisc_peek_len(cl->qdisc); +- if (realtime) +- update_ed(cl, next_len); +- else +- update_d(cl, next_len); ++ /* Check queue length again since some qdisc implementations ++ * (e.g., netem/codel) might empty the queue during the peek ++ * operation. ++ */ ++ if (cl->qdisc->q.qlen != 0) { ++ if (realtime) ++ update_ed(cl, next_len); ++ else ++ update_d(cl, next_len); ++ } + } else { + /* the class becomes passive */ + eltree_remove(cl); +-- +2.39.5 + diff --git a/queue-5.4/net_sched-hfsc-fix-a-uaf-vulnerability-in-class-hand.patch b/queue-5.4/net_sched-hfsc-fix-a-uaf-vulnerability-in-class-hand.patch new file mode 100644 index 0000000000..05eddd61b6 --- /dev/null +++ b/queue-5.4/net_sched-hfsc-fix-a-uaf-vulnerability-in-class-hand.patch @@ -0,0 +1,70 @@ +From 316f4c74221925547196a878fe6f7db1c9f55b38 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 11:47:30 -0700 +Subject: net_sched: hfsc: Fix a UAF vulnerability in class handling + +From: Cong Wang + +[ Upstream commit 3df275ef0a6ae181e8428a6589ef5d5231e58b5c ] + +This patch fixes a Use-After-Free vulnerability in the HFSC qdisc class +handling. The issue occurs due to a time-of-check/time-of-use condition +in hfsc_change_class() when working with certain child qdiscs like netem +or codel. + +The vulnerability works as follows: +1. hfsc_change_class() checks if a class has packets (q.qlen != 0) +2. It then calls qdisc_peek_len(), which for certain qdiscs (e.g., + codel, netem) might drop packets and empty the queue +3. The code continues assuming the queue is still non-empty, adding + the class to vttree +4. This breaks HFSC scheduler assumptions that only non-empty classes + are in vttree +5. Later, when the class is destroyed, this can lead to a Use-After-Free + +The fix adds a second queue length check after qdisc_peek_len() to verify +the queue wasn't emptied. + +Fixes: 21f4d5cc25ec ("net_sched/hfsc: fix curve activation in hfsc_change_class()") +Reported-by: Gerrard Tai +Reviewed-by: Konstantin Khlebnikov +Signed-off-by: Cong Wang +Reviewed-by: Jamal Hadi Salim +Link: https://patch.msgid.link/20250417184732.943057-2-xiyou.wangcong@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_hfsc.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c +index 9ebae0d07a9c6..eabc62df6f4e4 100644 +--- a/net/sched/sch_hfsc.c ++++ b/net/sched/sch_hfsc.c +@@ -959,6 +959,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, + + if (cl != NULL) { + int old_flags; ++ int len = 0; + + if (parentid) { + if (cl->cl_parent && +@@ -989,9 +990,13 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, + if (usc != NULL) + hfsc_change_usc(cl, usc, cur_time); + ++ if (cl->qdisc->q.qlen != 0) ++ len = qdisc_peek_len(cl->qdisc); ++ /* Check queue length again since some qdisc implementations ++ * (e.g., netem/codel) might empty the queue during the peek ++ * operation. ++ */ + if (cl->qdisc->q.qlen != 0) { +- int len = qdisc_peek_len(cl->qdisc); +- + if (cl->cl_flags & HFSC_RSC) { + if (old_flags & HFSC_RSC) + update_ed(cl, len); +-- +2.39.5 + diff --git a/queue-5.4/series b/queue-5.4/series index 11ee5066dc..99fbe16b1c 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -138,3 +138,8 @@ pci-rename-pci_irq_legacy-to-pci_irq_intx.patch misc-pci_endpoint_test-use-intx-instead-of-legacy.patch misc-pci_endpoint_test-fix-displaying-irq_type-after.patch drm-amd-pm-prevent-division-by-zero.patch +cpufreq-scpi-fix-null-ptr-deref-in-scpi_cpufreq_get_.patch +net-phy-leds-fix-memory-leak.patch +tipc-fix-null-pointer-dereference-in-tipc_mon_reinit.patch +net_sched-hfsc-fix-a-uaf-vulnerability-in-class-hand.patch +net_sched-hfsc-fix-a-potential-uaf-in-hfsc_dequeue-t.patch diff --git a/queue-5.4/tipc-fix-null-pointer-dereference-in-tipc_mon_reinit.patch b/queue-5.4/tipc-fix-null-pointer-dereference-in-tipc_mon_reinit.patch new file mode 100644 index 0000000000..d82377322c --- /dev/null +++ b/queue-5.4/tipc-fix-null-pointer-dereference-in-tipc_mon_reinit.patch @@ -0,0 +1,125 @@ +From 5ea86caeca1990eebbc3ffd377aed4e49311c1fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 14:47:15 +0700 +Subject: tipc: fix NULL pointer dereference in tipc_mon_reinit_self() + +From: Tung Nguyen + +[ Upstream commit d63527e109e811ef11abb1c2985048fdb528b4cb ] + +syzbot reported: + +tipc: Node number set to 1055423674 +Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI +KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] +CPU: 3 UID: 0 PID: 6017 Comm: kworker/3:5 Not tainted 6.15.0-rc1-syzkaller-00246-g900241a5cc15 #0 PREEMPT(full) +Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 +Workqueue: events tipc_net_finalize_work +RIP: 0010:tipc_mon_reinit_self+0x11c/0x210 net/tipc/monitor.c:719 +... +RSP: 0018:ffffc9000356fb68 EFLAGS: 00010246 +RAX: 0000000000000000 RBX: 0000000000000000 RCX: 000000003ee87cba +RDX: 0000000000000000 RSI: ffffffff8dbc56a7 RDI: ffff88804c2cc010 +RBP: dffffc0000000000 R08: 0000000000000001 R09: 0000000000000000 +R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000007 +R13: fffffbfff2111097 R14: ffff88804ead8000 R15: ffff88804ead9010 +FS: 0000000000000000(0000) GS:ffff888097ab9000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00000000f720eb00 CR3: 000000000e182000 CR4: 0000000000352ef0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + + tipc_net_finalize+0x10b/0x180 net/tipc/net.c:140 + process_one_work+0x9cc/0x1b70 kernel/workqueue.c:3238 + process_scheduled_works kernel/workqueue.c:3319 [inline] + worker_thread+0x6c8/0xf10 kernel/workqueue.c:3400 + kthread+0x3c2/0x780 kernel/kthread.c:464 + ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:153 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 + +... +RIP: 0010:tipc_mon_reinit_self+0x11c/0x210 net/tipc/monitor.c:719 +... +RSP: 0018:ffffc9000356fb68 EFLAGS: 00010246 +RAX: 0000000000000000 RBX: 0000000000000000 RCX: 000000003ee87cba +RDX: 0000000000000000 RSI: ffffffff8dbc56a7 RDI: ffff88804c2cc010 +RBP: dffffc0000000000 R08: 0000000000000001 R09: 0000000000000000 +R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000007 +R13: fffffbfff2111097 R14: ffff88804ead8000 R15: ffff88804ead9010 +FS: 0000000000000000(0000) GS:ffff888097ab9000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00000000f720eb00 CR3: 000000000e182000 CR4: 0000000000352ef0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 + +There is a racing condition between workqueue created when enabling +bearer and another thread created when disabling bearer right after +that as follow: + +enabling_bearer | disabling_bearer +--------------- | ---------------- +tipc_disc_timeout() | +{ | bearer_disable() + ... | { + schedule_work(&tn->work); | tipc_mon_delete() + ... | { +} | ... + | write_lock_bh(&mon->lock); + | mon->self = NULL; + | write_unlock_bh(&mon->lock); + | ... + | } +tipc_net_finalize_work() | } +{ | + ... | + tipc_net_finalize() | + { | + ... | + tipc_mon_reinit_self() | + { | + ... | + write_lock_bh(&mon->lock); | + mon->self->addr = tipc_own_addr(net); | + write_unlock_bh(&mon->lock); | + ... | + } | + ... | + } | + ... | +} | + +'mon->self' is set to NULL in disabling_bearer thread and dereferenced +later in enabling_bearer thread. + +This commit fixes this issue by validating 'mon->self' before assigning +node address to it. + +Reported-by: syzbot+ed60da8d686dc709164c@syzkaller.appspotmail.com +Fixes: 46cb01eeeb86 ("tipc: update mon's self addr when node addr generated") +Signed-off-by: Tung Nguyen +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250417074826.578115-1-tung.quang.nguyen@est.tech +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/monitor.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/tipc/monitor.c b/net/tipc/monitor.c +index 0b9ad3b5ff18a..2e63d5f82b784 100644 +--- a/net/tipc/monitor.c ++++ b/net/tipc/monitor.c +@@ -677,7 +677,8 @@ void tipc_mon_reinit_self(struct net *net) + if (!mon) + continue; + write_lock_bh(&mon->lock); +- mon->self->addr = tipc_own_addr(net); ++ if (mon->self) ++ mon->self->addr = tipc_own_addr(net); + write_unlock_bh(&mon->lock); + } + } +-- +2.39.5 + -- 2.47.3