From: Greg Kroah-Hartman Date: Tue, 22 Jul 2025 10:11:04 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v6.1.147~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b787253589fb86a178cbfff2355d1170b3324db2;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: net_sched-sch_sfq-annotate-data-races-around-q-perturb_period.patch net_sched-sch_sfq-don-t-allow-1-packet-limit.patch net_sched-sch_sfq-handle-bigger-packets.patch net_sched-sch_sfq-move-the-limit-validation.patch net_sched-sch_sfq-reject-invalid-perturb-period.patch net_sched-sch_sfq-use-a-temporary-work-area-for-validating-configuration.patch power-supply-bq24190-fix-use-after-free-bug-in-bq24190_remove-due-to-race-condition.patch power-supply-bq24190_charger-fix-runtime-pm-imbalance-on-error.patch power-supply-bq24190_charger-using-pm_runtime_resume_and_get-instead-of-pm_runtime_get_sync.patch virtio-net-ensure-the-received-length-does-not-exceed-allocated-size.patch xhci-disable-stream-for-xhc-controller-with-xhci_broken_streams.patch --- diff --git a/queue-5.4/net_sched-sch_sfq-annotate-data-races-around-q-perturb_period.patch b/queue-5.4/net_sched-sch_sfq-annotate-data-races-around-q-perturb_period.patch new file mode 100644 index 0000000000..51461c001f --- /dev/null +++ b/queue-5.4/net_sched-sch_sfq-annotate-data-races-around-q-perturb_period.patch @@ -0,0 +1,71 @@ +From stable+bounces-163264-greg=kroah.com@vger.kernel.org Thu Jul 17 14:46:32 2025 +From: Harshit Mogalapalli +Date: Thu, 17 Jul 2025 05:45:51 -0700 +Subject: net_sched: sch_sfq: annotate data-races around q->perturb_period +To: stable@vger.kernel.org +Cc: edumazet@google.com, tavip@google.com, Simon Horman , Jakub Kicinski , Harshit Mogalapalli +Message-ID: <20250717124556.589696-2-harshit.m.mogalapalli@oracle.com> + +From: Eric Dumazet + +[ Upstream commit a17ef9e6c2c1cf0fc6cd6ca6a9ce525c67d1da7f ] + +sfq_perturbation() reads q->perturb_period locklessly. +Add annotations to fix potential issues. + +Signed-off-by: Eric Dumazet +Reviewed-by: Simon Horman +Link: https://lore.kernel.org/r/20240430180015.3111398-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +[ Harshit: Backport to 5.4.y, conflicts resolved due to missing commit: + d636fc5dd692 ("net: sched: add rcu annotations around + qdisc->qdisc_sleeping")in 5.4.y ] +Signed-off-by: Harshit Mogalapalli +Signed-off-by: Greg Kroah-Hartman +--- + net/sched/sch_sfq.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/net/sched/sch_sfq.c ++++ b/net/sched/sch_sfq.c +@@ -611,6 +611,7 @@ static void sfq_perturbation(struct time + struct Qdisc *sch = q->sch; + spinlock_t *root_lock = qdisc_lock(qdisc_root_sleeping(sch)); + siphash_key_t nkey; ++ int period; + + get_random_bytes(&nkey, sizeof(nkey)); + spin_lock(root_lock); +@@ -619,8 +620,12 @@ static void sfq_perturbation(struct time + sfq_rehash(sch); + spin_unlock(root_lock); + +- if (q->perturb_period) +- mod_timer(&q->perturb_timer, jiffies + q->perturb_period); ++ /* q->perturb_period can change under us from ++ * sfq_change() and sfq_destroy(). ++ */ ++ period = READ_ONCE(q->perturb_period); ++ if (period) ++ mod_timer(&q->perturb_timer, jiffies + period); + } + + static int sfq_change(struct Qdisc *sch, struct nlattr *opt) +@@ -662,7 +667,7 @@ static int sfq_change(struct Qdisc *sch, + q->quantum = ctl->quantum; + q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum); + } +- q->perturb_period = ctl->perturb_period * HZ; ++ WRITE_ONCE(q->perturb_period, ctl->perturb_period * HZ); + if (ctl->flows) + q->maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS); + if (ctl->divisor) { +@@ -724,7 +729,7 @@ static void sfq_destroy(struct Qdisc *sc + struct sfq_sched_data *q = qdisc_priv(sch); + + tcf_block_put(q->block); +- q->perturb_period = 0; ++ WRITE_ONCE(q->perturb_period, 0); + del_timer_sync(&q->perturb_timer); + sfq_free(q->ht); + sfq_free(q->slots); diff --git a/queue-5.4/net_sched-sch_sfq-don-t-allow-1-packet-limit.patch b/queue-5.4/net_sched-sch_sfq-don-t-allow-1-packet-limit.patch new file mode 100644 index 0000000000..e54f4de98a --- /dev/null +++ b/queue-5.4/net_sched-sch_sfq-don-t-allow-1-packet-limit.patch @@ -0,0 +1,115 @@ +From stable+bounces-163260-greg=kroah.com@vger.kernel.org Thu Jul 17 14:46:20 2025 +From: Harshit Mogalapalli +Date: Thu, 17 Jul 2025 05:45:53 -0700 +Subject: net_sched: sch_sfq: don't allow 1 packet limit +To: stable@vger.kernel.org +Cc: edumazet@google.com, tavip@google.com, syzbot , Jakub Kicinski , Harshit Mogalapalli +Message-ID: <20250717124556.589696-4-harshit.m.mogalapalli@oracle.com> + +From: Octavian Purdila + +[ Upstream commit 10685681bafce6febb39770f3387621bf5d67d0b ] + +The current implementation does not work correctly with a limit of +1. iproute2 actually checks for this and this patch adds the check in +kernel as well. + +This fixes the following syzkaller reported crash: + +UBSAN: array-index-out-of-bounds in net/sched/sch_sfq.c:210:6 +index 65535 is out of range for type 'struct sfq_head[128]' +CPU: 0 PID: 2569 Comm: syz-executor101 Not tainted 5.10.0-smp-DEV #1 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024 +Call Trace: + __dump_stack lib/dump_stack.c:79 [inline] + dump_stack+0x125/0x19f lib/dump_stack.c:120 + ubsan_epilogue lib/ubsan.c:148 [inline] + __ubsan_handle_out_of_bounds+0xed/0x120 lib/ubsan.c:347 + sfq_link net/sched/sch_sfq.c:210 [inline] + sfq_dec+0x528/0x600 net/sched/sch_sfq.c:238 + sfq_dequeue+0x39b/0x9d0 net/sched/sch_sfq.c:500 + sfq_reset+0x13/0x50 net/sched/sch_sfq.c:525 + qdisc_reset+0xfe/0x510 net/sched/sch_generic.c:1026 + tbf_reset+0x3d/0x100 net/sched/sch_tbf.c:319 + qdisc_reset+0xfe/0x510 net/sched/sch_generic.c:1026 + dev_reset_queue+0x8c/0x140 net/sched/sch_generic.c:1296 + netdev_for_each_tx_queue include/linux/netdevice.h:2350 [inline] + dev_deactivate_many+0x6dc/0xc20 net/sched/sch_generic.c:1362 + __dev_close_many+0x214/0x350 net/core/dev.c:1468 + dev_close_many+0x207/0x510 net/core/dev.c:1506 + unregister_netdevice_many+0x40f/0x16b0 net/core/dev.c:10738 + unregister_netdevice_queue+0x2be/0x310 net/core/dev.c:10695 + unregister_netdevice include/linux/netdevice.h:2893 [inline] + __tun_detach+0x6b6/0x1600 drivers/net/tun.c:689 + tun_detach drivers/net/tun.c:705 [inline] + tun_chr_close+0x104/0x1b0 drivers/net/tun.c:3640 + __fput+0x203/0x840 fs/file_table.c:280 + task_work_run+0x129/0x1b0 kernel/task_work.c:185 + exit_task_work include/linux/task_work.h:33 [inline] + do_exit+0x5ce/0x2200 kernel/exit.c:931 + do_group_exit+0x144/0x310 kernel/exit.c:1046 + __do_sys_exit_group kernel/exit.c:1057 [inline] + __se_sys_exit_group kernel/exit.c:1055 [inline] + __x64_sys_exit_group+0x3b/0x40 kernel/exit.c:1055 + do_syscall_64+0x6c/0xd0 + entry_SYSCALL_64_after_hwframe+0x61/0xcb +RIP: 0033:0x7fe5e7b52479 +Code: Unable to access opcode bytes at RIP 0x7fe5e7b5244f. +RSP: 002b:00007ffd3c800398 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7 +RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fe5e7b52479 +RDX: 000000000000003c RSI: 00000000000000e7 RDI: 0000000000000000 +RBP: 00007fe5e7bcd2d0 R08: ffffffffffffffb8 R09: 0000000000000014 +R10: 0000000000000000 R11: 0000000000000246 R12: 00007fe5e7bcd2d0 +R13: 0000000000000000 R14: 00007fe5e7bcdd20 R15: 00007fe5e7b24270 + +The crash can be also be reproduced with the following (with a tc +recompiled to allow for sfq limits of 1): + +tc qdisc add dev dummy0 handle 1: root tbf rate 1Kbit burst 100b lat 1s +../iproute2-6.9.0/tc/tc qdisc add dev dummy0 handle 2: parent 1:10 sfq limit 1 +ifconfig dummy0 up +ping -I dummy0 -f -c2 -W0.1 8.8.8.8 +sleep 1 + +Scenario that triggers the crash: + +* the first packet is sent and queued in TBF and SFQ; qdisc qlen is 1 + +* TBF dequeues: it peeks from SFQ which moves the packet to the + gso_skb list and keeps qdisc qlen set to 1. TBF is out of tokens so + it schedules itself for later. + +* the second packet is sent and TBF tries to queues it to SFQ. qdisc + qlen is now 2 and because the SFQ limit is 1 the packet is dropped + by SFQ. At this point qlen is 1, and all of the SFQ slots are empty, + however q->tail is not NULL. + +At this point, assuming no more packets are queued, when sch_dequeue +runs again it will decrement the qlen for the current empty slot +causing an underflow and the subsequent out of bounds access. + +Reported-by: syzbot +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Octavian Purdila +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20241204030520.2084663-2-tavip@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Harshit Mogalapalli +Signed-off-by: Greg Kroah-Hartman +--- + net/sched/sch_sfq.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/net/sched/sch_sfq.c ++++ b/net/sched/sch_sfq.c +@@ -652,6 +652,10 @@ static int sfq_change(struct Qdisc *sch, + if (!p) + return -ENOMEM; + } ++ if (ctl->limit == 1) { ++ NL_SET_ERR_MSG_MOD(extack, "invalid limit"); ++ return -EINVAL; ++ } + sch_tree_lock(sch); + if (ctl->quantum) + q->quantum = ctl->quantum; diff --git a/queue-5.4/net_sched-sch_sfq-handle-bigger-packets.patch b/queue-5.4/net_sched-sch_sfq-handle-bigger-packets.patch new file mode 100644 index 0000000000..2f15154be0 --- /dev/null +++ b/queue-5.4/net_sched-sch_sfq-handle-bigger-packets.patch @@ -0,0 +1,162 @@ +From stable+bounces-163265-greg=kroah.com@vger.kernel.org Thu Jul 17 14:46:33 2025 +From: Harshit Mogalapalli +Date: Thu, 17 Jul 2025 05:45:52 -0700 +Subject: net_sched: sch_sfq: handle bigger packets +To: stable@vger.kernel.org +Cc: edumazet@google.com, tavip@google.com, "Toke Høiland-Jørgensen" , "Jakub Kicinski" , "Harshit Mogalapalli" +Message-ID: <20250717124556.589696-3-harshit.m.mogalapalli@oracle.com> + +From: Eric Dumazet + +[ Upstream commit e4650d7ae4252f67e997a632adfae0dd74d3a99a ] + +SFQ has an assumption on dealing with packets smaller than 64KB. + +Even before BIG TCP, TCA_STAB can provide arbitrary big values +in qdisc_pkt_len(skb) + +It is time to switch (struct sfq_slot)->allot to a 32bit field. + +sizeof(struct sfq_slot) is now 64 bytes, giving better cache locality. + +Signed-off-by: Eric Dumazet +Reviewed-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20241008111603.653140-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Harshit Mogalapalli +Signed-off-by: Greg Kroah-Hartman +--- + net/sched/sch_sfq.c | 39 +++++++++++++-------------------------- + 1 file changed, 13 insertions(+), 26 deletions(-) + +--- a/net/sched/sch_sfq.c ++++ b/net/sched/sch_sfq.c +@@ -77,12 +77,6 @@ + #define SFQ_EMPTY_SLOT 0xffff + #define SFQ_DEFAULT_HASH_DIVISOR 1024 + +-/* We use 16 bits to store allot, and want to handle packets up to 64K +- * Scale allot by 8 (1<<3) so that no overflow occurs. +- */ +-#define SFQ_ALLOT_SHIFT 3 +-#define SFQ_ALLOT_SIZE(X) DIV_ROUND_UP(X, 1 << SFQ_ALLOT_SHIFT) +- + /* This type should contain at least SFQ_MAX_DEPTH + 1 + SFQ_MAX_FLOWS values */ + typedef u16 sfq_index; + +@@ -104,7 +98,7 @@ struct sfq_slot { + sfq_index next; /* next slot in sfq RR chain */ + struct sfq_head dep; /* anchor in dep[] chains */ + unsigned short hash; /* hash value (index in ht[]) */ +- short allot; /* credit for this slot */ ++ int allot; /* credit for this slot */ + + unsigned int backlog; + struct red_vars vars; +@@ -120,7 +114,6 @@ struct sfq_sched_data { + siphash_key_t perturbation; + u8 cur_depth; /* depth of longest slot */ + u8 flags; +- unsigned short scaled_quantum; /* SFQ_ALLOT_SIZE(quantum) */ + struct tcf_proto __rcu *filter_list; + struct tcf_block *block; + sfq_index *ht; /* Hash table ('divisor' slots) */ +@@ -459,7 +452,7 @@ enqueue: + */ + q->tail = slot; + /* We could use a bigger initial quantum for new flows */ +- slot->allot = q->scaled_quantum; ++ slot->allot = q->quantum; + } + if (++sch->q.qlen <= q->limit) + return NET_XMIT_SUCCESS; +@@ -496,7 +489,7 @@ next_slot: + slot = &q->slots[a]; + if (slot->allot <= 0) { + q->tail = slot; +- slot->allot += q->scaled_quantum; ++ slot->allot += q->quantum; + goto next_slot; + } + skb = slot_dequeue_head(slot); +@@ -515,7 +508,7 @@ next_slot: + } + q->tail->next = next_a; + } else { +- slot->allot -= SFQ_ALLOT_SIZE(qdisc_pkt_len(skb)); ++ slot->allot -= qdisc_pkt_len(skb); + } + return skb; + } +@@ -598,7 +591,7 @@ drop: + q->tail->next = x; + } + q->tail = slot; +- slot->allot = q->scaled_quantum; ++ slot->allot = q->quantum; + } + } + sch->q.qlen -= dropped; +@@ -628,7 +621,8 @@ static void sfq_perturbation(struct time + mod_timer(&q->perturb_timer, jiffies + period); + } + +-static int sfq_change(struct Qdisc *sch, struct nlattr *opt) ++static int sfq_change(struct Qdisc *sch, struct nlattr *opt, ++ struct netlink_ext_ack *extack) + { + struct sfq_sched_data *q = qdisc_priv(sch); + struct tc_sfq_qopt *ctl = nla_data(opt); +@@ -646,14 +640,10 @@ static int sfq_change(struct Qdisc *sch, + (!is_power_of_2(ctl->divisor) || ctl->divisor > 65536)) + return -EINVAL; + +- /* slot->allot is a short, make sure quantum is not too big. */ +- if (ctl->quantum) { +- unsigned int scaled = SFQ_ALLOT_SIZE(ctl->quantum); +- +- if (scaled <= 0 || scaled > SHRT_MAX) +- return -EINVAL; ++ if ((int)ctl->quantum < 0) { ++ NL_SET_ERR_MSG_MOD(extack, "invalid quantum"); ++ return -EINVAL; + } +- + if (ctl_v1 && !red_check_params(ctl_v1->qth_min, ctl_v1->qth_max, + ctl_v1->Wlog, ctl_v1->Scell_log, NULL)) + return -EINVAL; +@@ -663,10 +653,8 @@ static int sfq_change(struct Qdisc *sch, + return -ENOMEM; + } + sch_tree_lock(sch); +- if (ctl->quantum) { ++ if (ctl->quantum) + q->quantum = ctl->quantum; +- q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum); +- } + WRITE_ONCE(q->perturb_period, ctl->perturb_period * HZ); + if (ctl->flows) + q->maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS); +@@ -762,12 +750,11 @@ static int sfq_init(struct Qdisc *sch, s + q->divisor = SFQ_DEFAULT_HASH_DIVISOR; + q->maxflows = SFQ_DEFAULT_FLOWS; + q->quantum = psched_mtu(qdisc_dev(sch)); +- q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum); + q->perturb_period = 0; + get_random_bytes(&q->perturbation, sizeof(q->perturbation)); + + if (opt) { +- int err = sfq_change(sch, opt); ++ int err = sfq_change(sch, opt, extack); + if (err) + return err; + } +@@ -878,7 +865,7 @@ static int sfq_dump_class_stats(struct Q + if (idx != SFQ_EMPTY_SLOT) { + const struct sfq_slot *slot = &q->slots[idx]; + +- xstats.allot = slot->allot << SFQ_ALLOT_SHIFT; ++ xstats.allot = slot->allot; + qs.qlen = slot->qlen; + qs.backlog = slot->backlog; + } diff --git a/queue-5.4/net_sched-sch_sfq-move-the-limit-validation.patch b/queue-5.4/net_sched-sch_sfq-move-the-limit-validation.patch new file mode 100644 index 0000000000..0010c55ef6 --- /dev/null +++ b/queue-5.4/net_sched-sch_sfq-move-the-limit-validation.patch @@ -0,0 +1,84 @@ +From stable+bounces-163262-greg=kroah.com@vger.kernel.org Thu Jul 17 14:46:23 2025 +From: Harshit Mogalapalli +Date: Thu, 17 Jul 2025 05:45:55 -0700 +Subject: net_sched: sch_sfq: move the limit validation +To: stable@vger.kernel.org +Cc: edumazet@google.com, tavip@google.com, syzbot , Cong Wang , "David S. Miller" , Harshit Mogalapalli +Message-ID: <20250717124556.589696-6-harshit.m.mogalapalli@oracle.com> + +From: Octavian Purdila + +[ Upstream commit b3bf8f63e6179076b57c9de660c9f80b5abefe70 ] + +It is not sufficient to directly validate the limit on the data that +the user passes as it can be updated based on how the other parameters +are changed. + +Move the check at the end of the configuration update process to also +catch scenarios where the limit is indirectly updated, for example +with the following configurations: + +tc qdisc add dev dummy0 handle 1: root sfq limit 2 flows 1 depth 1 +tc qdisc add dev dummy0 handle 1: root sfq limit 2 flows 1 divisor 1 + +This fixes the following syzkaller reported crash: + +------------[ cut here ]------------ +UBSAN: array-index-out-of-bounds in net/sched/sch_sfq.c:203:6 +index 65535 is out of range for type 'struct sfq_head[128]' +CPU: 1 UID: 0 PID: 3037 Comm: syz.2.16 Not tainted 6.14.0-rc2-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 12/27/2024 +Call Trace: + + __dump_stack lib/dump_stack.c:94 [inline] + dump_stack_lvl+0x201/0x300 lib/dump_stack.c:120 + ubsan_epilogue lib/ubsan.c:231 [inline] + __ubsan_handle_out_of_bounds+0xf5/0x120 lib/ubsan.c:429 + sfq_link net/sched/sch_sfq.c:203 [inline] + sfq_dec+0x53c/0x610 net/sched/sch_sfq.c:231 + sfq_dequeue+0x34e/0x8c0 net/sched/sch_sfq.c:493 + sfq_reset+0x17/0x60 net/sched/sch_sfq.c:518 + qdisc_reset+0x12e/0x600 net/sched/sch_generic.c:1035 + tbf_reset+0x41/0x110 net/sched/sch_tbf.c:339 + qdisc_reset+0x12e/0x600 net/sched/sch_generic.c:1035 + dev_reset_queue+0x100/0x1b0 net/sched/sch_generic.c:1311 + netdev_for_each_tx_queue include/linux/netdevice.h:2590 [inline] + dev_deactivate_many+0x7e5/0xe70 net/sched/sch_generic.c:1375 + +Reported-by: syzbot +Fixes: 10685681bafc ("net_sched: sch_sfq: don't allow 1 packet limit") +Signed-off-by: Octavian Purdila +Acked-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Harshit Mogalapalli +Signed-off-by: Greg Kroah-Hartman +--- + net/sched/sch_sfq.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/net/sched/sch_sfq.c ++++ b/net/sched/sch_sfq.c +@@ -661,10 +661,6 @@ static int sfq_change(struct Qdisc *sch, + if (!p) + return -ENOMEM; + } +- if (ctl->limit == 1) { +- NL_SET_ERR_MSG_MOD(extack, "invalid limit"); +- return -EINVAL; +- } + + sch_tree_lock(sch); + +@@ -705,6 +701,12 @@ static int sfq_change(struct Qdisc *sch, + limit = min_t(u32, ctl->limit, maxdepth * maxflows); + maxflows = min_t(u32, maxflows, limit); + } ++ if (limit == 1) { ++ sch_tree_unlock(sch); ++ kfree(p); ++ NL_SET_ERR_MSG_MOD(extack, "invalid limit"); ++ return -EINVAL; ++ } + + /* commit configuration */ + q->limit = limit; diff --git a/queue-5.4/net_sched-sch_sfq-reject-invalid-perturb-period.patch b/queue-5.4/net_sched-sch_sfq-reject-invalid-perturb-period.patch new file mode 100644 index 0000000000..09c626c7f2 --- /dev/null +++ b/queue-5.4/net_sched-sch_sfq-reject-invalid-perturb-period.patch @@ -0,0 +1,76 @@ +From stable+bounces-163263-greg=kroah.com@vger.kernel.org Thu Jul 17 14:46:31 2025 +From: Harshit Mogalapalli +Date: Thu, 17 Jul 2025 05:45:56 -0700 +Subject: net_sched: sch_sfq: reject invalid perturb period +To: stable@vger.kernel.org +Cc: edumazet@google.com, tavip@google.com, Gerrard Tai , Jakub Kicinski , Harshit Mogalapalli +Message-ID: <20250717124556.589696-7-harshit.m.mogalapalli@oracle.com> + +From: Eric Dumazet + +[ Upstream commit 7ca52541c05c832d32b112274f81a985101f9ba8 ] + +Gerrard Tai reported that SFQ perturb_period has no range check yet, +and this can be used to trigger a race condition fixed in a separate patch. + +We want to make sure ctl->perturb_period * HZ will not overflow +and is positive. + +Tested: + +tc qd add dev lo root sfq perturb -10 # negative value : error +Error: sch_sfq: invalid perturb period. + +tc qd add dev lo root sfq perturb 1000000000 # too big : error +Error: sch_sfq: invalid perturb period. + +tc qd add dev lo root sfq perturb 2000000 # acceptable value +tc -s -d qd sh dev lo +qdisc sfq 8005: root refcnt 2 limit 127p quantum 64Kb depth 127 flows 128 divisor 1024 perturb 2000000sec + Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) + backlog 0b 0p requeues 0 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: Gerrard Tai +Signed-off-by: Eric Dumazet +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20250611083501.1810459-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Harshit Mogalapalli +Signed-off-by: Greg Kroah-Hartman +--- + net/sched/sch_sfq.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/net/sched/sch_sfq.c ++++ b/net/sched/sch_sfq.c +@@ -653,6 +653,14 @@ static int sfq_change(struct Qdisc *sch, + NL_SET_ERR_MSG_MOD(extack, "invalid quantum"); + return -EINVAL; + } ++ ++ if (ctl->perturb_period < 0 || ++ ctl->perturb_period > INT_MAX / HZ) { ++ NL_SET_ERR_MSG_MOD(extack, "invalid perturb period"); ++ return -EINVAL; ++ } ++ perturb_period = ctl->perturb_period * HZ; ++ + if (ctl_v1 && !red_check_params(ctl_v1->qth_min, ctl_v1->qth_max, + ctl_v1->Wlog, ctl_v1->Scell_log, NULL)) + return -EINVAL; +@@ -669,14 +677,12 @@ static int sfq_change(struct Qdisc *sch, + headdrop = q->headdrop; + maxdepth = q->maxdepth; + maxflows = q->maxflows; +- perturb_period = q->perturb_period; + quantum = q->quantum; + flags = q->flags; + + /* update and validate configuration */ + if (ctl->quantum) + quantum = ctl->quantum; +- perturb_period = ctl->perturb_period * HZ; + if (ctl->flows) + maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS); + if (ctl->divisor) { diff --git a/queue-5.4/net_sched-sch_sfq-use-a-temporary-work-area-for-validating-configuration.patch b/queue-5.4/net_sched-sch_sfq-use-a-temporary-work-area-for-validating-configuration.patch new file mode 100644 index 0000000000..607149c464 --- /dev/null +++ b/queue-5.4/net_sched-sch_sfq-use-a-temporary-work-area-for-validating-configuration.patch @@ -0,0 +1,121 @@ +From stable+bounces-163261-greg=kroah.com@vger.kernel.org Thu Jul 17 14:46:23 2025 +From: Harshit Mogalapalli +Date: Thu, 17 Jul 2025 05:45:54 -0700 +Subject: net_sched: sch_sfq: use a temporary work area for validating configuration +To: stable@vger.kernel.org +Cc: edumazet@google.com, tavip@google.com, Cong Wang , "David S. Miller" , Harshit Mogalapalli +Message-ID: <20250717124556.589696-5-harshit.m.mogalapalli@oracle.com> + +From: Octavian Purdila + +[ Upstream commit 8c0cea59d40cf6dd13c2950437631dd614fbade6 ] + +Many configuration parameters have influence on others (e.g. divisor +-> flows -> limit, depth -> limit) and so it is difficult to correctly +do all of the validation before applying the configuration. And if a +validation error is detected late it is difficult to roll back a +partially applied configuration. + +To avoid these issues use a temporary work area to update and validate +the configuration and only then apply the configuration to the +internal state. + +Signed-off-by: Octavian Purdila +Acked-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Harshit Mogalapalli +Signed-off-by: Greg Kroah-Hartman +--- + net/sched/sch_sfq.c | 56 ++++++++++++++++++++++++++++++++++++++++------------ + 1 file changed, 44 insertions(+), 12 deletions(-) + +--- a/net/sched/sch_sfq.c ++++ b/net/sched/sch_sfq.c +@@ -631,6 +631,15 @@ static int sfq_change(struct Qdisc *sch, + struct red_parms *p = NULL; + struct sk_buff *to_free = NULL; + struct sk_buff *tail = NULL; ++ unsigned int maxflows; ++ unsigned int quantum; ++ unsigned int divisor; ++ int perturb_period; ++ u8 headdrop; ++ u8 maxdepth; ++ int limit; ++ u8 flags; ++ + + if (opt->nla_len < nla_attr_size(sizeof(*ctl))) + return -EINVAL; +@@ -656,36 +665,59 @@ static int sfq_change(struct Qdisc *sch, + NL_SET_ERR_MSG_MOD(extack, "invalid limit"); + return -EINVAL; + } ++ + sch_tree_lock(sch); ++ ++ limit = q->limit; ++ divisor = q->divisor; ++ headdrop = q->headdrop; ++ maxdepth = q->maxdepth; ++ maxflows = q->maxflows; ++ perturb_period = q->perturb_period; ++ quantum = q->quantum; ++ flags = q->flags; ++ ++ /* update and validate configuration */ + if (ctl->quantum) +- q->quantum = ctl->quantum; +- WRITE_ONCE(q->perturb_period, ctl->perturb_period * HZ); ++ quantum = ctl->quantum; ++ perturb_period = ctl->perturb_period * HZ; + if (ctl->flows) +- q->maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS); ++ maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS); + if (ctl->divisor) { +- q->divisor = ctl->divisor; +- q->maxflows = min_t(u32, q->maxflows, q->divisor); ++ divisor = ctl->divisor; ++ maxflows = min_t(u32, maxflows, divisor); + } + if (ctl_v1) { + if (ctl_v1->depth) +- q->maxdepth = min_t(u32, ctl_v1->depth, SFQ_MAX_DEPTH); ++ maxdepth = min_t(u32, ctl_v1->depth, SFQ_MAX_DEPTH); + if (p) { +- swap(q->red_parms, p); +- red_set_parms(q->red_parms, ++ red_set_parms(p, + ctl_v1->qth_min, ctl_v1->qth_max, + ctl_v1->Wlog, + ctl_v1->Plog, ctl_v1->Scell_log, + NULL, + ctl_v1->max_P); + } +- q->flags = ctl_v1->flags; +- q->headdrop = ctl_v1->headdrop; ++ flags = ctl_v1->flags; ++ headdrop = ctl_v1->headdrop; + } + if (ctl->limit) { +- q->limit = min_t(u32, ctl->limit, q->maxdepth * q->maxflows); +- q->maxflows = min_t(u32, q->maxflows, q->limit); ++ limit = min_t(u32, ctl->limit, maxdepth * maxflows); ++ maxflows = min_t(u32, maxflows, limit); + } + ++ /* commit configuration */ ++ q->limit = limit; ++ q->divisor = divisor; ++ q->headdrop = headdrop; ++ q->maxdepth = maxdepth; ++ q->maxflows = maxflows; ++ WRITE_ONCE(q->perturb_period, perturb_period); ++ q->quantum = quantum; ++ q->flags = flags; ++ if (p) ++ swap(q->red_parms, p); ++ + qlen = sch->q.qlen; + while (sch->q.qlen > q->limit) { + dropped += sfq_drop(sch, &to_free); diff --git a/queue-5.4/power-supply-bq24190-fix-use-after-free-bug-in-bq24190_remove-due-to-race-condition.patch b/queue-5.4/power-supply-bq24190-fix-use-after-free-bug-in-bq24190_remove-due-to-race-condition.patch new file mode 100644 index 0000000000..ada1e143bb --- /dev/null +++ b/queue-5.4/power-supply-bq24190-fix-use-after-free-bug-in-bq24190_remove-due-to-race-condition.patch @@ -0,0 +1,54 @@ +From stable+bounces-163575-greg=kroah.com@vger.kernel.org Mon Jul 21 13:49:35 2025 +From: skulkarni@mvista.com +Date: Mon, 21 Jul 2025 17:18:46 +0530 +Subject: power: supply: bq24190: Fix use after free bug in bq24190_remove due to race condition +To: stable@vger.kernel.org +Cc: Zheng Wang , Sebastian Reichel , Shubham Kulkarni +Message-ID: <20250721114846.1360952-4-skulkarni@mvista.com> + +From: Zheng Wang + +[ Upstream commit 47c29d69212911f50bdcdd0564b5999a559010d4 ] + +In bq24190_probe, &bdi->input_current_limit_work is bound +with bq24190_input_current_limit_work. When external power +changed, it will call bq24190_charger_external_power_changed + to start the work. + +If we remove the module which will call bq24190_remove to make +cleanup, there may be a unfinished work. The possible +sequence is as follows: + +CPU0 CPUc1 + + |bq24190_input_current_limit_work +bq24190_remove | +power_supply_unregister | +device_unregister | +power_supply_dev_release| +kfree(psy) | + | + | power_supply_get_property_from_supplier + | //use + +Fix it by finishing the work before cleanup in the bq24190_remove + +Fixes: 97774672573a ("power_supply: Initialize changed_work before calling device_add") +Signed-off-by: Zheng Wang +Signed-off-by: Sebastian Reichel +Signed-off-by: Shubham Kulkarni +Signed-off-by: Greg Kroah-Hartman +--- + drivers/power/supply/bq24190_charger.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/power/supply/bq24190_charger.c ++++ b/drivers/power/supply/bq24190_charger.c +@@ -1845,6 +1845,7 @@ static int bq24190_remove(struct i2c_cli + struct bq24190_dev_info *bdi = i2c_get_clientdata(client); + int error; + ++ cancel_delayed_work_sync(&bdi->input_current_limit_work); + error = pm_runtime_resume_and_get(bdi->dev); + if (error < 0) + dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error); diff --git a/queue-5.4/power-supply-bq24190_charger-fix-runtime-pm-imbalance-on-error.patch b/queue-5.4/power-supply-bq24190_charger-fix-runtime-pm-imbalance-on-error.patch new file mode 100644 index 0000000000..cb75eb85e8 --- /dev/null +++ b/queue-5.4/power-supply-bq24190_charger-fix-runtime-pm-imbalance-on-error.patch @@ -0,0 +1,40 @@ +From stable+bounces-163573-greg=kroah.com@vger.kernel.org Mon Jul 21 13:49:58 2025 +From: skulkarni@mvista.com +Date: Mon, 21 Jul 2025 17:18:44 +0530 +Subject: power: supply: bq24190_charger: Fix runtime PM imbalance on error +To: stable@vger.kernel.org +Cc: Dinghao Liu , "Rafael J . Wysocki" , Sebastian Reichel , Shubham Kulkarni +Message-ID: <20250721114846.1360952-2-skulkarni@mvista.com> + +From: Dinghao Liu + +[ Upstream commit 1a37a039711610dd53ec03d8cab9e81875338225 ] + +pm_runtime_get_sync() increments the runtime PM usage counter even +it returns an error code. Thus a pairing decrement is needed on +the error handling path to keep the counter balanced. + +Signed-off-by: Dinghao Liu +Reviewed-by: Rafael J. Wysocki +Signed-off-by: Sebastian Reichel +Stable-dep-of: 47c29d692129 ("power: supply: bq24190: Fix use after free bug in bq24190_remove due to race condition") +Signed-off-by: Shubham Kulkarni +Signed-off-by: Greg Kroah-Hartman +--- + drivers/power/supply/bq24190_charger.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/power/supply/bq24190_charger.c ++++ b/drivers/power/supply/bq24190_charger.c +@@ -484,8 +484,10 @@ static ssize_t bq24190_sysfs_store(struc + return ret; + + ret = pm_runtime_get_sync(bdi->dev); +- if (ret < 0) ++ if (ret < 0) { ++ pm_runtime_put_noidle(bdi->dev); + return ret; ++ } + + ret = bq24190_write_mask(bdi, info->reg, info->mask, info->shift, v); + if (ret) diff --git a/queue-5.4/power-supply-bq24190_charger-using-pm_runtime_resume_and_get-instead-of-pm_runtime_get_sync.patch b/queue-5.4/power-supply-bq24190_charger-using-pm_runtime_resume_and_get-instead-of-pm_runtime_get_sync.patch new file mode 100644 index 0000000000..68b8e7f90e --- /dev/null +++ b/queue-5.4/power-supply-bq24190_charger-using-pm_runtime_resume_and_get-instead-of-pm_runtime_get_sync.patch @@ -0,0 +1,190 @@ +From stable+bounces-163574-greg=kroah.com@vger.kernel.org Mon Jul 21 13:49:34 2025 +From: skulkarni@mvista.com +Date: Mon, 21 Jul 2025 17:18:45 +0530 +Subject: power: supply: bq24190_charger: using pm_runtime_resume_and_get instead of pm_runtime_get_sync +To: stable@vger.kernel.org +Cc: Minghao Chi , Zeal Robot , Sebastian Reichel , Shubham Kulkarni +Message-ID: <20250721114846.1360952-3-skulkarni@mvista.com> + +From: Minghao Chi + +[ Upstream commit d96a89407e5f682d1cb22569d91784506c784863 ] + +Using pm_runtime_resume_and_get is more appropriate +for simplifing code + +Reported-by: Zeal Robot +Signed-off-by: Minghao Chi +Signed-off-by: Sebastian Reichel +[ skulkarni: Minor changes in hunk #3/12 wrt the mainline commit ] +Stable-dep-of: 47c29d692129 ("power: supply: bq24190: Fix use after free bug in bq24190_remove due to race condition") +Signed-off-by: Shubham Kulkarni +Signed-off-by: Greg Kroah-Hartman +--- + drivers/power/supply/bq24190_charger.c | 63 +++++++++++---------------------- + 1 file changed, 21 insertions(+), 42 deletions(-) + +--- a/drivers/power/supply/bq24190_charger.c ++++ b/drivers/power/supply/bq24190_charger.c +@@ -448,11 +448,9 @@ static ssize_t bq24190_sysfs_show(struct + if (!info) + return -EINVAL; + +- ret = pm_runtime_get_sync(bdi->dev); +- if (ret < 0) { +- pm_runtime_put_noidle(bdi->dev); ++ ret = pm_runtime_resume_and_get(bdi->dev); ++ if (ret < 0) + return ret; +- } + + ret = bq24190_read_mask(bdi, info->reg, info->mask, info->shift, &v); + if (ret) +@@ -483,11 +481,9 @@ static ssize_t bq24190_sysfs_store(struc + if (ret < 0) + return ret; + +- ret = pm_runtime_get_sync(bdi->dev); +- if (ret < 0) { +- pm_runtime_put_noidle(bdi->dev); ++ ret = pm_runtime_resume_and_get(bdi->dev); ++ if (ret < 0) + return ret; +- } + + ret = bq24190_write_mask(bdi, info->reg, info->mask, info->shift, v); + if (ret) +@@ -506,10 +502,9 @@ static int bq24190_set_charge_mode(struc + struct bq24190_dev_info *bdi = rdev_get_drvdata(dev); + int ret; + +- ret = pm_runtime_get_sync(bdi->dev); ++ ret = pm_runtime_resume_and_get(bdi->dev); + if (ret < 0) { + dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", ret); +- pm_runtime_put_noidle(bdi->dev); + return ret; + } + +@@ -539,10 +534,9 @@ static int bq24190_vbus_is_enabled(struc + int ret; + u8 val; + +- ret = pm_runtime_get_sync(bdi->dev); ++ ret = pm_runtime_resume_and_get(bdi->dev); + if (ret < 0) { + dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", ret); +- pm_runtime_put_noidle(bdi->dev); + return ret; + } + +@@ -1083,11 +1077,9 @@ static int bq24190_charger_get_property( + + dev_dbg(bdi->dev, "prop: %d\n", psp); + +- ret = pm_runtime_get_sync(bdi->dev); +- if (ret < 0) { +- pm_runtime_put_noidle(bdi->dev); ++ ret = pm_runtime_resume_and_get(bdi->dev); ++ if (ret < 0) + return ret; +- } + + switch (psp) { + case POWER_SUPPLY_PROP_CHARGE_TYPE: +@@ -1157,11 +1149,9 @@ static int bq24190_charger_set_property( + + dev_dbg(bdi->dev, "prop: %d\n", psp); + +- ret = pm_runtime_get_sync(bdi->dev); +- if (ret < 0) { +- pm_runtime_put_noidle(bdi->dev); ++ ret = pm_runtime_resume_and_get(bdi->dev); ++ if (ret < 0) + return ret; +- } + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: +@@ -1431,11 +1421,9 @@ static int bq24190_battery_get_property( + dev_warn(bdi->dev, "warning: /sys/class/power_supply/bq24190-battery is deprecated\n"); + dev_dbg(bdi->dev, "prop: %d\n", psp); + +- ret = pm_runtime_get_sync(bdi->dev); +- if (ret < 0) { +- pm_runtime_put_noidle(bdi->dev); ++ ret = pm_runtime_resume_and_get(bdi->dev); ++ if (ret < 0) + return ret; +- } + + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: +@@ -1479,11 +1467,9 @@ static int bq24190_battery_set_property( + dev_warn(bdi->dev, "warning: /sys/class/power_supply/bq24190-battery is deprecated\n"); + dev_dbg(bdi->dev, "prop: %d\n", psp); + +- ret = pm_runtime_get_sync(bdi->dev); +- if (ret < 0) { +- pm_runtime_put_noidle(bdi->dev); ++ ret = pm_runtime_resume_and_get(bdi->dev); ++ if (ret < 0) + return ret; +- } + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: +@@ -1637,10 +1623,9 @@ static irqreturn_t bq24190_irq_handler_t + int error; + + bdi->irq_event = true; +- error = pm_runtime_get_sync(bdi->dev); ++ error = pm_runtime_resume_and_get(bdi->dev); + if (error < 0) { + dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error); +- pm_runtime_put_noidle(bdi->dev); + return IRQ_NONE; + } + bq24190_check_status(bdi); +@@ -1860,11 +1845,9 @@ static int bq24190_remove(struct i2c_cli + struct bq24190_dev_info *bdi = i2c_get_clientdata(client); + int error; + +- error = pm_runtime_get_sync(bdi->dev); +- if (error < 0) { ++ error = pm_runtime_resume_and_get(bdi->dev); ++ if (error < 0) + dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error); +- pm_runtime_put_noidle(bdi->dev); +- } + + bq24190_register_reset(bdi); + if (bdi->battery) +@@ -1913,11 +1896,9 @@ static __maybe_unused int bq24190_pm_sus + struct bq24190_dev_info *bdi = i2c_get_clientdata(client); + int error; + +- error = pm_runtime_get_sync(bdi->dev); +- if (error < 0) { ++ error = pm_runtime_resume_and_get(bdi->dev); ++ if (error < 0) + dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error); +- pm_runtime_put_noidle(bdi->dev); +- } + + bq24190_register_reset(bdi); + +@@ -1938,11 +1919,9 @@ static __maybe_unused int bq24190_pm_res + bdi->f_reg = 0; + bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */ + +- error = pm_runtime_get_sync(bdi->dev); +- if (error < 0) { ++ error = pm_runtime_resume_and_get(bdi->dev); ++ if (error < 0) + dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error); +- pm_runtime_put_noidle(bdi->dev); +- } + + bq24190_register_reset(bdi); + bq24190_set_config(bdi); diff --git a/queue-5.4/series b/queue-5.4/series index 9c85644b64..f83ae43b7a 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -40,3 +40,14 @@ net-sched-return-null-when-htb_lookup_leaf-encounter.patch usb-musb-fix-gadget-state-on-disconnect.patch usb-dwc3-qcom-don-t-leave-bcr-asserted.patch asoc-fsl_sai-force-a-software-reset-when-starting-in-consumer-mode.patch +virtio-net-ensure-the-received-length-does-not-exceed-allocated-size.patch +xhci-disable-stream-for-xhc-controller-with-xhci_broken_streams.patch +power-supply-bq24190_charger-fix-runtime-pm-imbalance-on-error.patch +power-supply-bq24190_charger-using-pm_runtime_resume_and_get-instead-of-pm_runtime_get_sync.patch +power-supply-bq24190-fix-use-after-free-bug-in-bq24190_remove-due-to-race-condition.patch +net_sched-sch_sfq-annotate-data-races-around-q-perturb_period.patch +net_sched-sch_sfq-handle-bigger-packets.patch +net_sched-sch_sfq-don-t-allow-1-packet-limit.patch +net_sched-sch_sfq-use-a-temporary-work-area-for-validating-configuration.patch +net_sched-sch_sfq-move-the-limit-validation.patch +net_sched-sch_sfq-reject-invalid-perturb-period.patch diff --git a/queue-5.4/virtio-net-ensure-the-received-length-does-not-exceed-allocated-size.patch b/queue-5.4/virtio-net-ensure-the-received-length-does-not-exceed-allocated-size.patch new file mode 100644 index 0000000000..4f195379bb --- /dev/null +++ b/queue-5.4/virtio-net-ensure-the-received-length-does-not-exceed-allocated-size.patch @@ -0,0 +1,112 @@ +From 315dbdd7cdf6aa533829774caaf4d25f1fd20e73 Mon Sep 17 00:00:00 2001 +From: Bui Quang Minh +Date: Mon, 30 Jun 2025 21:42:10 +0700 +Subject: virtio-net: ensure the received length does not exceed allocated size + +From: Bui Quang Minh + +commit 315dbdd7cdf6aa533829774caaf4d25f1fd20e73 upstream. + +In xdp_linearize_page, when reading the following buffers from the ring, +we forget to check the received length with the true allocate size. This +can lead to an out-of-bound read. This commit adds that missing check. + +Cc: +Fixes: 4941d472bf95 ("virtio-net: do not reset during XDP set") +Signed-off-by: Bui Quang Minh +Acked-by: Jason Wang +Link: https://patch.msgid.link/20250630144212.48471-2-minhquangbui99@gmail.com +Signed-off-by: Paolo Abeni +[ adapted virtqueue_get_buf() to virtqueue_get_buf_ctx() ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/virtio_net.c | 38 ++++++++++++++++++++++++++++++++++---- + 1 file changed, 34 insertions(+), 4 deletions(-) + +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -394,6 +394,26 @@ static unsigned int mergeable_ctx_to_tru + return (unsigned long)mrg_ctx & ((1 << MRG_CTX_HEADER_SHIFT) - 1); + } + ++static int check_mergeable_len(struct net_device *dev, void *mrg_ctx, ++ unsigned int len) ++{ ++ unsigned int headroom, tailroom, room, truesize; ++ ++ truesize = mergeable_ctx_to_truesize(mrg_ctx); ++ headroom = mergeable_ctx_to_headroom(mrg_ctx); ++ tailroom = headroom ? sizeof(struct skb_shared_info) : 0; ++ room = SKB_DATA_ALIGN(headroom + tailroom); ++ ++ if (len > truesize - room) { ++ pr_debug("%s: rx error: len %u exceeds truesize %lu\n", ++ dev->name, len, (unsigned long)(truesize - room)); ++ dev->stats.rx_length_errors++; ++ return -1; ++ } ++ ++ return 0; ++} ++ + /* Called from bottom half context */ + static struct sk_buff *page_to_skb(struct virtnet_info *vi, + struct receive_queue *rq, +@@ -639,7 +659,8 @@ static unsigned int virtnet_get_headroom + * across multiple buffers (num_buf > 1), and we make sure buffers + * have enough headroom. + */ +-static struct page *xdp_linearize_page(struct receive_queue *rq, ++static struct page *xdp_linearize_page(struct net_device *dev, ++ struct receive_queue *rq, + u16 *num_buf, + struct page *p, + int offset, +@@ -659,18 +680,27 @@ static struct page *xdp_linearize_page(s + memcpy(page_address(page) + page_off, page_address(p) + offset, *len); + page_off += *len; + ++ /* Only mergeable mode can go inside this while loop. In small mode, ++ * *num_buf == 1, so it cannot go inside. ++ */ + while (--*num_buf) { + unsigned int buflen; + void *buf; ++ void *ctx; + int off; + +- buf = virtqueue_get_buf(rq->vq, &buflen); ++ buf = virtqueue_get_buf_ctx(rq->vq, &buflen, &ctx); + if (unlikely(!buf)) + goto err_buf; + + p = virt_to_head_page(buf); + off = buf - page_address(p); + ++ if (check_mergeable_len(dev, ctx, buflen)) { ++ put_page(p); ++ goto err_buf; ++ } ++ + /* guard against a misconfigured or uncooperative backend that + * is sending packet larger than the MTU. + */ +@@ -745,7 +775,7 @@ static struct sk_buff *receive_small(str + headroom = vi->hdr_len + header_offset; + buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); +- xdp_page = xdp_linearize_page(rq, &num_buf, page, ++ xdp_page = xdp_linearize_page(dev, rq, &num_buf, page, + offset, header_offset, + &tlen); + if (!xdp_page) +@@ -910,7 +940,7 @@ static struct sk_buff *receive_mergeable + if (unlikely(num_buf > 1 || + headroom < virtnet_get_headroom(vi))) { + /* linearize data for XDP */ +- xdp_page = xdp_linearize_page(rq, &num_buf, ++ xdp_page = xdp_linearize_page(dev, rq, &num_buf, + page, offset, + VIRTIO_XDP_HEADROOM, + &len); diff --git a/queue-5.4/xhci-disable-stream-for-xhc-controller-with-xhci_broken_streams.patch b/queue-5.4/xhci-disable-stream-for-xhc-controller-with-xhci_broken_streams.patch new file mode 100644 index 0000000000..778ee3fdce --- /dev/null +++ b/queue-5.4/xhci-disable-stream-for-xhc-controller-with-xhci_broken_streams.patch @@ -0,0 +1,35 @@ +From cd65ee81240e8bc3c3119b46db7f60c80864b90b Mon Sep 17 00:00:00 2001 +From: Hongyu Xie +Date: Fri, 27 Jun 2025 17:41:20 +0300 +Subject: xhci: Disable stream for xHC controller with XHCI_BROKEN_STREAMS + +From: Hongyu Xie + +commit cd65ee81240e8bc3c3119b46db7f60c80864b90b upstream. + +Disable stream for platform xHC controller with broken stream. + +Fixes: 14aec589327a6 ("storage: accept some UAS devices if streams are unavailable") +Cc: stable +Signed-off-by: Hongyu Xie +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20250627144127.3889714-3-mathias.nyman@linux.intel.com +[ removed xhci_get_usb3_hcd() call ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/xhci-plat.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -333,7 +333,8 @@ static int xhci_plat_probe(struct platfo + if (ret) + goto disable_usb_phy; + +- if (HCC_MAX_PSA(xhci->hcc_params) >= 4) ++ if (HCC_MAX_PSA(xhci->hcc_params) >= 4 && ++ !(xhci->quirks & XHCI_BROKEN_STREAMS)) + xhci->shared_hcd->can_do_streams = 1; + + ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);