From bcf21c5951e8d5fb671b72371fc32f43b0ee2d29 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Sep 2025 14:26:49 +0200 Subject: [PATCH] 5.4-stable patches added patches: net-fix-null-ptr-deref-by-sock_lock_init_class_and_name-and-rmmod.patch series usb-hub-fix-flushing-of-delayed-work-used-for-post-resume-purposes.patch --- ...k_lock_init_class_and_name-and-rmmod.patch | 272 ++++++++++++++++++ queue-5.4/series | 2 + ...d-work-used-for-post-resume-purposes.patch | 119 ++++++++ 3 files changed, 393 insertions(+) create mode 100644 queue-5.4/net-fix-null-ptr-deref-by-sock_lock_init_class_and_name-and-rmmod.patch create mode 100644 queue-5.4/series create mode 100644 queue-5.4/usb-hub-fix-flushing-of-delayed-work-used-for-post-resume-purposes.patch diff --git a/queue-5.4/net-fix-null-ptr-deref-by-sock_lock_init_class_and_name-and-rmmod.patch b/queue-5.4/net-fix-null-ptr-deref-by-sock_lock_init_class_and_name-and-rmmod.patch new file mode 100644 index 0000000000..613902b654 --- /dev/null +++ b/queue-5.4/net-fix-null-ptr-deref-by-sock_lock_init_class_and_name-and-rmmod.patch @@ -0,0 +1,272 @@ +From 0bb2f7a1ad1f11d861f58e5ee5051c8974ff9569 Mon Sep 17 00:00:00 2001 +From: Kuniyuki Iwashima +Date: Mon, 7 Apr 2025 09:33:11 -0700 +Subject: net: Fix null-ptr-deref by sock_lock_init_class_and_name() and rmmod. + +From: Kuniyuki Iwashima + +commit 0bb2f7a1ad1f11d861f58e5ee5051c8974ff9569 upstream. + +When I ran the repro [0] and waited a few seconds, I observed two +LOCKDEP splats: a warning immediately followed by a null-ptr-deref. [1] + +Reproduction Steps: + + 1) Mount CIFS + 2) Add an iptables rule to drop incoming FIN packets for CIFS + 3) Unmount CIFS + 4) Unload the CIFS module + 5) Remove the iptables rule + +At step 3), the CIFS module calls sock_release() for the underlying +TCP socket, and it returns quickly. However, the socket remains in +FIN_WAIT_1 because incoming FIN packets are dropped. + +At this point, the module's refcnt is 0 while the socket is still +alive, so the following rmmod command succeeds. + + # ss -tan + State Recv-Q Send-Q Local Address:Port Peer Address:Port + FIN-WAIT-1 0 477 10.0.2.15:51062 10.0.0.137:445 + + # lsmod | grep cifs + cifs 1159168 0 + +This highlights a discrepancy between the lifetime of the CIFS module +and the underlying TCP socket. Even after CIFS calls sock_release() +and it returns, the TCP socket does not die immediately in order to +close the connection gracefully. + +While this is generally fine, it causes an issue with LOCKDEP because +CIFS assigns a different lock class to the TCP socket's sk->sk_lock +using sock_lock_init_class_and_name(). + +Once an incoming packet is processed for the socket or a timer fires, +sk->sk_lock is acquired. + +Then, LOCKDEP checks the lock context in check_wait_context(), where +hlock_class() is called to retrieve the lock class. However, since +the module has already been unloaded, hlock_class() logs a warning +and returns NULL, triggering the null-ptr-deref. + +If LOCKDEP is enabled, we must ensure that a module calling +sock_lock_init_class_and_name() (CIFS, NFS, etc) cannot be unloaded +while such a socket is still alive to prevent this issue. + +Let's hold the module reference in sock_lock_init_class_and_name() +and release it when the socket is freed in sk_prot_free(). + +Note that sock_lock_init() clears sk->sk_owner for svc_create_socket() +that calls sock_lock_init_class_and_name() for a listening socket, +which clones a socket by sk_clone_lock() without GFP_ZERO. + +[0]: +CIFS_SERVER="10.0.0.137" +CIFS_PATH="//${CIFS_SERVER}/Users/Administrator/Desktop/CIFS_TEST" +DEV="enp0s3" +CRED="/root/WindowsCredential.txt" + +MNT=$(mktemp -d /tmp/XXXXXX) +mount -t cifs ${CIFS_PATH} ${MNT} -o vers=3.0,credentials=${CRED},cache=none,echo_interval=1 + +iptables -A INPUT -s ${CIFS_SERVER} -j DROP + +for i in $(seq 10); +do + umount ${MNT} + rmmod cifs + sleep 1 +done + +rm -r ${MNT} + +iptables -D INPUT -s ${CIFS_SERVER} -j DROP + +[1]: +DEBUG_LOCKS_WARN_ON(1) +WARNING: CPU: 10 PID: 0 at kernel/locking/lockdep.c:234 hlock_class (kernel/locking/lockdep.c:234 kernel/locking/lockdep.c:223) +Modules linked in: cifs_arc4 nls_ucs2_utils cifs_md4 [last unloaded: cifs] +CPU: 10 UID: 0 PID: 0 Comm: swapper/10 Not tainted 6.14.0 #36 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014 +RIP: 0010:hlock_class (kernel/locking/lockdep.c:234 kernel/locking/lockdep.c:223) +... +Call Trace: + + __lock_acquire (kernel/locking/lockdep.c:4853 kernel/locking/lockdep.c:5178) + lock_acquire (kernel/locking/lockdep.c:469 kernel/locking/lockdep.c:5853 kernel/locking/lockdep.c:5816) + _raw_spin_lock_nested (kernel/locking/spinlock.c:379) + tcp_v4_rcv (./include/linux/skbuff.h:1678 ./include/net/tcp.h:2547 net/ipv4/tcp_ipv4.c:2350) +... + +BUG: kernel NULL pointer dereference, address: 00000000000000c4 + PF: supervisor read access in kernel mode + PF: error_code(0x0000) - not-present page +PGD 0 +Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI +CPU: 10 UID: 0 PID: 0 Comm: swapper/10 Tainted: G W 6.14.0 #36 +Tainted: [W]=WARN +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014 +RIP: 0010:__lock_acquire (kernel/locking/lockdep.c:4852 kernel/locking/lockdep.c:5178) +Code: 15 41 09 c7 41 8b 44 24 20 25 ff 1f 00 00 41 09 c7 8b 84 24 a0 00 00 00 45 89 7c 24 20 41 89 44 24 24 e8 e1 bc ff ff 4c 89 e7 <44> 0f b6 b8 c4 00 00 00 e8 d1 bc ff ff 0f b6 80 c5 00 00 00 88 44 +RSP: 0018:ffa0000000468a10 EFLAGS: 00010046 +RAX: 0000000000000000 RBX: ff1100010091cc38 RCX: 0000000000000027 +RDX: ff1100081f09ca48 RSI: 0000000000000001 RDI: ff1100010091cc88 +RBP: ff1100010091c200 R08: ff1100083fe6e228 R09: 00000000ffffbfff +R10: ff1100081eca0000 R11: ff1100083fe10dc0 R12: ff1100010091cc88 +R13: 0000000000000001 R14: 0000000000000000 R15: 00000000000424b1 +FS: 0000000000000000(0000) GS:ff1100081f080000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00000000000000c4 CR3: 0000000002c4a003 CR4: 0000000000771ef0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400 +PKRU: 55555554 +Call Trace: + + lock_acquire (kernel/locking/lockdep.c:469 kernel/locking/lockdep.c:5853 kernel/locking/lockdep.c:5816) + _raw_spin_lock_nested (kernel/locking/spinlock.c:379) + tcp_v4_rcv (./include/linux/skbuff.h:1678 ./include/net/tcp.h:2547 net/ipv4/tcp_ipv4.c:2350) + ip_protocol_deliver_rcu (net/ipv4/ip_input.c:205 (discriminator 1)) + ip_local_deliver_finish (./include/linux/rcupdate.h:878 net/ipv4/ip_input.c:234) + ip_sublist_rcv_finish (net/ipv4/ip_input.c:576) + ip_list_rcv_finish (net/ipv4/ip_input.c:628) + ip_list_rcv (net/ipv4/ip_input.c:670) + __netif_receive_skb_list_core (net/core/dev.c:5939 net/core/dev.c:5986) + netif_receive_skb_list_internal (net/core/dev.c:6040 net/core/dev.c:6129) + napi_complete_done (./include/linux/list.h:37 ./include/net/gro.h:519 ./include/net/gro.h:514 net/core/dev.c:6496) + e1000_clean (drivers/net/ethernet/intel/e1000/e1000_main.c:3815) + __napi_poll.constprop.0 (net/core/dev.c:7191) + net_rx_action (net/core/dev.c:7262 net/core/dev.c:7382) + handle_softirqs (kernel/softirq.c:561) + __irq_exit_rcu (kernel/softirq.c:596 kernel/softirq.c:435 kernel/softirq.c:662) + irq_exit_rcu (kernel/softirq.c:680) + common_interrupt (arch/x86/kernel/irq.c:280 (discriminator 14)) + + + asm_common_interrupt (./arch/x86/include/asm/idtentry.h:693) +RIP: 0010:default_idle (./arch/x86/include/asm/irqflags.h:37 ./arch/x86/include/asm/irqflags.h:92 arch/x86/kernel/process.c:744) +Code: 4c 01 c7 4c 29 c2 e9 72 ff ff ff 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f 1e fa eb 07 0f 00 2d c3 2b 15 00 fb f4 c3 cc cc cc cc 66 66 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90 +RSP: 0018:ffa00000000ffee8 EFLAGS: 00000202 +RAX: 000000000000640b RBX: ff1100010091c200 RCX: 0000000000061aa4 +RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffff812f30c5 +RBP: 000000000000000a R08: 0000000000000001 R09: 0000000000000000 +R10: 0000000000000001 R11: 0000000000000002 R12: 0000000000000000 +R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 + ? do_idle (kernel/sched/idle.c:186 kernel/sched/idle.c:325) + default_idle_call (./include/linux/cpuidle.h:143 kernel/sched/idle.c:118) + do_idle (kernel/sched/idle.c:186 kernel/sched/idle.c:325) + cpu_startup_entry (kernel/sched/idle.c:422 (discriminator 1)) + start_secondary (arch/x86/kernel/smpboot.c:315) + common_startup_64 (arch/x86/kernel/head_64.S:421) + +Modules linked in: cifs_arc4 nls_ucs2_utils cifs_md4 [last unloaded: cifs] +CR2: 00000000000000c4 + +Fixes: ed07536ed673 ("[PATCH] lockdep: annotate nfs/nfsd in-kernel sockets") +Signed-off-by: Kuniyuki Iwashima +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20250407163313.22682-1-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +[ no ns_tracker and sk_user_frags fields ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/net/sock.h | 40 ++++++++++++++++++++++++++++++++++++++-- + net/core/sock.c | 5 +++++ + 2 files changed, 43 insertions(+), 2 deletions(-) + +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -321,6 +321,8 @@ struct bpf_sk_storage; + * @sk_clockid: clockid used by time-based scheduling (SO_TXTIME) + * @sk_txtime_deadline_mode: set deadline mode for SO_TXTIME + * @sk_txtime_unused: unused txtime flags ++ * @sk_owner: reference to the real owner of the socket that calls ++ * sock_lock_init_class_and_name(). + */ + struct sock { + /* +@@ -515,6 +517,10 @@ struct sock { + struct bpf_sk_storage __rcu *sk_bpf_storage; + #endif + struct rcu_head sk_rcu; ++ ++#if IS_ENABLED(CONFIG_PROVE_LOCKING) && IS_ENABLED(CONFIG_MODULES) ++ struct module *sk_owner; ++#endif + }; + + enum sk_pacing { +@@ -1525,6 +1531,35 @@ static inline void sock_release_ownershi + } + } + ++#if IS_ENABLED(CONFIG_PROVE_LOCKING) && IS_ENABLED(CONFIG_MODULES) ++static inline void sk_owner_set(struct sock *sk, struct module *owner) ++{ ++ __module_get(owner); ++ sk->sk_owner = owner; ++} ++ ++static inline void sk_owner_clear(struct sock *sk) ++{ ++ sk->sk_owner = NULL; ++} ++ ++static inline void sk_owner_put(struct sock *sk) ++{ ++ module_put(sk->sk_owner); ++} ++#else ++static inline void sk_owner_set(struct sock *sk, struct module *owner) ++{ ++} ++ ++static inline void sk_owner_clear(struct sock *sk) ++{ ++} ++ ++static inline void sk_owner_put(struct sock *sk) ++{ ++} ++#endif + /* + * Macro so as to not evaluate some arguments when + * lockdep is not enabled. +@@ -1534,13 +1569,14 @@ static inline void sock_release_ownershi + */ + #define sock_lock_init_class_and_name(sk, sname, skey, name, key) \ + do { \ ++ sk_owner_set(sk, THIS_MODULE); \ + sk->sk_lock.owned = 0; \ + init_waitqueue_head(&sk->sk_lock.wq); \ + spin_lock_init(&(sk)->sk_lock.slock); \ + debug_check_no_locks_freed((void *)&(sk)->sk_lock, \ +- sizeof((sk)->sk_lock)); \ ++ sizeof((sk)->sk_lock)); \ + lockdep_set_class_and_name(&(sk)->sk_lock.slock, \ +- (skey), (sname)); \ ++ (skey), (sname)); \ + lockdep_init_map(&(sk)->sk_lock.dep_map, (name), (key), 0); \ + } while (0) + +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -1567,6 +1567,8 @@ lenout: + */ + static inline void sock_lock_init(struct sock *sk) + { ++ sk_owner_clear(sk); ++ + if (sk->sk_kern_sock) + sock_lock_init_class_and_name( + sk, +@@ -1652,6 +1654,9 @@ static void sk_prot_free(struct proto *p + cgroup_sk_free(&sk->sk_cgrp_data); + mem_cgroup_sk_free(sk); + security_sk_free(sk); ++ ++ sk_owner_put(sk); ++ + if (slab != NULL) + kmem_cache_free(slab, sk); + else diff --git a/queue-5.4/series b/queue-5.4/series new file mode 100644 index 0000000000..b17c4b4c7b --- /dev/null +++ b/queue-5.4/series @@ -0,0 +1,2 @@ +usb-hub-fix-flushing-of-delayed-work-used-for-post-resume-purposes.patch +net-fix-null-ptr-deref-by-sock_lock_init_class_and_name-and-rmmod.patch diff --git a/queue-5.4/usb-hub-fix-flushing-of-delayed-work-used-for-post-resume-purposes.patch b/queue-5.4/usb-hub-fix-flushing-of-delayed-work-used-for-post-resume-purposes.patch new file mode 100644 index 0000000000..6ed6c340a6 --- /dev/null +++ b/queue-5.4/usb-hub-fix-flushing-of-delayed-work-used-for-post-resume-purposes.patch @@ -0,0 +1,119 @@ +From 9bd9c8026341f75f25c53104eb7e656e357ca1a2 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Fri, 27 Jun 2025 19:43:48 +0300 +Subject: usb: hub: Fix flushing of delayed work used for post resume purposes + +From: Mathias Nyman + +commit 9bd9c8026341f75f25c53104eb7e656e357ca1a2 upstream. + +Delayed work that prevents USB3 hubs from runtime-suspending too early +needed to be flushed in hub_quiesce() to resolve issues detected on +QC SC8280XP CRD board during suspend resume testing. + +This flushing did however trigger new issues on Raspberry Pi 3B+, which +doesn't have USB3 ports, and doesn't queue any post resume delayed work. + +The flushed 'hub->init_work' item is used for several purposes, and +is originally initialized with a 'NULL' work function. The work function +is also changed on the fly, which may contribute to the issue. + +Solve this by creating a dedicated delayed work item for post resume work, +and flush that delayed work in hub_quiesce() + +Cc: stable +Fixes: a49e1e2e785f ("usb: hub: Fix flushing and scheduling of delayed work that tunes runtime pm") +Reported-by: Mark Brown +Closes: https://lore.kernel.org/linux-usb/aF5rNp1l0LWITnEB@finisterre.sirena.org.uk +Signed-off-by: Mathias Nyman +Tested-by: Konrad Dybcio # SC8280XP CRD +Tested-by: Mark Brown +Link: https://lore.kernel.org/r/20250627164348.3982628-2-mathias.nyman@linux.intel.com +[florian: adjust for lack of hub_{get,put} and timer_delete_sync] +Signed-off-by: Florian Fainelli +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/hub.c | 21 ++++++++------------- + drivers/usb/core/hub.h | 1 + + 2 files changed, 9 insertions(+), 13 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -1030,12 +1030,11 @@ int usb_remove_device(struct usb_device + + enum hub_activation_type { + HUB_INIT, HUB_INIT2, HUB_INIT3, /* INITs must come first */ +- HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME, HUB_POST_RESUME, ++ HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME, + }; + + static void hub_init_func2(struct work_struct *ws); + static void hub_init_func3(struct work_struct *ws); +-static void hub_post_resume(struct work_struct *ws); + + static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) + { +@@ -1059,12 +1058,6 @@ static void hub_activate(struct usb_hub + goto init3; + } + +- if (type == HUB_POST_RESUME) { +- usb_autopm_put_interface_async(to_usb_interface(hub->intfdev)); +- kref_put(&hub->kref, hub_release); +- return; +- } +- + kref_get(&hub->kref); + + /* The superspeed hub except for root hub has to use Hub Depth +@@ -1318,8 +1311,8 @@ static void hub_activate(struct usb_hub + usb_autopm_get_interface_no_resume( + to_usb_interface(hub->intfdev)); + +- INIT_DELAYED_WORK(&hub->init_work, hub_post_resume); +- queue_delayed_work(system_power_efficient_wq, &hub->init_work, ++ queue_delayed_work(system_power_efficient_wq, ++ &hub->post_resume_work, + msecs_to_jiffies(USB_SS_PORT_U0_WAKE_TIME)); + return; + } +@@ -1344,9 +1337,10 @@ static void hub_init_func3(struct work_s + + static void hub_post_resume(struct work_struct *ws) + { +- struct usb_hub *hub = container_of(ws, struct usb_hub, init_work.work); ++ struct usb_hub *hub = container_of(ws, struct usb_hub, post_resume_work.work); + +- hub_activate(hub, HUB_POST_RESUME); ++ usb_autopm_put_interface_async(to_usb_interface(hub->intfdev)); ++ kref_put(&hub->kref, hub_release); + } + + enum hub_quiescing_type { +@@ -1374,7 +1368,7 @@ static void hub_quiesce(struct usb_hub * + + /* Stop hub_wq and related activity */ + del_timer_sync(&hub->irq_urb_retry); +- flush_delayed_work(&hub->init_work); ++ flush_delayed_work(&hub->post_resume_work); + usb_kill_urb(hub->urb); + if (hub->has_indicators) + cancel_delayed_work_sync(&hub->leds); +@@ -1921,6 +1915,7 @@ static int hub_probe(struct usb_interfac + hub->hdev = hdev; + INIT_DELAYED_WORK(&hub->leds, led_work); + INIT_DELAYED_WORK(&hub->init_work, NULL); ++ INIT_DELAYED_WORK(&hub->post_resume_work, hub_post_resume); + INIT_WORK(&hub->events, hub_event); + spin_lock_init(&hub->irq_urb_lock); + timer_setup(&hub->irq_urb_retry, hub_retry_irq_urb, 0); +--- a/drivers/usb/core/hub.h ++++ b/drivers/usb/core/hub.h +@@ -69,6 +69,7 @@ struct usb_hub { + u8 indicator[USB_MAXCHILDREN]; + struct delayed_work leds; + struct delayed_work init_work; ++ struct delayed_work post_resume_work; + struct work_struct events; + spinlock_t irq_urb_lock; + struct timer_list irq_urb_retry; -- 2.47.3