diff options
17 files changed, 1880 insertions, 0 deletions
diff --git a/queue-5.10/aoe-clean-device-rq_list-in-aoedev_downdev.patch b/queue-5.10/aoe-clean-device-rq_list-in-aoedev_downdev.patch new file mode 100644 index 0000000000..e8ad7c1c3d --- /dev/null +++ b/queue-5.10/aoe-clean-device-rq_list-in-aoedev_downdev.patch @@ -0,0 +1,56 @@ +From 7818f9367dd2b8ffb557339e154f2838c40918fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 10 Jun 2025 17:05:59 +0000 +Subject: aoe: clean device rq_list in aoedev_downdev() + +From: Justin Sanders <jsanders.devel@gmail.com> + +[ Upstream commit 7f90d45e57cb2ef1f0adcaf925ddffdfc5e680ca ] + +An aoe device's rq_list contains accepted block requests that are +waiting to be transmitted to the aoe target. This queue was added as +part of the conversion to blk_mq. However, the queue was not cleaned out +when an aoe device is downed which caused blk_mq_freeze_queue() to sleep +indefinitely waiting for those requests to complete, causing a hang. This +fix cleans out the queue before calling blk_mq_freeze_queue(). + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=212665 +Fixes: 3582dd291788 ("aoe: convert aoeblk to blk-mq") +Signed-off-by: Justin Sanders <jsanders.devel@gmail.com> +Link: https://lore.kernel.org/r/20250610170600.869-1-jsanders.devel@gmail.com +Tested-By: Valentin Kleibel <valentin@vrvis.at> +Signed-off-by: Jens Axboe <axboe@kernel.dk> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/block/aoe/aoedev.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c +index e2ea2356da061..ec043f4bb1f2e 100644 +--- a/drivers/block/aoe/aoedev.c ++++ b/drivers/block/aoe/aoedev.c +@@ -198,6 +198,7 @@ aoedev_downdev(struct aoedev *d) + { + struct aoetgt *t, **tt, **te; + struct list_head *head, *pos, *nx; ++ struct request *rq, *rqnext; + int i; + + d->flags &= ~DEVFL_UP; +@@ -223,6 +224,13 @@ aoedev_downdev(struct aoedev *d) + /* clean out the in-process request (if any) */ + aoe_failip(d); + ++ /* clean out any queued block requests */ ++ list_for_each_entry_safe(rq, rqnext, &d->rq_list, queuelist) { ++ list_del_init(&rq->queuelist); ++ blk_mq_start_request(rq); ++ blk_mq_end_request(rq, BLK_STS_IOERR); ++ } ++ + /* fast fail all pending I/O */ + if (d->blkq) { + /* UP is cleared, freeze+quiesce to insure all are errored */ +-- +2.39.5 + diff --git a/queue-5.10/atm-atmtcp-free-invalid-length-skb-in-atmtcp_c_send.patch b/queue-5.10/atm-atmtcp-free-invalid-length-skb-in-atmtcp_c_send.patch new file mode 100644 index 0000000000..97715b8873 --- /dev/null +++ b/queue-5.10/atm-atmtcp-free-invalid-length-skb-in-atmtcp_c_send.patch @@ -0,0 +1,95 @@ +From 60765d4f0d906bd76942609f86c7ae39038daede Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 16 Jun 2025 11:21:14 -0700 +Subject: atm: atmtcp: Free invalid length skb in atmtcp_c_send(). + +From: Kuniyuki Iwashima <kuniyu@google.com> + +[ Upstream commit 2f370ae1fb6317985f3497b1bb80d457508ca2f7 ] + +syzbot reported the splat below. [0] + +vcc_sendmsg() copies data passed from userspace to skb and passes +it to vcc->dev->ops->send(). + +atmtcp_c_send() accesses skb->data as struct atmtcp_hdr after +checking if skb->len is 0, but it's not enough. + +Also, when skb->len == 0, skb and sk (vcc) were leaked because +dev_kfree_skb() is not called and sk_wmem_alloc adjustment is missing +to revert atm_account_tx() in vcc_sendmsg(), which is expected +to be done in atm_pop_raw(). + +Let's properly free skb with an invalid length in atmtcp_c_send(). + +[0]: +BUG: KMSAN: uninit-value in atmtcp_c_send+0x255/0xed0 drivers/atm/atmtcp.c:294 + atmtcp_c_send+0x255/0xed0 drivers/atm/atmtcp.c:294 + vcc_sendmsg+0xd7c/0xff0 net/atm/common.c:644 + sock_sendmsg_nosec net/socket.c:712 [inline] + __sock_sendmsg+0x330/0x3d0 net/socket.c:727 + ____sys_sendmsg+0x7e0/0xd80 net/socket.c:2566 + ___sys_sendmsg+0x271/0x3b0 net/socket.c:2620 + __sys_sendmsg net/socket.c:2652 [inline] + __do_sys_sendmsg net/socket.c:2657 [inline] + __se_sys_sendmsg net/socket.c:2655 [inline] + __x64_sys_sendmsg+0x211/0x3e0 net/socket.c:2655 + x64_sys_call+0x32fb/0x3db0 arch/x86/include/generated/asm/syscalls_64.h:47 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xd9/0x210 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Uninit was created at: + slab_post_alloc_hook mm/slub.c:4154 [inline] + slab_alloc_node mm/slub.c:4197 [inline] + kmem_cache_alloc_node_noprof+0x818/0xf00 mm/slub.c:4249 + kmalloc_reserve+0x13c/0x4b0 net/core/skbuff.c:579 + __alloc_skb+0x347/0x7d0 net/core/skbuff.c:670 + alloc_skb include/linux/skbuff.h:1336 [inline] + vcc_sendmsg+0xb40/0xff0 net/atm/common.c:628 + sock_sendmsg_nosec net/socket.c:712 [inline] + __sock_sendmsg+0x330/0x3d0 net/socket.c:727 + ____sys_sendmsg+0x7e0/0xd80 net/socket.c:2566 + ___sys_sendmsg+0x271/0x3b0 net/socket.c:2620 + __sys_sendmsg net/socket.c:2652 [inline] + __do_sys_sendmsg net/socket.c:2657 [inline] + __se_sys_sendmsg net/socket.c:2655 [inline] + __x64_sys_sendmsg+0x211/0x3e0 net/socket.c:2655 + x64_sys_call+0x32fb/0x3db0 arch/x86/include/generated/asm/syscalls_64.h:47 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xd9/0x210 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +CPU: 1 UID: 0 PID: 5798 Comm: syz-executor192 Not tainted 6.16.0-rc1-syzkaller-00010-g2c4a1f3fe03e #0 PREEMPT(undef) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/07/2025 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+1d3c235276f62963e93a@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=1d3c235276f62963e93a +Tested-by: syzbot+1d3c235276f62963e93a@syzkaller.appspotmail.com +Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> +Link: https://patch.msgid.link/20250616182147.963333-2-kuni1840@gmail.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/atm/atmtcp.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c +index 96bea1ab1eccf..ff558908897f3 100644 +--- a/drivers/atm/atmtcp.c ++++ b/drivers/atm/atmtcp.c +@@ -288,7 +288,9 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) + struct sk_buff *new_skb; + int result = 0; + +- if (!skb->len) return 0; ++ if (skb->len < sizeof(struct atmtcp_hdr)) ++ goto done; ++ + dev = vcc->dev_data; + hdr = (struct atmtcp_hdr *) skb->data; + if (hdr->length == ATMTCP_HDR_MAGIC) { +-- +2.39.5 + diff --git a/queue-5.10/calipso-fix-null-ptr-deref-in-calipso_req_-set-del-a.patch b/queue-5.10/calipso-fix-null-ptr-deref-in-calipso_req_-set-del-a.patch new file mode 100644 index 0000000000..867660f309 --- /dev/null +++ b/queue-5.10/calipso-fix-null-ptr-deref-in-calipso_req_-set-del-a.patch @@ -0,0 +1,196 @@ +From cc1f94d02881cc53e74e2ba98241b09916b2e421 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 17 Jun 2025 15:40:42 -0700 +Subject: calipso: Fix null-ptr-deref in calipso_req_{set,del}attr(). + +From: Kuniyuki Iwashima <kuniyu@google.com> + +[ Upstream commit 10876da918fa1aec0227fb4c67647513447f53a9 ] + +syzkaller reported a null-ptr-deref in sock_omalloc() while allocating +a CALIPSO option. [0] + +The NULL is of struct sock, which was fetched by sk_to_full_sk() in +calipso_req_setattr(). + +Since commit a1a5344ddbe8 ("tcp: avoid two atomic ops for syncookies"), +reqsk->rsk_listener could be NULL when SYN Cookie is returned to its +client, as hinted by the leading SYN Cookie log. + +Here are 3 options to fix the bug: + + 1) Return 0 in calipso_req_setattr() + 2) Return an error in calipso_req_setattr() + 3) Alaways set rsk_listener + +1) is no go as it bypasses LSM, but 2) effectively disables SYN Cookie +for CALIPSO. 3) is also no go as there have been many efforts to reduce +atomic ops and make TCP robust against DDoS. See also commit 3b24d854cb35 +("tcp/dccp: do not touch listener sk_refcnt under synflood"). + +As of the blamed commit, SYN Cookie already did not need refcounting, +and no one has stumbled on the bug for 9 years, so no CALIPSO user will +care about SYN Cookie. + +Let's return an error in calipso_req_setattr() and calipso_req_delattr() +in the SYN Cookie case. + +This can be reproduced by [1] on Fedora and now connect() of nc times out. + +[0]: +TCP: request_sock_TCPv6: Possible SYN flooding on port [::]:20002. Sending cookies. +Oops: general protection fault, probably for non-canonical address 0xdffffc0000000006: 0000 [#1] PREEMPT SMP KASAN NOPTI +KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037] +CPU: 3 UID: 0 PID: 12262 Comm: syz.1.2611 Not tainted 6.14.0 #2 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014 +RIP: 0010:read_pnet include/net/net_namespace.h:406 [inline] +RIP: 0010:sock_net include/net/sock.h:655 [inline] +RIP: 0010:sock_kmalloc+0x35/0x170 net/core/sock.c:2806 +Code: 89 d5 41 54 55 89 f5 53 48 89 fb e8 25 e3 c6 fd e8 f0 91 e3 00 48 8d 7b 30 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 26 01 00 00 48 b8 00 00 00 00 00 fc ff df 4c 8b +RSP: 0018:ffff88811af89038 EFLAGS: 00010216 +RAX: dffffc0000000000 RBX: 0000000000000000 RCX: ffff888105266400 +RDX: 0000000000000006 RSI: ffff88800c890000 RDI: 0000000000000030 +RBP: 0000000000000050 R08: 0000000000000000 R09: ffff88810526640e +R10: ffffed1020a4cc81 R11: ffff88810526640f R12: 0000000000000000 +R13: 0000000000000820 R14: ffff888105266400 R15: 0000000000000050 +FS: 00007f0653a07640(0000) GS:ffff88811af80000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007f863ba096f4 CR3: 00000000163c0005 CR4: 0000000000770ef0 +PKRU: 80000000 +Call Trace: + <IRQ> + ipv6_renew_options+0x279/0x950 net/ipv6/exthdrs.c:1288 + calipso_req_setattr+0x181/0x340 net/ipv6/calipso.c:1204 + calipso_req_setattr+0x56/0x80 net/netlabel/netlabel_calipso.c:597 + netlbl_req_setattr+0x18a/0x440 net/netlabel/netlabel_kapi.c:1249 + selinux_netlbl_inet_conn_request+0x1fb/0x320 security/selinux/netlabel.c:342 + selinux_inet_conn_request+0x1eb/0x2c0 security/selinux/hooks.c:5551 + security_inet_conn_request+0x50/0xa0 security/security.c:4945 + tcp_v6_route_req+0x22c/0x550 net/ipv6/tcp_ipv6.c:825 + tcp_conn_request+0xec8/0x2b70 net/ipv4/tcp_input.c:7275 + tcp_v6_conn_request+0x1e3/0x440 net/ipv6/tcp_ipv6.c:1328 + tcp_rcv_state_process+0xafa/0x52b0 net/ipv4/tcp_input.c:6781 + tcp_v6_do_rcv+0x8a6/0x1a40 net/ipv6/tcp_ipv6.c:1667 + tcp_v6_rcv+0x505e/0x5b50 net/ipv6/tcp_ipv6.c:1904 + ip6_protocol_deliver_rcu+0x17c/0x1da0 net/ipv6/ip6_input.c:436 + ip6_input_finish+0x103/0x180 net/ipv6/ip6_input.c:480 + NF_HOOK include/linux/netfilter.h:314 [inline] + NF_HOOK include/linux/netfilter.h:308 [inline] + ip6_input+0x13c/0x6b0 net/ipv6/ip6_input.c:491 + dst_input include/net/dst.h:469 [inline] + ip6_rcv_finish net/ipv6/ip6_input.c:79 [inline] + ip6_rcv_finish+0xb6/0x490 net/ipv6/ip6_input.c:69 + NF_HOOK include/linux/netfilter.h:314 [inline] + NF_HOOK include/linux/netfilter.h:308 [inline] + ipv6_rcv+0xf9/0x490 net/ipv6/ip6_input.c:309 + __netif_receive_skb_one_core+0x12e/0x1f0 net/core/dev.c:5896 + __netif_receive_skb+0x1d/0x170 net/core/dev.c:6009 + process_backlog+0x41e/0x13b0 net/core/dev.c:6357 + __napi_poll+0xbd/0x710 net/core/dev.c:7191 + napi_poll net/core/dev.c:7260 [inline] + net_rx_action+0x9de/0xde0 net/core/dev.c:7382 + handle_softirqs+0x19a/0x770 kernel/softirq.c:561 + do_softirq.part.0+0x36/0x70 kernel/softirq.c:462 + </IRQ> + <TASK> + do_softirq arch/x86/include/asm/preempt.h:26 [inline] + __local_bh_enable_ip+0xf1/0x110 kernel/softirq.c:389 + local_bh_enable include/linux/bottom_half.h:33 [inline] + rcu_read_unlock_bh include/linux/rcupdate.h:919 [inline] + __dev_queue_xmit+0xc2a/0x3c40 net/core/dev.c:4679 + dev_queue_xmit include/linux/netdevice.h:3313 [inline] + neigh_hh_output include/net/neighbour.h:523 [inline] + neigh_output include/net/neighbour.h:537 [inline] + ip6_finish_output2+0xd69/0x1f80 net/ipv6/ip6_output.c:141 + __ip6_finish_output net/ipv6/ip6_output.c:215 [inline] + ip6_finish_output+0x5dc/0xd60 net/ipv6/ip6_output.c:226 + NF_HOOK_COND include/linux/netfilter.h:303 [inline] + ip6_output+0x24b/0x8d0 net/ipv6/ip6_output.c:247 + dst_output include/net/dst.h:459 [inline] + NF_HOOK include/linux/netfilter.h:314 [inline] + NF_HOOK include/linux/netfilter.h:308 [inline] + ip6_xmit+0xbbc/0x20d0 net/ipv6/ip6_output.c:366 + inet6_csk_xmit+0x39a/0x720 net/ipv6/inet6_connection_sock.c:135 + __tcp_transmit_skb+0x1a7b/0x3b40 net/ipv4/tcp_output.c:1471 + tcp_transmit_skb net/ipv4/tcp_output.c:1489 [inline] + tcp_send_syn_data net/ipv4/tcp_output.c:4059 [inline] + tcp_connect+0x1c0c/0x4510 net/ipv4/tcp_output.c:4148 + tcp_v6_connect+0x156c/0x2080 net/ipv6/tcp_ipv6.c:333 + __inet_stream_connect+0x3a7/0xed0 net/ipv4/af_inet.c:677 + tcp_sendmsg_fastopen+0x3e2/0x710 net/ipv4/tcp.c:1039 + tcp_sendmsg_locked+0x1e82/0x3570 net/ipv4/tcp.c:1091 + tcp_sendmsg+0x2f/0x50 net/ipv4/tcp.c:1358 + inet6_sendmsg+0xb9/0x150 net/ipv6/af_inet6.c:659 + sock_sendmsg_nosec net/socket.c:718 [inline] + __sock_sendmsg+0xf4/0x2a0 net/socket.c:733 + __sys_sendto+0x29a/0x390 net/socket.c:2187 + __do_sys_sendto net/socket.c:2194 [inline] + __se_sys_sendto net/socket.c:2190 [inline] + __x64_sys_sendto+0xe1/0x1c0 net/socket.c:2190 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xc3/0x1d0 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +RIP: 0033:0x7f06553c47ed +Code: 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007f0653a06fc8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c +RAX: ffffffffffffffda RBX: 00007f0655605fa0 RCX: 00007f06553c47ed +RDX: 0000000000000000 RSI: 0000000000000000 RDI: 000000000000000b +RBP: 00007f065545db38 R08: 0000200000000140 R09: 000000000000001c +R10: f7384d4ea84b01bd R11: 0000000000000246 R12: 0000000000000000 +R13: 00007f0655605fac R14: 00007f0655606038 R15: 00007f06539e7000 + </TASK> +Modules linked in: + +[1]: +dnf install -y selinux-policy-targeted policycoreutils netlabel_tools procps-ng nmap-ncat +mount -t selinuxfs none /sys/fs/selinux +load_policy +netlabelctl calipso add pass doi:1 +netlabelctl map del default +netlabelctl map add default address:::1 protocol:calipso,1 +sysctl net.ipv4.tcp_syncookies=2 +nc -l ::1 80 & +nc ::1 80 + +Fixes: e1adea927080 ("calipso: Allow request sockets to be relabelled by the lsm.") +Reported-by: syzkaller <syzkaller@googlegroups.com> +Reported-by: John Cheung <john.cs.hey@gmail.com> +Closes: https://lore.kernel.org/netdev/CAP=Rh=MvfhrGADy+-WJiftV2_WzMH4VEhEFmeT28qY+4yxNu4w@mail.gmail.com/ +Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> +Acked-by: Paul Moore <paul@paul-moore.com> +Link: https://patch.msgid.link/20250617224125.17299-1-kuni1840@gmail.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/ipv6/calipso.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c +index e17e756bb1ad9..59997e5d1343e 100644 +--- a/net/ipv6/calipso.c ++++ b/net/ipv6/calipso.c +@@ -1210,6 +1210,10 @@ static int calipso_req_setattr(struct request_sock *req, + struct ipv6_opt_hdr *old, *new; + struct sock *sk = sk_to_full_sk(req_to_sk(req)); + ++ /* sk is NULL for SYN+ACK w/ SYN Cookie */ ++ if (!sk) ++ return -ENOMEM; ++ + if (req_inet->ipv6_opt && req_inet->ipv6_opt->hopopt) + old = req_inet->ipv6_opt->hopopt; + else +@@ -1250,6 +1254,10 @@ static void calipso_req_delattr(struct request_sock *req) + struct ipv6_txoptions *txopts; + struct sock *sk = sk_to_full_sk(req_to_sk(req)); + ++ /* sk is NULL for SYN+ACK w/ SYN Cookie */ ++ if (!sk) ++ return; ++ + if (!req_inet->ipv6_opt || !req_inet->ipv6_opt->hopopt) + return; + +-- +2.39.5 + diff --git a/queue-5.10/drm-nouveau-bl-increase-buffer-size-to-avoid-truncat.patch b/queue-5.10/drm-nouveau-bl-increase-buffer-size-to-avoid-truncat.patch new file mode 100644 index 0000000000..54717d2046 --- /dev/null +++ b/queue-5.10/drm-nouveau-bl-increase-buffer-size-to-avoid-truncat.patch @@ -0,0 +1,81 @@ +From d84ed326d6bcf188264db3fb61f793d8cdf71b7d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 10 Jun 2025 14:54:51 -0700 +Subject: drm/nouveau/bl: increase buffer size to avoid truncate warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jacob Keller <jacob.e.keller@intel.com> + +[ Upstream commit 61b2b3737499f1fb361a54a16828db24a8345e85 ] + +The nouveau_get_backlight_name() function generates a unique name for the +backlight interface, appending an id from 1 to 99 for all backlight devices +after the first. + +GCC 15 (and likely other compilers) produce the following +-Wformat-truncation warning: + +nouveau_backlight.c: In function ‘nouveau_backlight_init’: +nouveau_backlight.c:56:69: error: ‘%d’ directive output may be truncated writing between 1 and 10 bytes into a region of size 3 [-Werror=format-truncation=] + 56 | snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb); + | ^~ +In function ‘nouveau_get_backlight_name’, + inlined from ‘nouveau_backlight_init’ at nouveau_backlight.c:351:7: +nouveau_backlight.c:56:56: note: directive argument in the range [1, 2147483647] + 56 | snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb); + | ^~~~~~~~~~~~~~~~ +nouveau_backlight.c:56:17: note: ‘snprintf’ output between 14 and 23 bytes into a destination of size 15 + 56 | snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The warning started appearing after commit ab244be47a8f ("drm/nouveau: +Fix a potential theorical leak in nouveau_get_backlight_name()") This fix +for the ida usage removed the explicit value check for ids larger than 99. +The compiler is unable to intuit that the ida_alloc_max() limits the +returned value range between 0 and 99. + +Because the compiler can no longer infer that the number ranges from 0 to +99, it thinks that it could use as many as 11 digits (10 + the potential - +sign for negative numbers). + +The warning has gone unfixed for some time, with at least one kernel test +robot report. The code breaks W=1 builds, which is especially frustrating +with the introduction of CONFIG_WERROR. + +The string is stored temporarily on the stack and then copied into the +device name. Its not a big deal to use 11 more bytes of stack rounding out +to an even 24 bytes. Increase BL_NAME_SIZE to 24 to avoid the truncation +warning. This fixes the W=1 builds that include this driver. + +Compile tested only. + +Fixes: ab244be47a8f ("drm/nouveau: Fix a potential theorical leak in nouveau_get_backlight_name()") +Reported-by: kernel test robot <lkp@intel.com> +Closes: https://lore.kernel.org/oe-kbuild-all/202312050324.0kv4PnfZ-lkp@intel.com/ +Suggested-by: Timur Tabi <ttabi@nvidia.com> +Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> +Link: https://lore.kernel.org/r/20250610-jk-nouveua-drm-bl-snprintf-fix-v2-1-7fdd4b84b48e@intel.com +Signed-off-by: Danilo Krummrich <dakr@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/nouveau/nouveau_backlight.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c +index f2f3280c3a50e..171cc170c458d 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c ++++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c +@@ -40,7 +40,7 @@ + #include "nouveau_connector.h" + + static struct ida bl_ida; +-#define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0' ++#define BL_NAME_SIZE 24 // 12 for name + 11 for digits + 1 for '\0' + + struct nouveau_backlight { + struct backlight_device *dev; +-- +2.39.5 + diff --git a/queue-5.10/hwmon-occ-add-new-temperature-sensor-type.patch b/queue-5.10/hwmon-occ-add-new-temperature-sensor-type.patch new file mode 100644 index 0000000000..d9b827a5bc --- /dev/null +++ b/queue-5.10/hwmon-occ-add-new-temperature-sensor-type.patch @@ -0,0 +1,134 @@ +From 14291bc3bebcf2a09a81c1c31ef926331b2de384 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 20 Nov 2020 11:33:15 +1030 +Subject: hwmon: (occ) Add new temperature sensor type + +From: Eddie James <eajames@linux.ibm.com> + +[ Upstream commit db4919ec86ff405273a767e1a9b51e2760e73ce5 ] + +The latest version of the On-Chip Controller (OCC) has a different +format for the temperature sensor data. Add a new temperature sensor +version to handle this data. + +Signed-off-by: Eddie James <eajames@linux.ibm.com> +Reviewed-by: Joel Stanley <joel@jms.id.au> +Signed-off-by: Joel Stanley <joel@jms.id.au> +Link: https://lore.kernel.org/r/20201120010315.190737-4-joel@jms.id.au +Signed-off-by: Guenter Roeck <linux@roeck-us.net> +Stable-dep-of: 744c2fe950e9 ("hwmon: (occ) Rework attribute registration for stack usage") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/hwmon/occ/common.c | 75 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 75 insertions(+) + +diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c +index d052502dc2c0e..580e63d7daa00 100644 +--- a/drivers/hwmon/occ/common.c ++++ b/drivers/hwmon/occ/common.c +@@ -41,6 +41,14 @@ struct temp_sensor_2 { + u8 value; + } __packed; + ++struct temp_sensor_10 { ++ u32 sensor_id; ++ u8 fru_type; ++ u8 value; ++ u8 throttle; ++ u8 reserved; ++} __packed; ++ + struct freq_sensor_1 { + u16 sensor_id; + u16 value; +@@ -307,6 +315,60 @@ static ssize_t occ_show_temp_2(struct device *dev, + return snprintf(buf, PAGE_SIZE - 1, "%u\n", val); + } + ++static ssize_t occ_show_temp_10(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int rc; ++ u32 val = 0; ++ struct temp_sensor_10 *temp; ++ struct occ *occ = dev_get_drvdata(dev); ++ struct occ_sensors *sensors = &occ->sensors; ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ ++ rc = occ_update_response(occ); ++ if (rc) ++ return rc; ++ ++ temp = ((struct temp_sensor_10 *)sensors->temp.data) + sattr->index; ++ ++ switch (sattr->nr) { ++ case 0: ++ val = get_unaligned_be32(&temp->sensor_id); ++ break; ++ case 1: ++ val = temp->value; ++ if (val == OCC_TEMP_SENSOR_FAULT) ++ return -EREMOTEIO; ++ ++ /* ++ * VRM doesn't return temperature, only alarm bit. This ++ * attribute maps to tempX_alarm instead of tempX_input for ++ * VRM ++ */ ++ if (temp->fru_type != OCC_FRU_TYPE_VRM) { ++ /* sensor not ready */ ++ if (val == 0) ++ return -EAGAIN; ++ ++ val *= 1000; ++ } ++ break; ++ case 2: ++ val = temp->fru_type; ++ break; ++ case 3: ++ val = temp->value == OCC_TEMP_SENSOR_FAULT; ++ break; ++ case 4: ++ val = temp->throttle * 1000; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return snprintf(buf, PAGE_SIZE - 1, "%u\n", val); ++} ++ + static ssize_t occ_show_freq_1(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -745,6 +807,10 @@ static int occ_setup_sensor_attrs(struct occ *occ) + num_attrs += (sensors->temp.num_sensors * 4); + show_temp = occ_show_temp_2; + break; ++ case 0x10: ++ num_attrs += (sensors->temp.num_sensors * 5); ++ show_temp = occ_show_temp_10; ++ break; + default: + sensors->temp.num_sensors = 0; + } +@@ -844,6 +910,15 @@ static int occ_setup_sensor_attrs(struct occ *occ) + attr->sensor = OCC_INIT_ATTR(attr->name, 0444, + show_temp, NULL, 3, i); + attr++; ++ ++ if (sensors->temp.version == 0x10) { ++ snprintf(attr->name, sizeof(attr->name), ++ "temp%d_max", s); ++ attr->sensor = OCC_INIT_ATTR(attr->name, 0444, ++ show_temp, NULL, ++ 4, i); ++ attr++; ++ } + } + } + +-- +2.39.5 + diff --git a/queue-5.10/hwmon-occ-add-soft-minimum-power-cap-attribute.patch b/queue-5.10/hwmon-occ-add-soft-minimum-power-cap-attribute.patch new file mode 100644 index 0000000000..079cb857ca --- /dev/null +++ b/queue-5.10/hwmon-occ-add-soft-minimum-power-cap-attribute.patch @@ -0,0 +1,71 @@ +From 93c82f3476ba797df37381aea7dede855092bf03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 15 Feb 2022 09:10:22 -0600 +Subject: hwmon: (occ) Add soft minimum power cap attribute + +From: Eddie James <eajames@linux.ibm.com> + +[ Upstream commit 84dc9e8a7eec2cdff00728baedf0fb35fc7c11e8 ] + +Export the power caps data for the soft minimum power cap through hwmon. + +Signed-off-by: Eddie James <eajames@linux.ibm.com> +Reviewed-by: Joel Stanley <joel@jms.id.au> +Link: https://lore.kernel.org/r/20220215151022.7498-5-eajames@linux.ibm.com +Signed-off-by: Guenter Roeck <linux@roeck-us.net> +Stable-dep-of: 744c2fe950e9 ("hwmon: (occ) Rework attribute registration for stack usage") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/hwmon/occ/common.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c +index 580e63d7daa00..ce4a16b475fd1 100644 +--- a/drivers/hwmon/occ/common.c ++++ b/drivers/hwmon/occ/common.c +@@ -685,6 +685,9 @@ static ssize_t occ_show_caps_3(struct device *dev, + case 7: + val = caps->user_source; + break; ++ case 8: ++ val = get_unaligned_be16(&caps->soft_min) * 1000000ULL; ++ break; + default: + return -EINVAL; + } +@@ -845,12 +848,13 @@ static int occ_setup_sensor_attrs(struct occ *occ) + case 1: + num_attrs += (sensors->caps.num_sensors * 7); + break; +- case 3: +- show_caps = occ_show_caps_3; +- fallthrough; + case 2: + num_attrs += (sensors->caps.num_sensors * 8); + break; ++ case 3: ++ show_caps = occ_show_caps_3; ++ num_attrs += (sensors->caps.num_sensors * 9); ++ break; + default: + sensors->caps.num_sensors = 0; + } +@@ -1057,6 +1061,15 @@ static int occ_setup_sensor_attrs(struct occ *occ) + attr->sensor = OCC_INIT_ATTR(attr->name, 0444, + show_caps, NULL, 7, 0); + attr++; ++ ++ if (sensors->caps.version > 2) { ++ snprintf(attr->name, sizeof(attr->name), ++ "power%d_cap_min_soft", s); ++ attr->sensor = OCC_INIT_ATTR(attr->name, 0444, ++ show_caps, NULL, ++ 8, 0); ++ attr++; ++ } + } + } + +-- +2.39.5 + diff --git a/queue-5.10/hwmon-occ-fix-unaligned-accesses.patch b/queue-5.10/hwmon-occ-fix-unaligned-accesses.patch new file mode 100644 index 0000000000..4af74c78cc --- /dev/null +++ b/queue-5.10/hwmon-occ-fix-unaligned-accesses.patch @@ -0,0 +1,109 @@ +From 55791c0c0fbf473fe2af2ca39890c641adf4a8a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 10 Jun 2025 11:25:49 +0200 +Subject: hwmon: (occ) fix unaligned accesses + +From: Arnd Bergmann <arnd@arndb.de> + +[ Upstream commit 2c021b45c154958566aad0cae9f74ab26a2d5732 ] + +Passing a pointer to an unaligned integer as a function argument is +undefined behavior: + +drivers/hwmon/occ/common.c:492:27: warning: taking address of packed member 'accumulator' of class or structure 'power_sensor_2' may result in an unaligned pointer value [-Waddress-of-packed-member] + 492 | val = occ_get_powr_avg(&power->accumulator, + | ^~~~~~~~~~~~~~~~~~ +drivers/hwmon/occ/common.c:493:13: warning: taking address of packed member 'update_tag' of class or structure 'power_sensor_2' may result in an unaligned pointer value [-Waddress-of-packed-member] + 493 | &power->update_tag); + | ^~~~~~~~~~~~~~~~~ + +Move the get_unaligned() calls out of the function and pass these +through argument registers instead. + +Fixes: c10e753d43eb ("hwmon (occ): Add sensor types and versions") +Signed-off-by: Arnd Bergmann <arnd@arndb.de> +Link: https://lore.kernel.org/r/20250610092553.2641094-1-arnd@kernel.org +Signed-off-by: Guenter Roeck <linux@roeck-us.net> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/hwmon/occ/common.c | 28 +++++++++++++--------------- + 1 file changed, 13 insertions(+), 15 deletions(-) + +diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c +index 44980946281c2..51bf560ef20b1 100644 +--- a/drivers/hwmon/occ/common.c ++++ b/drivers/hwmon/occ/common.c +@@ -468,12 +468,10 @@ static ssize_t occ_show_power_1(struct device *dev, + return snprintf(buf, PAGE_SIZE - 1, "%llu\n", val); + } + +-static u64 occ_get_powr_avg(u64 *accum, u32 *samples) ++static u64 occ_get_powr_avg(u64 accum, u32 samples) + { +- u64 divisor = get_unaligned_be32(samples); +- +- return (divisor == 0) ? 0 : +- div64_u64(get_unaligned_be64(accum) * 1000000ULL, divisor); ++ return (samples == 0) ? 0 : ++ mul_u64_u32_div(accum, 1000000UL, samples); + } + + static ssize_t occ_show_power_2(struct device *dev, +@@ -498,8 +496,8 @@ static ssize_t occ_show_power_2(struct device *dev, + get_unaligned_be32(&power->sensor_id), + power->function_id, power->apss_channel); + case 1: +- val = occ_get_powr_avg(&power->accumulator, +- &power->update_tag); ++ val = occ_get_powr_avg(get_unaligned_be64(&power->accumulator), ++ get_unaligned_be32(&power->update_tag)); + break; + case 2: + val = (u64)get_unaligned_be32(&power->update_tag) * +@@ -536,8 +534,8 @@ static ssize_t occ_show_power_a0(struct device *dev, + return snprintf(buf, PAGE_SIZE - 1, "%u_system\n", + get_unaligned_be32(&power->sensor_id)); + case 1: +- val = occ_get_powr_avg(&power->system.accumulator, +- &power->system.update_tag); ++ val = occ_get_powr_avg(get_unaligned_be64(&power->system.accumulator), ++ get_unaligned_be32(&power->system.update_tag)); + break; + case 2: + val = (u64)get_unaligned_be32(&power->system.update_tag) * +@@ -550,8 +548,8 @@ static ssize_t occ_show_power_a0(struct device *dev, + return snprintf(buf, PAGE_SIZE - 1, "%u_proc\n", + get_unaligned_be32(&power->sensor_id)); + case 5: +- val = occ_get_powr_avg(&power->proc.accumulator, +- &power->proc.update_tag); ++ val = occ_get_powr_avg(get_unaligned_be64(&power->proc.accumulator), ++ get_unaligned_be32(&power->proc.update_tag)); + break; + case 6: + val = (u64)get_unaligned_be32(&power->proc.update_tag) * +@@ -564,8 +562,8 @@ static ssize_t occ_show_power_a0(struct device *dev, + return snprintf(buf, PAGE_SIZE - 1, "%u_vdd\n", + get_unaligned_be32(&power->sensor_id)); + case 9: +- val = occ_get_powr_avg(&power->vdd.accumulator, +- &power->vdd.update_tag); ++ val = occ_get_powr_avg(get_unaligned_be64(&power->vdd.accumulator), ++ get_unaligned_be32(&power->vdd.update_tag)); + break; + case 10: + val = (u64)get_unaligned_be32(&power->vdd.update_tag) * +@@ -578,8 +576,8 @@ static ssize_t occ_show_power_a0(struct device *dev, + return snprintf(buf, PAGE_SIZE - 1, "%u_vdn\n", + get_unaligned_be32(&power->sensor_id)); + case 13: +- val = occ_get_powr_avg(&power->vdn.accumulator, +- &power->vdn.update_tag); ++ val = occ_get_powr_avg(get_unaligned_be64(&power->vdn.accumulator), ++ get_unaligned_be32(&power->vdn.update_tag)); + break; + case 14: + val = (u64)get_unaligned_be32(&power->vdn.update_tag) * +-- +2.39.5 + diff --git a/queue-5.10/hwmon-occ-rework-attribute-registration-for-stack-us.patch b/queue-5.10/hwmon-occ-rework-attribute-registration-for-stack-us.patch new file mode 100644 index 0000000000..542d63b219 --- /dev/null +++ b/queue-5.10/hwmon-occ-rework-attribute-registration-for-stack-us.patch @@ -0,0 +1,365 @@ +From 49872c655398903cbb36391cda748af6700c6921 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 10 Jun 2025 11:23:06 +0200 +Subject: hwmon: (occ) Rework attribute registration for stack usage + +From: Arnd Bergmann <arnd@arndb.de> + +[ Upstream commit 744c2fe950e936c4d62430de899d6253424200ed ] + +clang produces an output with excessive stack usage when building the +occ_setup_sensor_attrs() function, apparently the result of having +a lot of struct literals and building with the -fno-strict-overflow +option that leads clang to skip some optimization in case the 'attr' +pointer overruns: + +drivers/hwmon/occ/common.c:775:12: error: stack frame size (1392) exceeds limit (1280) in 'occ_setup_sensor_attrs' [-Werror,-Wframe-larger-than] + +Replace the custom macros for initializing the attributes with a +simpler function call that does not run into this corner case. + +Link: https://godbolt.org/z/Wf1Yx76a5 +Fixes: 54076cb3b5ff ("hwmon (occ): Add sensor attributes and register hwmon device") +Signed-off-by: Arnd Bergmann <arnd@arndb.de> +Link: https://lore.kernel.org/r/20250610092315.2640039-1-arnd@kernel.org +Signed-off-by: Guenter Roeck <linux@roeck-us.net> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/hwmon/occ/common.c | 212 +++++++++++++++---------------------- + 1 file changed, 85 insertions(+), 127 deletions(-) + +diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c +index ce4a16b475fd1..44980946281c2 100644 +--- a/drivers/hwmon/occ/common.c ++++ b/drivers/hwmon/occ/common.c +@@ -759,29 +759,30 @@ static ssize_t occ_show_extended(struct device *dev, + } + + /* +- * Some helper macros to make it easier to define an occ_attribute. Since these +- * are dynamically allocated, we shouldn't use the existing kernel macros which ++ * A helper to make it easier to define an occ_attribute. Since these ++ * are dynamically allocated, we cannot use the existing kernel macros which + * stringify the name argument. + */ +-#define ATTR_OCC(_name, _mode, _show, _store) { \ +- .attr = { \ +- .name = _name, \ +- .mode = VERIFY_OCTAL_PERMISSIONS(_mode), \ +- }, \ +- .show = _show, \ +- .store = _store, \ +-} +- +-#define SENSOR_ATTR_OCC(_name, _mode, _show, _store, _nr, _index) { \ +- .dev_attr = ATTR_OCC(_name, _mode, _show, _store), \ +- .index = _index, \ +- .nr = _nr, \ ++static void occ_init_attribute(struct occ_attribute *attr, int mode, ++ ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf), ++ ssize_t (*store)(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count), ++ int nr, int index, const char *fmt, ...) ++{ ++ va_list args; ++ ++ va_start(args, fmt); ++ vsnprintf(attr->name, sizeof(attr->name), fmt, args); ++ va_end(args); ++ ++ attr->sensor.dev_attr.attr.name = attr->name; ++ attr->sensor.dev_attr.attr.mode = mode; ++ attr->sensor.dev_attr.show = show; ++ attr->sensor.dev_attr.store = store; ++ attr->sensor.index = index; ++ attr->sensor.nr = nr; + } + +-#define OCC_INIT_ATTR(_name, _mode, _show, _store, _nr, _index) \ +- ((struct sensor_device_attribute_2) \ +- SENSOR_ATTR_OCC(_name, _mode, _show, _store, _nr, _index)) +- + /* + * Allocate and instatiate sensor_device_attribute_2s. It's most efficient to + * use our own instead of the built-in hwmon attribute types. +@@ -867,14 +868,15 @@ static int occ_setup_sensor_attrs(struct occ *occ) + sensors->extended.num_sensors = 0; + } + +- occ->attrs = devm_kzalloc(dev, sizeof(*occ->attrs) * num_attrs, ++ occ->attrs = devm_kcalloc(dev, num_attrs, sizeof(*occ->attrs), + GFP_KERNEL); + if (!occ->attrs) + return -ENOMEM; + + /* null-terminated list */ +- occ->group.attrs = devm_kzalloc(dev, sizeof(*occ->group.attrs) * +- num_attrs + 1, GFP_KERNEL); ++ occ->group.attrs = devm_kcalloc(dev, num_attrs + 1, ++ sizeof(*occ->group.attrs), ++ GFP_KERNEL); + if (!occ->group.attrs) + return -ENOMEM; + +@@ -884,43 +886,33 @@ static int occ_setup_sensor_attrs(struct occ *occ) + s = i + 1; + temp = ((struct temp_sensor_2 *)sensors->temp.data) + i; + +- snprintf(attr->name, sizeof(attr->name), "temp%d_label", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_temp, NULL, +- 0, i); ++ occ_init_attribute(attr, 0444, show_temp, NULL, ++ 0, i, "temp%d_label", s); + attr++; + + if (sensors->temp.version > 1 && + temp->fru_type == OCC_FRU_TYPE_VRM) { +- snprintf(attr->name, sizeof(attr->name), +- "temp%d_alarm", s); ++ occ_init_attribute(attr, 0444, show_temp, NULL, ++ 1, i, "temp%d_alarm", s); + } else { +- snprintf(attr->name, sizeof(attr->name), +- "temp%d_input", s); ++ occ_init_attribute(attr, 0444, show_temp, NULL, ++ 1, i, "temp%d_input", s); + } + +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_temp, NULL, +- 1, i); + attr++; + + if (sensors->temp.version > 1) { +- snprintf(attr->name, sizeof(attr->name), +- "temp%d_fru_type", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- show_temp, NULL, 2, i); ++ occ_init_attribute(attr, 0444, show_temp, NULL, ++ 2, i, "temp%d_fru_type", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), +- "temp%d_fault", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- show_temp, NULL, 3, i); ++ occ_init_attribute(attr, 0444, show_temp, NULL, ++ 3, i, "temp%d_fault", s); + attr++; + + if (sensors->temp.version == 0x10) { +- snprintf(attr->name, sizeof(attr->name), +- "temp%d_max", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- show_temp, NULL, +- 4, i); ++ occ_init_attribute(attr, 0444, show_temp, NULL, ++ 4, i, "temp%d_max", s); + attr++; + } + } +@@ -929,14 +921,12 @@ static int occ_setup_sensor_attrs(struct occ *occ) + for (i = 0; i < sensors->freq.num_sensors; ++i) { + s = i + 1; + +- snprintf(attr->name, sizeof(attr->name), "freq%d_label", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_freq, NULL, +- 0, i); ++ occ_init_attribute(attr, 0444, show_freq, NULL, ++ 0, i, "freq%d_label", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), "freq%d_input", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_freq, NULL, +- 1, i); ++ occ_init_attribute(attr, 0444, show_freq, NULL, ++ 1, i, "freq%d_input", s); + attr++; + } + +@@ -952,32 +942,24 @@ static int occ_setup_sensor_attrs(struct occ *occ) + s = (i * 4) + 1; + + for (j = 0; j < 4; ++j) { +- snprintf(attr->name, sizeof(attr->name), +- "power%d_label", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- show_power, NULL, +- nr++, i); ++ occ_init_attribute(attr, 0444, show_power, ++ NULL, nr++, i, ++ "power%d_label", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), +- "power%d_average", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- show_power, NULL, +- nr++, i); ++ occ_init_attribute(attr, 0444, show_power, ++ NULL, nr++, i, ++ "power%d_average", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), +- "power%d_average_interval", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- show_power, NULL, +- nr++, i); ++ occ_init_attribute(attr, 0444, show_power, ++ NULL, nr++, i, ++ "power%d_average_interval", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), +- "power%d_input", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- show_power, NULL, +- nr++, i); ++ occ_init_attribute(attr, 0444, show_power, ++ NULL, nr++, i, ++ "power%d_input", s); + attr++; + + s++; +@@ -989,28 +971,20 @@ static int occ_setup_sensor_attrs(struct occ *occ) + for (i = 0; i < sensors->power.num_sensors; ++i) { + s = i + 1; + +- snprintf(attr->name, sizeof(attr->name), +- "power%d_label", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- show_power, NULL, 0, i); ++ occ_init_attribute(attr, 0444, show_power, NULL, ++ 0, i, "power%d_label", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), +- "power%d_average", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- show_power, NULL, 1, i); ++ occ_init_attribute(attr, 0444, show_power, NULL, ++ 1, i, "power%d_average", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), +- "power%d_average_interval", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- show_power, NULL, 2, i); ++ occ_init_attribute(attr, 0444, show_power, NULL, ++ 2, i, "power%d_average_interval", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), +- "power%d_input", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- show_power, NULL, 3, i); ++ occ_init_attribute(attr, 0444, show_power, NULL, ++ 3, i, "power%d_input", s); + attr++; + } + +@@ -1018,56 +992,43 @@ static int occ_setup_sensor_attrs(struct occ *occ) + } + + if (sensors->caps.num_sensors >= 1) { +- snprintf(attr->name, sizeof(attr->name), "power%d_label", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, +- 0, 0); ++ occ_init_attribute(attr, 0444, show_caps, NULL, ++ 0, 0, "power%d_label", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), "power%d_cap", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, +- 1, 0); ++ occ_init_attribute(attr, 0444, show_caps, NULL, ++ 1, 0, "power%d_cap", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), "power%d_input", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, +- 2, 0); ++ occ_init_attribute(attr, 0444, show_caps, NULL, ++ 2, 0, "power%d_input", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), +- "power%d_cap_not_redundant", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, +- 3, 0); ++ occ_init_attribute(attr, 0444, show_caps, NULL, ++ 3, 0, "power%d_cap_not_redundant", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), "power%d_cap_max", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, +- 4, 0); ++ occ_init_attribute(attr, 0444, show_caps, NULL, ++ 4, 0, "power%d_cap_max", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), "power%d_cap_min", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, +- 5, 0); ++ occ_init_attribute(attr, 0444, show_caps, NULL, ++ 5, 0, "power%d_cap_min", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), "power%d_cap_user", +- s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0644, show_caps, +- occ_store_caps_user, 6, 0); ++ occ_init_attribute(attr, 0644, show_caps, occ_store_caps_user, ++ 6, 0, "power%d_cap_user", s); + attr++; + + if (sensors->caps.version > 1) { +- snprintf(attr->name, sizeof(attr->name), +- "power%d_cap_user_source", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- show_caps, NULL, 7, 0); ++ occ_init_attribute(attr, 0444, show_caps, NULL, ++ 7, 0, "power%d_cap_user_source", s); + attr++; + + if (sensors->caps.version > 2) { +- snprintf(attr->name, sizeof(attr->name), +- "power%d_cap_min_soft", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- show_caps, NULL, +- 8, 0); ++ occ_init_attribute(attr, 0444, show_caps, NULL, ++ 8, 0, ++ "power%d_cap_min_soft", s); + attr++; + } + } +@@ -1076,19 +1037,16 @@ static int occ_setup_sensor_attrs(struct occ *occ) + for (i = 0; i < sensors->extended.num_sensors; ++i) { + s = i + 1; + +- snprintf(attr->name, sizeof(attr->name), "extn%d_label", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- occ_show_extended, NULL, 0, i); ++ occ_init_attribute(attr, 0444, occ_show_extended, NULL, ++ 0, i, "extn%d_label", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), "extn%d_flags", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- occ_show_extended, NULL, 1, i); ++ occ_init_attribute(attr, 0444, occ_show_extended, NULL, ++ 1, i, "extn%d_flags", s); + attr++; + +- snprintf(attr->name, sizeof(attr->name), "extn%d_input", s); +- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, +- occ_show_extended, NULL, 2, i); ++ occ_init_attribute(attr, 0444, occ_show_extended, NULL, ++ 2, i, "extn%d_input", s); + attr++; + } + +-- +2.39.5 + diff --git a/queue-5.10/mpls-use-rcu_dereference_rtnl-in-mpls_route_input_rc.patch b/queue-5.10/mpls-use-rcu_dereference_rtnl-in-mpls_route_input_rc.patch new file mode 100644 index 0000000000..65f5767531 --- /dev/null +++ b/queue-5.10/mpls-use-rcu_dereference_rtnl-in-mpls_route_input_rc.patch @@ -0,0 +1,95 @@ +From f7cbe6a472fd000ed2394ebb027e89b2c7c37dd0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 16 Jun 2025 13:15:12 -0700 +Subject: mpls: Use rcu_dereference_rtnl() in mpls_route_input_rcu(). + +From: Kuniyuki Iwashima <kuniyu@google.com> + +[ Upstream commit 6dbb0d97c5096072c78a6abffe393584e57ae945 ] + +As syzbot reported [0], mpls_route_input_rcu() can be called +from mpls_getroute(), where is under RTNL. + +net->mpls.platform_label is only updated under RTNL. + +Let's use rcu_dereference_rtnl() in mpls_route_input_rcu() to +silence the splat. + +[0]: +WARNING: suspicious RCU usage +6.15.0-rc7-syzkaller-00082-g5cdb2c77c4c3 #0 Not tainted + ---------------------------- +net/mpls/af_mpls.c:84 suspicious rcu_dereference_check() usage! + +other info that might help us debug this: + +rcu_scheduler_active = 2, debug_locks = 1 +1 lock held by syz.2.4451/17730: + #0: ffffffff9012a3e8 (rtnl_mutex){+.+.}-{4:4}, at: rtnl_lock net/core/rtnetlink.c:80 [inline] + #0: ffffffff9012a3e8 (rtnl_mutex){+.+.}-{4:4}, at: rtnetlink_rcv_msg+0x371/0xe90 net/core/rtnetlink.c:6961 + +stack backtrace: +CPU: 1 UID: 0 PID: 17730 Comm: syz.2.4451 Not tainted 6.15.0-rc7-syzkaller-00082-g5cdb2c77c4c3 #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/07/2025 +Call Trace: + <TASK> + __dump_stack lib/dump_stack.c:94 [inline] + dump_stack_lvl+0x16c/0x1f0 lib/dump_stack.c:120 + lockdep_rcu_suspicious+0x166/0x260 kernel/locking/lockdep.c:6865 + mpls_route_input_rcu+0x1d4/0x200 net/mpls/af_mpls.c:84 + mpls_getroute+0x621/0x1ea0 net/mpls/af_mpls.c:2381 + rtnetlink_rcv_msg+0x3c9/0xe90 net/core/rtnetlink.c:6964 + netlink_rcv_skb+0x16d/0x440 net/netlink/af_netlink.c:2534 + netlink_unicast_kernel net/netlink/af_netlink.c:1313 [inline] + netlink_unicast+0x53a/0x7f0 net/netlink/af_netlink.c:1339 + netlink_sendmsg+0x8d1/0xdd0 net/netlink/af_netlink.c:1883 + sock_sendmsg_nosec net/socket.c:712 [inline] + __sock_sendmsg net/socket.c:727 [inline] + ____sys_sendmsg+0xa98/0xc70 net/socket.c:2566 + ___sys_sendmsg+0x134/0x1d0 net/socket.c:2620 + __sys_sendmmsg+0x200/0x420 net/socket.c:2709 + __do_sys_sendmmsg net/socket.c:2736 [inline] + __se_sys_sendmmsg net/socket.c:2733 [inline] + __x64_sys_sendmmsg+0x9c/0x100 net/socket.c:2733 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xcd/0x230 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +RIP: 0033:0x7f0a2818e969 +Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007f0a28f52038 EFLAGS: 00000246 ORIG_RAX: 0000000000000133 +RAX: ffffffffffffffda RBX: 00007f0a283b5fa0 RCX: 00007f0a2818e969 +RDX: 0000000000000003 RSI: 0000200000000080 RDI: 0000000000000003 +RBP: 00007f0a28210ab1 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 +R13: 0000000000000000 R14: 00007f0a283b5fa0 R15: 00007ffce5e9f268 + </TASK> + +Fixes: 0189197f4416 ("mpls: Basic routing support") +Reported-by: syzbot+8a583bdd1a5cc0b0e068@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68507981.a70a0220.395abc.01ef.GAE@google.com/ +Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> +Link: https://patch.msgid.link/20250616201532.1036568-1-kuni1840@gmail.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/mpls/af_mpls.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c +index 1dcbdab9319bb..fa095bc8b0c1a 100644 +--- a/net/mpls/af_mpls.c ++++ b/net/mpls/af_mpls.c +@@ -80,8 +80,8 @@ static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned index) + + if (index < net->mpls.platform_labels) { + struct mpls_route __rcu **platform_label = +- rcu_dereference(net->mpls.platform_label); +- rt = rcu_dereference(platform_label[index]); ++ rcu_dereference_rtnl(net->mpls.platform_label); ++ rt = rcu_dereference_rtnl(platform_label[index]); + } + return rt; + } +-- +2.39.5 + diff --git a/queue-5.10/net-atm-add-lec_mutex.patch b/queue-5.10/net-atm-add-lec_mutex.patch new file mode 100644 index 0000000000..7f71550e2d --- /dev/null +++ b/queue-5.10/net-atm-add-lec_mutex.patch @@ -0,0 +1,161 @@ +From 2a2087f133b555c603f945eec7bd81948ab52e30 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 18 Jun 2025 14:08:43 +0000 +Subject: net: atm: add lec_mutex + +From: Eric Dumazet <edumazet@google.com> + +[ Upstream commit d13a3824bfd2b4774b671a75cf766a16637a0e67 ] + +syzbot found its way in net/atm/lec.c, and found an error path +in lecd_attach() could leave a dangling pointer in dev_lec[]. + +Add a mutex to protect dev_lecp[] uses from lecd_attach(), +lec_vcc_attach() and lec_mcast_attach(). + +Following patch will use this mutex for /proc/net/atm/lec. + +BUG: KASAN: slab-use-after-free in lecd_attach net/atm/lec.c:751 [inline] +BUG: KASAN: slab-use-after-free in lane_ioctl+0x2224/0x23e0 net/atm/lec.c:1008 +Read of size 8 at addr ffff88807c7b8e68 by task syz.1.17/6142 + +CPU: 1 UID: 0 PID: 6142 Comm: syz.1.17 Not tainted 6.16.0-rc1-syzkaller-00239-g08215f5486ec #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/07/2025 +Call Trace: + <TASK> + __dump_stack lib/dump_stack.c:94 [inline] + dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:408 [inline] + print_report+0xcd/0x680 mm/kasan/report.c:521 + kasan_report+0xe0/0x110 mm/kasan/report.c:634 + lecd_attach net/atm/lec.c:751 [inline] + lane_ioctl+0x2224/0x23e0 net/atm/lec.c:1008 + do_vcc_ioctl+0x12c/0x930 net/atm/ioctl.c:159 + sock_do_ioctl+0x118/0x280 net/socket.c:1190 + sock_ioctl+0x227/0x6b0 net/socket.c:1311 + vfs_ioctl fs/ioctl.c:51 [inline] + __do_sys_ioctl fs/ioctl.c:907 [inline] + __se_sys_ioctl fs/ioctl.c:893 [inline] + __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + </TASK> + +Allocated by task 6132: + kasan_save_stack+0x33/0x60 mm/kasan/common.c:47 + kasan_save_track+0x14/0x30 mm/kasan/common.c:68 + poison_kmalloc_redzone mm/kasan/common.c:377 [inline] + __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394 + kasan_kmalloc include/linux/kasan.h:260 [inline] + __do_kmalloc_node mm/slub.c:4328 [inline] + __kvmalloc_node_noprof+0x27b/0x620 mm/slub.c:5015 + alloc_netdev_mqs+0xd2/0x1570 net/core/dev.c:11711 + lecd_attach net/atm/lec.c:737 [inline] + lane_ioctl+0x17db/0x23e0 net/atm/lec.c:1008 + do_vcc_ioctl+0x12c/0x930 net/atm/ioctl.c:159 + sock_do_ioctl+0x118/0x280 net/socket.c:1190 + sock_ioctl+0x227/0x6b0 net/socket.c:1311 + vfs_ioctl fs/ioctl.c:51 [inline] + __do_sys_ioctl fs/ioctl.c:907 [inline] + __se_sys_ioctl fs/ioctl.c:893 [inline] + __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Freed by task 6132: + kasan_save_stack+0x33/0x60 mm/kasan/common.c:47 + kasan_save_track+0x14/0x30 mm/kasan/common.c:68 + kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576 + poison_slab_object mm/kasan/common.c:247 [inline] + __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264 + kasan_slab_free include/linux/kasan.h:233 [inline] + slab_free_hook mm/slub.c:2381 [inline] + slab_free mm/slub.c:4643 [inline] + kfree+0x2b4/0x4d0 mm/slub.c:4842 + free_netdev+0x6c5/0x910 net/core/dev.c:11892 + lecd_attach net/atm/lec.c:744 [inline] + lane_ioctl+0x1ce8/0x23e0 net/atm/lec.c:1008 + do_vcc_ioctl+0x12c/0x930 net/atm/ioctl.c:159 + sock_do_ioctl+0x118/0x280 net/socket.c:1190 + sock_ioctl+0x227/0x6b0 net/socket.c:1311 + vfs_ioctl fs/ioctl.c:51 [inline] + __do_sys_ioctl fs/ioctl.c:907 [inline] + __se_sys_ioctl fs/ioctl.c:893 [inline] + __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+8b64dec3affaed7b3af5@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/6852c6f6.050a0220.216029.0018.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet <edumazet@google.com> +Link: https://patch.msgid.link/20250618140844.1686882-2-edumazet@google.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/atm/lec.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/net/atm/lec.c b/net/atm/lec.c +index ca9952c52fb5c..3f67b84c8f1c9 100644 +--- a/net/atm/lec.c ++++ b/net/atm/lec.c +@@ -124,6 +124,7 @@ static unsigned char bus_mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + /* Device structures */ + static struct net_device *dev_lec[MAX_LEC_ITF]; ++static DEFINE_MUTEX(lec_mutex); + + #if IS_ENABLED(CONFIG_BRIDGE) + static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev) +@@ -687,6 +688,7 @@ static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg) + int bytes_left; + struct atmlec_ioc ioc_data; + ++ lockdep_assert_held(&lec_mutex); + /* Lecd must be up in this case */ + bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc)); + if (bytes_left != 0) +@@ -712,6 +714,7 @@ static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg) + + static int lec_mcast_attach(struct atm_vcc *vcc, int arg) + { ++ lockdep_assert_held(&lec_mutex); + if (arg < 0 || arg >= MAX_LEC_ITF) + return -EINVAL; + arg = array_index_nospec(arg, MAX_LEC_ITF); +@@ -727,6 +730,7 @@ static int lecd_attach(struct atm_vcc *vcc, int arg) + int i; + struct lec_priv *priv; + ++ lockdep_assert_held(&lec_mutex); + if (arg < 0) + arg = 0; + if (arg >= MAX_LEC_ITF) +@@ -744,6 +748,7 @@ static int lecd_attach(struct atm_vcc *vcc, int arg) + snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i); + if (register_netdev(dev_lec[i])) { + free_netdev(dev_lec[i]); ++ dev_lec[i] = NULL; + return -EINVAL; + } + +@@ -1005,6 +1010,7 @@ static int lane_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) + return -ENOIOCTLCMD; + } + ++ mutex_lock(&lec_mutex); + switch (cmd) { + case ATMLEC_CTRL: + err = lecd_attach(vcc, (int)arg); +@@ -1019,6 +1025,7 @@ static int lane_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) + break; + } + ++ mutex_unlock(&lec_mutex); + return err; + } + +-- +2.39.5 + diff --git a/queue-5.10/net-atm-fix-proc-net-atm-lec-handling.patch b/queue-5.10/net-atm-fix-proc-net-atm-lec-handling.patch new file mode 100644 index 0000000000..68f00df1ec --- /dev/null +++ b/queue-5.10/net-atm-fix-proc-net-atm-lec-handling.patch @@ -0,0 +1,58 @@ +From aefa3deb6cba4e9be7bf4837fbbe87b2f6ad6c84 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 18 Jun 2025 14:08:44 +0000 +Subject: net: atm: fix /proc/net/atm/lec handling + +From: Eric Dumazet <edumazet@google.com> + +[ Upstream commit d03b79f459c7935cff830d98373474f440bd03ae ] + +/proc/net/atm/lec must ensure safety against dev_lec[] changes. + +It appears it had dev_put() calls without prior dev_hold(), +leading to imbalance and UAF. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Acked-by: Francois Romieu <romieu@fr.zoreil.com> # Minor atm contributor +Link: https://patch.msgid.link/20250618140844.1686882-3-edumazet@google.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/atm/lec.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/atm/lec.c b/net/atm/lec.c +index 3f67b84c8f1c9..73078306504c0 100644 +--- a/net/atm/lec.c ++++ b/net/atm/lec.c +@@ -911,7 +911,6 @@ static void *lec_itf_walk(struct lec_state *state, loff_t *l) + v = (dev && netdev_priv(dev)) ? + lec_priv_walk(state, l, netdev_priv(dev)) : NULL; + if (!v && dev) { +- dev_put(dev); + /* Partial state reset for the next time we get called */ + dev = NULL; + } +@@ -935,6 +934,7 @@ static void *lec_seq_start(struct seq_file *seq, loff_t *pos) + { + struct lec_state *state = seq->private; + ++ mutex_lock(&lec_mutex); + state->itf = 0; + state->dev = NULL; + state->locked = NULL; +@@ -952,8 +952,9 @@ static void lec_seq_stop(struct seq_file *seq, void *v) + if (state->dev) { + spin_unlock_irqrestore(&state->locked->lec_arp_lock, + state->flags); +- dev_put(state->dev); ++ state->dev = NULL; + } ++ mutex_unlock(&lec_mutex); + } + + static void *lec_seq_next(struct seq_file *seq, void *v, loff_t *pos) +-- +2.39.5 + diff --git a/queue-5.10/net-ice-perform-accurate-arfs-flow-match.patch b/queue-5.10/net-ice-perform-accurate-arfs-flow-match.patch new file mode 100644 index 0000000000..056d7206a9 --- /dev/null +++ b/queue-5.10/net-ice-perform-accurate-arfs-flow-match.patch @@ -0,0 +1,158 @@ +From 5871455ceb6ab1cb9a8763b7b07d623b3c29cc84 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 20 May 2025 22:36:56 +0530 +Subject: net: ice: Perform accurate aRFS flow match + +From: Krishna Kumar <krikku@gmail.com> + +[ Upstream commit 5d3bc9e5e725aa36cca9b794e340057feb6880b4 ] + +This patch fixes an issue seen in a large-scale deployment under heavy +incoming pkts where the aRFS flow wrongly matches a flow and reprograms the +NIC with wrong settings. That mis-steering causes RX-path latency spikes +and noisy neighbor effects when many connections collide on the same +hash (some of our production servers have 20-30K connections). + +set_rps_cpu() calls ndo_rx_flow_steer() with flow_id that is calculated by +hashing the skb sized by the per rx-queue table size. This results in +multiple connections (even across different rx-queues) getting the same +hash value. The driver steer function modifies the wrong flow to use this +rx-queue, e.g.: Flow#1 is first added: + Flow#1: <ip1, port1, ip2, port2>, Hash 'h', q#10 + +Later when a new flow needs to be added: + Flow#2: <ip3, port3, ip4, port4>, Hash 'h', q#20 + +The driver finds the hash 'h' from Flow#1 and updates it to use q#20. This +results in both flows getting un-optimized - packets for Flow#1 goes to +q#20, and then reprogrammed back to q#10 later and so on; and Flow #2 +programming is never done as Flow#1 is matched first for all misses. Many +flows may wrongly share the same hash and reprogram rules of the original +flow each with their own q#. + +Tested on two 144-core servers with 16K netperf sessions for 180s. Netperf +clients are pinned to cores 0-71 sequentially (so that wrong packets on q#s +72-143 can be measured). IRQs are set 1:1 for queues -> CPUs, enable XPS, +enable aRFS (global value is 144 * rps_flow_cnt). + +Test notes about results from ice_rx_flow_steer(): +--------------------------------------------------- +1. "Skip:" counter increments here: + if (fltr_info->q_index == rxq_idx || + arfs_entry->fltr_state != ICE_ARFS_ACTIVE) + goto out; +2. "Add:" counter increments here: + ret = arfs_entry->fltr_info.fltr_id; + INIT_HLIST_NODE(&arfs_entry->list_entry); +3. "Update:" counter increments here: + /* update the queue to forward to on an already existing flow */ + +Runtime comparison: original code vs with the patch for different +rps_flow_cnt values. + ++-------------------------------+--------------+--------------+ +| rps_flow_cnt | 512 | 2048 | ++-------------------------------+--------------+--------------+ +| Ratio of Pkts on Good:Bad q's | 214 vs 822K | 1.1M vs 980K | +| Avoid wrong aRFS programming | 0 vs 310K | 0 vs 30K | +| CPU User | 216 vs 183 | 216 vs 206 | +| CPU System | 1441 vs 1171 | 1447 vs 1320 | +| CPU Softirq | 1245 vs 920 | 1238 vs 961 | +| CPU Total | 29 vs 22.7 | 29 vs 24.9 | +| aRFS Update | 533K vs 59 | 521K vs 32 | +| aRFS Skip | 82M vs 77M | 7.2M vs 4.5M | ++-------------------------------+--------------+--------------+ + +A separate TCP_STREAM and TCP_RR with 1,4,8,16,64,128,256,512 connections +showed no performance degradation. + +Some points on the patch/aRFS behavior: +1. Enabling full tuple matching ensures flows are always correctly matched, + even with smaller hash sizes. +2. 5-6% drop in CPU utilization as the packets arrive at the correct CPUs + and fewer calls to driver for programming on misses. +3. Larger hash tables reduces mis-steering due to more unique flow hashes, + but still has clashes. However, with larger per-device rps_flow_cnt, old + flows take more time to expire and new aRFS flows cannot be added if h/w + limits are reached (rps_may_expire_flow() succeeds when 10*rps_flow_cnt + pkts have been processed by this cpu that are not part of the flow). + +Fixes: 28bf26724fdb0 ("ice: Implement aRFS") +Signed-off-by: Krishna Kumar <krikku@gmail.com> +Reviewed-by: Simon Horman <horms@kernel.org> +Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/intel/ice/ice_arfs.c | 48 +++++++++++++++++++++++ + 1 file changed, 48 insertions(+) + +diff --git a/drivers/net/ethernet/intel/ice/ice_arfs.c b/drivers/net/ethernet/intel/ice/ice_arfs.c +index 085b1a0d67c56..bb27474805c42 100644 +--- a/drivers/net/ethernet/intel/ice/ice_arfs.c ++++ b/drivers/net/ethernet/intel/ice/ice_arfs.c +@@ -376,6 +376,50 @@ ice_arfs_is_perfect_flow_set(struct ice_hw *hw, __be16 l3_proto, u8 l4_proto) + return false; + } + ++/** ++ * ice_arfs_cmp - Check if aRFS filter matches this flow. ++ * @fltr_info: filter info of the saved ARFS entry. ++ * @fk: flow dissector keys. ++ * @n_proto: One of htons(ETH_P_IP) or htons(ETH_P_IPV6). ++ * @ip_proto: One of IPPROTO_TCP or IPPROTO_UDP. ++ * ++ * Since this function assumes limited values for n_proto and ip_proto, it ++ * is meant to be called only from ice_rx_flow_steer(). ++ * ++ * Return: ++ * * true - fltr_info refers to the same flow as fk. ++ * * false - fltr_info and fk refer to different flows. ++ */ ++static bool ++ice_arfs_cmp(const struct ice_fdir_fltr *fltr_info, const struct flow_keys *fk, ++ __be16 n_proto, u8 ip_proto) ++{ ++ /* Determine if the filter is for IPv4 or IPv6 based on flow_type, ++ * which is one of ICE_FLTR_PTYPE_NONF_IPV{4,6}_{TCP,UDP}. ++ */ ++ bool is_v4 = fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP || ++ fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP; ++ ++ /* Following checks are arranged in the quickest and most discriminative ++ * fields first for early failure. ++ */ ++ if (is_v4) ++ return n_proto == htons(ETH_P_IP) && ++ fltr_info->ip.v4.src_port == fk->ports.src && ++ fltr_info->ip.v4.dst_port == fk->ports.dst && ++ fltr_info->ip.v4.src_ip == fk->addrs.v4addrs.src && ++ fltr_info->ip.v4.dst_ip == fk->addrs.v4addrs.dst && ++ fltr_info->ip.v4.proto == ip_proto; ++ ++ return fltr_info->ip.v6.src_port == fk->ports.src && ++ fltr_info->ip.v6.dst_port == fk->ports.dst && ++ fltr_info->ip.v6.proto == ip_proto && ++ !memcmp(&fltr_info->ip.v6.src_ip, &fk->addrs.v6addrs.src, ++ sizeof(struct in6_addr)) && ++ !memcmp(&fltr_info->ip.v6.dst_ip, &fk->addrs.v6addrs.dst, ++ sizeof(struct in6_addr)); ++} ++ + /** + * ice_rx_flow_steer - steer the Rx flow to where application is being run + * @netdev: ptr to the netdev being adjusted +@@ -447,6 +491,10 @@ ice_rx_flow_steer(struct net_device *netdev, const struct sk_buff *skb, + continue; + + fltr_info = &arfs_entry->fltr_info; ++ ++ if (!ice_arfs_cmp(fltr_info, &fk, n_proto, ip_proto)) ++ continue; ++ + ret = fltr_info->fltr_id; + + if (fltr_info->q_index == rxq_idx || +-- +2.39.5 + diff --git a/queue-5.10/pldmfw-select-crc32-when-pldmfw-is-selected.patch b/queue-5.10/pldmfw-select-crc32-when-pldmfw-is-selected.patch new file mode 100644 index 0000000000..bbd1e18aa7 --- /dev/null +++ b/queue-5.10/pldmfw-select-crc32-when-pldmfw-is-selected.patch @@ -0,0 +1,49 @@ +From 3e1f1c80ea43e46b11a60636117437ce52ddc23b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 13 Jun 2025 17:46:20 +0100 +Subject: pldmfw: Select CRC32 when PLDMFW is selected + +From: Simon Horman <horms@kernel.org> + +[ Upstream commit 1224b218a4b9203656ecc932152f4c81a97b4fcc ] + +pldmfw calls crc32 code and depends on it being enabled, else +there is a link error as follows. So PLDMFW should select CRC32. + + lib/pldmfw/pldmfw.o: In function `pldmfw_flash_image': + pldmfw.c:(.text+0x70f): undefined reference to `crc32_le_base' + +This problem was introduced by commit b8265621f488 ("Add pldmfw library +for PLDM firmware update"). + +It manifests as of commit d69ea414c9b4 ("ice: implement device flash +update via devlink"). + +And is more likely to occur as of commit 9ad19171b6d6 ("lib/crc: remove +unnecessary prompt for CONFIG_CRC32 and drop 'default y'"). + +Found by chance while exercising builds based on tinyconfig. + +Fixes: b8265621f488 ("Add pldmfw library for PLDM firmware update") +Signed-off-by: Simon Horman <horms@kernel.org> +Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> +Link: https://patch.msgid.link/20250613-pldmfw-crc32-v1-1-f3fad109eee6@kernel.org +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + lib/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/Kconfig b/lib/Kconfig +index 36326864249dd..4f280d0d93dbd 100644 +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -692,4 +692,5 @@ config GENERIC_LIB_UCMPDI2 + + config PLDMFW + bool ++ select CRC32 + default n +-- +2.39.5 + diff --git a/queue-5.10/series b/queue-5.10/series index a0bf590d43..eb575a5d31 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -301,3 +301,19 @@ mm-hugetlb-unshare-page-tables-during-vma-split-not-before.patch mm-hugetlb-independent-pmd-page-table-shared-count.patch mm-hugetlb-fix-huge_pmd_unshare-vs-gup-fast-race.patch erofs-remove-unused-trace-event-erofs_destroy_inode.patch +drm-nouveau-bl-increase-buffer-size-to-avoid-truncat.patch +hwmon-occ-add-new-temperature-sensor-type.patch +hwmon-occ-add-soft-minimum-power-cap-attribute.patch +hwmon-occ-rework-attribute-registration-for-stack-us.patch +hwmon-occ-fix-unaligned-accesses.patch +pldmfw-select-crc32-when-pldmfw-is-selected.patch +aoe-clean-device-rq_list-in-aoedev_downdev.patch +net-ice-perform-accurate-arfs-flow-match.patch +wifi-carl9170-do-not-ping-device-which-has-failed-to.patch +mpls-use-rcu_dereference_rtnl-in-mpls_route_input_rc.patch +atm-atmtcp-free-invalid-length-skb-in-atmtcp_c_send.patch +tcp-fix-tcp_packet_delayed-for-tcp_is_non_sack_preve.patch +tipc-fix-null-ptr-deref-when-acquiring-remote-ip-of-.patch +calipso-fix-null-ptr-deref-in-calipso_req_-set-del-a.patch +net-atm-add-lec_mutex.patch +net-atm-fix-proc-net-atm-lec-handling.patch diff --git a/queue-5.10/tcp-fix-tcp_packet_delayed-for-tcp_is_non_sack_preve.patch b/queue-5.10/tcp-fix-tcp_packet_delayed-for-tcp_is_non_sack_preve.patch new file mode 100644 index 0000000000..11139d98e7 --- /dev/null +++ b/queue-5.10/tcp-fix-tcp_packet_delayed-for-tcp_is_non_sack_preve.patch @@ -0,0 +1,108 @@ +From 2a79daeb77c5a16ff2ac3efdeb8f0d883898a1cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 13 Jun 2025 15:30:56 -0400 +Subject: tcp: fix tcp_packet_delayed() for tcp_is_non_sack_preventing_reopen() + behavior + +From: Neal Cardwell <ncardwell@google.com> + +[ Upstream commit d0fa59897e049e84432600e86df82aab3dce7aa5 ] + +After the following commit from 2024: + +commit e37ab7373696 ("tcp: fix to allow timestamp undo if no retransmits were sent") + +...there was buggy behavior where TCP connections without SACK support +could easily see erroneous undo events at the end of fast recovery or +RTO recovery episodes. The erroneous undo events could cause those +connections to suffer repeated loss recovery episodes and high +retransmit rates. + +The problem was an interaction between the non-SACK behavior on these +connections and the undo logic. The problem is that, for non-SACK +connections at the end of a loss recovery episode, if snd_una == +high_seq, then tcp_is_non_sack_preventing_reopen() holds steady in +CA_Recovery or CA_Loss, but clears tp->retrans_stamp to 0. Then upon +the next ACK the "tcp: fix to allow timestamp undo if no retransmits +were sent" logic saw the tp->retrans_stamp at 0 and erroneously +concluded that no data was retransmitted, and erroneously performed an +undo of the cwnd reduction, restoring cwnd immediately to the value it +had before loss recovery. This caused an immediate burst of traffic +and build-up of queues and likely another immediate loss recovery +episode. + +This commit fixes tcp_packet_delayed() to ignore zero retrans_stamp +values for non-SACK connections when snd_una is at or above high_seq, +because tcp_is_non_sack_preventing_reopen() clears retrans_stamp in +this case, so it's not a valid signal that we can undo. + +Note that the commit named in the Fixes footer restored long-present +behavior from roughly 2005-2019, so apparently this bug was present +for a while during that era, and this was simply not caught. + +Fixes: e37ab7373696 ("tcp: fix to allow timestamp undo if no retransmits were sent") +Reported-by: Eric Wheeler <netdev@lists.ewheeler.net> +Closes: https://lore.kernel.org/netdev/64ea9333-e7f9-0df-b0f2-8d566143acab@ewheeler.net/ +Signed-off-by: Neal Cardwell <ncardwell@google.com> +Co-developed-by: Yuchung Cheng <ycheng@google.com> +Signed-off-by: Yuchung Cheng <ycheng@google.com> +Reviewed-by: Eric Dumazet <edumazet@google.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/ipv4/tcp_input.c | 37 +++++++++++++++++++++++++------------ + 1 file changed, 25 insertions(+), 12 deletions(-) + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index f239310e91590..82382ac1514f9 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -2424,20 +2424,33 @@ static inline bool tcp_packet_delayed(const struct tcp_sock *tp) + { + const struct sock *sk = (const struct sock *)tp; + +- if (tp->retrans_stamp && +- tcp_tsopt_ecr_before(tp, tp->retrans_stamp)) +- return true; /* got echoed TS before first retransmission */ +- +- /* Check if nothing was retransmitted (retrans_stamp==0), which may +- * happen in fast recovery due to TSQ. But we ignore zero retrans_stamp +- * in TCP_SYN_SENT, since when we set FLAG_SYN_ACKED we also clear +- * retrans_stamp even if we had retransmitted the SYN. ++ /* Received an echoed timestamp before the first retransmission? */ ++ if (tp->retrans_stamp) ++ return tcp_tsopt_ecr_before(tp, tp->retrans_stamp); ++ ++ /* We set tp->retrans_stamp upon the first retransmission of a loss ++ * recovery episode, so normally if tp->retrans_stamp is 0 then no ++ * retransmission has happened yet (likely due to TSQ, which can cause ++ * fast retransmits to be delayed). So if snd_una advanced while ++ * (tp->retrans_stamp is 0 then apparently a packet was merely delayed, ++ * not lost. But there are exceptions where we retransmit but then ++ * clear tp->retrans_stamp, so we check for those exceptions. + */ +- if (!tp->retrans_stamp && /* no record of a retransmit/SYN? */ +- sk->sk_state != TCP_SYN_SENT) /* not the FLAG_SYN_ACKED case? */ +- return true; /* nothing was retransmitted */ + +- return false; ++ /* (1) For non-SACK connections, tcp_is_non_sack_preventing_reopen() ++ * clears tp->retrans_stamp when snd_una == high_seq. ++ */ ++ if (!tcp_is_sack(tp) && !before(tp->snd_una, tp->high_seq)) ++ return false; ++ ++ /* (2) In TCP_SYN_SENT tcp_clean_rtx_queue() clears tp->retrans_stamp ++ * when setting FLAG_SYN_ACKED is set, even if the SYN was ++ * retransmitted. ++ */ ++ if (sk->sk_state == TCP_SYN_SENT) ++ return false; ++ ++ return true; /* tp->retrans_stamp is zero; no retransmit yet */ + } + + /* Undo procedures. */ +-- +2.39.5 + diff --git a/queue-5.10/tipc-fix-null-ptr-deref-when-acquiring-remote-ip-of-.patch b/queue-5.10/tipc-fix-null-ptr-deref-when-acquiring-remote-ip-of-.patch new file mode 100644 index 0000000000..b0884f2a2f --- /dev/null +++ b/queue-5.10/tipc-fix-null-ptr-deref-when-acquiring-remote-ip-of-.patch @@ -0,0 +1,65 @@ +From d1752cd9662bf4537cb820a7c7ccbd9b67e37cf8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 17 Jun 2025 05:56:24 +0000 +Subject: tipc: fix null-ptr-deref when acquiring remote ip of ethernet bearer + +From: Haixia Qu <hxqu@hillstonenet.com> + +[ Upstream commit f82727adcf2992822e12198792af450a76ebd5ef ] + +The reproduction steps: +1. create a tun interface +2. enable l2 bearer +3. TIPC_NL_UDP_GET_REMOTEIP with media name set to tun + +tipc: Started in network mode +tipc: Node identity 8af312d38a21, cluster identity 4711 +tipc: Enabled bearer <eth:syz_tun>, priority 1 +Oops: general protection fault +KASAN: null-ptr-deref in range +CPU: 1 UID: 1000 PID: 559 Comm: poc Not tainted 6.16.0-rc1+ #117 PREEMPT +Hardware name: QEMU Ubuntu 24.04 PC +RIP: 0010:tipc_udp_nl_dump_remoteip+0x4a4/0x8f0 + +the ub was in fact a struct dev. + +when bid != 0 && skip_cnt != 0, bearer_list[bid] may be NULL or +other media when other thread changes it. + +fix this by checking media_id. + +Fixes: 832629ca5c313 ("tipc: add UDP remoteip dump to netlink API") +Signed-off-by: Haixia Qu <hxqu@hillstonenet.com> +Reviewed-by: Tung Nguyen <tung.quang.nguyen@est.tech> +Link: https://patch.msgid.link/20250617055624.2680-1-hxqu@hillstonenet.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/tipc/udp_media.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c +index 25e733919131c..881f4c160dbf5 100644 +--- a/net/tipc/udp_media.c ++++ b/net/tipc/udp_media.c +@@ -481,7 +481,7 @@ int tipc_udp_nl_dump_remoteip(struct sk_buff *skb, struct netlink_callback *cb) + + rtnl_lock(); + b = tipc_bearer_find(net, bname); +- if (!b) { ++ if (!b || b->bcast_addr.media_id != TIPC_MEDIA_TYPE_UDP) { + rtnl_unlock(); + return -EINVAL; + } +@@ -492,7 +492,7 @@ int tipc_udp_nl_dump_remoteip(struct sk_buff *skb, struct netlink_callback *cb) + + rtnl_lock(); + b = rtnl_dereference(tn->bearer_list[bid]); +- if (!b) { ++ if (!b || b->bcast_addr.media_id != TIPC_MEDIA_TYPE_UDP) { + rtnl_unlock(); + return -EINVAL; + } +-- +2.39.5 + diff --git a/queue-5.10/wifi-carl9170-do-not-ping-device-which-has-failed-to.patch b/queue-5.10/wifi-carl9170-do-not-ping-device-which-has-failed-to.patch new file mode 100644 index 0000000000..8e4457e7ab --- /dev/null +++ b/queue-5.10/wifi-carl9170-do-not-ping-device-which-has-failed-to.patch @@ -0,0 +1,63 @@ +From e4e7795e398535f12726511dc94989789850c264 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 16 Jun 2025 21:12:05 +0300 +Subject: wifi: carl9170: do not ping device which has failed to load firmware + +From: Dmitry Antipov <dmantipov@yandex.ru> + +[ Upstream commit 15d25307692312cec4b57052da73387f91a2e870 ] + +Syzkaller reports [1, 2] crashes caused by an attempts to ping +the device which has failed to load firmware. Since such a device +doesn't pass 'ieee80211_register_hw()', an internal workqueue +managed by 'ieee80211_queue_work()' is not yet created and an +attempt to queue work on it causes null-ptr-deref. + +[1] https://syzkaller.appspot.com/bug?extid=9a4aec827829942045ff +[2] https://syzkaller.appspot.com/bug?extid=0d8afba53e8fb2633217 + +Fixes: e4a668c59080 ("carl9170: fix spurious restart due to high latency") +Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru> +Acked-by: Christian Lamparter <chunkeey@gmail.com> +Link: https://patch.msgid.link/20250616181205.38883-1-dmantipov@yandex.ru +Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/ath/carl9170/usb.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c +index a5265997b5767..debac4699687e 100644 +--- a/drivers/net/wireless/ath/carl9170/usb.c ++++ b/drivers/net/wireless/ath/carl9170/usb.c +@@ -438,14 +438,21 @@ static void carl9170_usb_rx_complete(struct urb *urb) + + if (atomic_read(&ar->rx_anch_urbs) == 0) { + /* +- * The system is too slow to cope with +- * the enormous workload. We have simply +- * run out of active rx urbs and this +- * unfortunately leads to an unpredictable +- * device. ++ * At this point, either the system is too slow to ++ * cope with the enormous workload (so we have simply ++ * run out of active rx urbs and this unfortunately ++ * leads to an unpredictable device), or the device ++ * is not fully functional after an unsuccessful ++ * firmware loading attempts (so it doesn't pass ++ * ieee80211_register_hw() and there is no internal ++ * workqueue at all). + */ + +- ieee80211_queue_work(ar->hw, &ar->ping_work); ++ if (ar->registered) ++ ieee80211_queue_work(ar->hw, &ar->ping_work); ++ else ++ pr_warn_once("device %s is not registered\n", ++ dev_name(&ar->udev->dev)); + } + } else { + /* +-- +2.39.5 + |