From 07efdda76e604908dbca20bbe17f8fe1045770aa Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Tue, 22 Nov 2022 10:17:59 -0500 Subject: [PATCH] Fixes for 5.10 Signed-off-by: Sasha Levin --- ...leaking-of-platform-device-on-module.patch | 54 ++++ ...aring-aggrprobe-s-post_handler-in-kp.patch | 75 +++++ ...ccess-to-sk_user_data-with-sk_callba.patch | 122 ++++++++ ...currency-bug-in-l2tp_tunnel_register.patch | 76 +++++ ...roup-to-copy-ip-ipv6-header-addresse.patch | 111 ++++++++ ...ude-dropped-pages-in-counting-dirty-.patch | 95 +++++++ ...fix-possible-uaf-in-sdebug_add_host_.patch | 44 +++ ...loop-fix-possible-name-leak-in-tcm_l.patch | 51 ++++ queue-5.10/series | 10 + ...-introduce-struct_group-helper-macro.patch | 262 ++++++++++++++++++ ...c95xx-fix-deadlock-on-runtime-resume.patch | 194 +++++++++++++ 11 files changed, 1094 insertions(+) create mode 100644 queue-5.10/input-i8042-fix-leaking-of-platform-device-on-module.patch create mode 100644 queue-5.10/kprobes-skip-clearing-aggrprobe-s-post_handler-in-kp.patch create mode 100644 queue-5.10/l2tp-serialize-access-to-sk_user_data-with-sk_callba.patch create mode 100644 queue-5.10/net-fix-a-concurrency-bug-in-l2tp_tunnel_register.patch create mode 100644 queue-5.10/net-use-struct_group-to-copy-ip-ipv6-header-addresse.patch create mode 100644 queue-5.10/ring-buffer-include-dropped-pages-in-counting-dirty-.patch create mode 100644 queue-5.10/scsi-scsi_debug-fix-possible-uaf-in-sdebug_add_host_.patch create mode 100644 queue-5.10/scsi-target-tcm_loop-fix-possible-name-leak-in-tcm_l.patch create mode 100644 queue-5.10/stddef-introduce-struct_group-helper-macro.patch create mode 100644 queue-5.10/usbnet-smsc95xx-fix-deadlock-on-runtime-resume.patch diff --git a/queue-5.10/input-i8042-fix-leaking-of-platform-device-on-module.patch b/queue-5.10/input-i8042-fix-leaking-of-platform-device-on-module.patch new file mode 100644 index 00000000000..3bff1a3e16a --- /dev/null +++ b/queue-5.10/input-i8042-fix-leaking-of-platform-device-on-module.patch @@ -0,0 +1,54 @@ +From cc04c3de3bab0b9beed062957f05ed5d8777970c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 15:40:03 -0800 +Subject: Input: i8042 - fix leaking of platform device on module removal + +From: Chen Jun + +[ Upstream commit 81cd7e8489278d28794e7b272950c3e00c344e44 ] + +Avoid resetting the module-wide i8042_platform_device pointer in +i8042_probe() or i8042_remove(), so that the device can be properly +destroyed by i8042_exit() on module unload. + +Fixes: 9222ba68c3f4 ("Input: i8042 - add deferred probe support") +Signed-off-by: Chen Jun +Link: https://lore.kernel.org/r/20221109034148.23821-1-chenjun102@huawei.com +Signed-off-by: Dmitry Torokhov +Signed-off-by: Sasha Levin +--- + drivers/input/serio/i8042.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c +index a9f68f535b72..8648b4c46138 100644 +--- a/drivers/input/serio/i8042.c ++++ b/drivers/input/serio/i8042.c +@@ -1543,8 +1543,6 @@ static int i8042_probe(struct platform_device *dev) + { + int error; + +- i8042_platform_device = dev; +- + if (i8042_reset == I8042_RESET_ALWAYS) { + error = i8042_controller_selftest(); + if (error) +@@ -1582,7 +1580,6 @@ static int i8042_probe(struct platform_device *dev) + i8042_free_aux_ports(); /* in case KBD failed but AUX not */ + i8042_free_irqs(); + i8042_controller_reset(false); +- i8042_platform_device = NULL; + + return error; + } +@@ -1592,7 +1589,6 @@ static int i8042_remove(struct platform_device *dev) + i8042_unregister_ports(); + i8042_free_irqs(); + i8042_controller_reset(false); +- i8042_platform_device = NULL; + + return 0; + } +-- +2.35.1 + diff --git a/queue-5.10/kprobes-skip-clearing-aggrprobe-s-post_handler-in-kp.patch b/queue-5.10/kprobes-skip-clearing-aggrprobe-s-post_handler-in-kp.patch new file mode 100644 index 00000000000..e3ecc61632b --- /dev/null +++ b/queue-5.10/kprobes-skip-clearing-aggrprobe-s-post_handler-in-kp.patch @@ -0,0 +1,75 @@ +From cf8f6996ec58a080ef98f1a63b31ea1c75acdf57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 10:15:34 +0900 +Subject: kprobes: Skip clearing aggrprobe's post_handler in kprobe-on-ftrace + case + +From: Li Huafei + +[ Upstream commit 5dd7caf0bdc5d0bae7cf9776b4d739fb09bd5ebb ] + +In __unregister_kprobe_top(), if the currently unregistered probe has +post_handler but other child probes of the aggrprobe do not have +post_handler, the post_handler of the aggrprobe is cleared. If this is +a ftrace-based probe, there is a problem. In later calls to +disarm_kprobe(), we will use kprobe_ftrace_ops because post_handler is +NULL. But we're armed with kprobe_ipmodify_ops. This triggers a WARN in +__disarm_kprobe_ftrace() and may even cause use-after-free: + + Failed to disarm kprobe-ftrace at kernel_clone+0x0/0x3c0 (error -2) + WARNING: CPU: 5 PID: 137 at kernel/kprobes.c:1135 __disarm_kprobe_ftrace.isra.21+0xcf/0xe0 + Modules linked in: testKprobe_007(-) + CPU: 5 PID: 137 Comm: rmmod Not tainted 6.1.0-rc4-dirty #18 + [...] + Call Trace: + + __disable_kprobe+0xcd/0xe0 + __unregister_kprobe_top+0x12/0x150 + ? mutex_lock+0xe/0x30 + unregister_kprobes.part.23+0x31/0xa0 + unregister_kprobe+0x32/0x40 + __x64_sys_delete_module+0x15e/0x260 + ? do_user_addr_fault+0x2cd/0x6b0 + do_syscall_64+0x3a/0x90 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + [...] + +For the kprobe-on-ftrace case, we keep the post_handler setting to +identify this aggrprobe armed with kprobe_ipmodify_ops. This way we +can disarm it correctly. + +Link: https://lore.kernel.org/all/20221112070000.35299-1-lihuafei1@huawei.com/ + +Fixes: 0bc11ed5ab60 ("kprobes: Allow kprobes coexist with livepatch") +Reported-by: Zhao Gongyi +Suggested-by: Masami Hiramatsu (Google) +Signed-off-by: Li Huafei +Acked-by: Masami Hiramatsu (Google) +Signed-off-by: Masami Hiramatsu (Google) +Signed-off-by: Sasha Levin +--- + kernel/kprobes.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/kernel/kprobes.c b/kernel/kprobes.c +index b0f444e86487..75150e755518 100644 +--- a/kernel/kprobes.c ++++ b/kernel/kprobes.c +@@ -1841,7 +1841,13 @@ static int __unregister_kprobe_top(struct kprobe *p) + if ((list_p != p) && (list_p->post_handler)) + goto noclean; + } +- ap->post_handler = NULL; ++ /* ++ * For the kprobe-on-ftrace case, we keep the ++ * post_handler setting to identify this aggrprobe ++ * armed with kprobe_ipmodify_ops. ++ */ ++ if (!kprobe_ftrace(ap)) ++ ap->post_handler = NULL; + } + noclean: + /* +-- +2.35.1 + diff --git a/queue-5.10/l2tp-serialize-access-to-sk_user_data-with-sk_callba.patch b/queue-5.10/l2tp-serialize-access-to-sk_user_data-with-sk_callba.patch new file mode 100644 index 00000000000..a219a19c8d0 --- /dev/null +++ b/queue-5.10/l2tp-serialize-access-to-sk_user_data-with-sk_callba.patch @@ -0,0 +1,122 @@ +From 6e121ef3f53982e168e775c4dececf3a2556c0fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 20:16:19 +0100 +Subject: l2tp: Serialize access to sk_user_data with sk_callback_lock + +From: Jakub Sitnicki + +[ Upstream commit b68777d54fac21fc833ec26ea1a2a84f975ab035 ] + +sk->sk_user_data has multiple users, which are not compatible with each +other. Writers must synchronize by grabbing the sk->sk_callback_lock. + +l2tp currently fails to grab the lock when modifying the underlying tunnel +socket fields. Fix it by adding appropriate locking. + +We err on the side of safety and grab the sk_callback_lock also inside the +sk_destruct callback overridden by l2tp, even though there should be no +refs allowing access to the sock at the time when sk_destruct gets called. + +v4: +- serialize write to sk_user_data in l2tp sk_destruct + +v3: +- switch from sock lock to sk_callback_lock +- document write-protection for sk_user_data + +v2: +- update Fixes to point to origin of the bug +- use real names in Reported/Tested-by tags + +Cc: Tom Parkin +Fixes: 3557baabf280 ("[L2TP]: PPP over L2TP driver core") +Reported-by: Haowei Yan +Signed-off-by: Jakub Sitnicki +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + include/net/sock.h | 2 +- + net/l2tp/l2tp_core.c | 19 +++++++++++++------ + 2 files changed, 14 insertions(+), 7 deletions(-) + +diff --git a/include/net/sock.h b/include/net/sock.h +index 90a8b8b26a20..69bbbe8bbf34 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -315,7 +315,7 @@ struct bpf_local_storage; + * @sk_tskey: counter to disambiguate concurrent tstamp requests + * @sk_zckey: counter to order MSG_ZEROCOPY notifications + * @sk_socket: Identd and reporting IO signals +- * @sk_user_data: RPC layer private data ++ * @sk_user_data: RPC layer private data. Write-protected by @sk_callback_lock. + * @sk_frag: cached page frag + * @sk_peek_off: current peek_offset value + * @sk_send_head: front of stuff to transmit +diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c +index dc8987ed08ad..e89852bc5309 100644 +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -1150,8 +1150,10 @@ static void l2tp_tunnel_destruct(struct sock *sk) + } + + /* Remove hooks into tunnel socket */ ++ write_lock_bh(&sk->sk_callback_lock); + sk->sk_destruct = tunnel->old_sk_destruct; + sk->sk_user_data = NULL; ++ write_unlock_bh(&sk->sk_callback_lock); + + /* Call the original destructor */ + if (sk->sk_destruct) +@@ -1471,16 +1473,18 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net, + sock = sockfd_lookup(tunnel->fd, &ret); + if (!sock) + goto err; +- +- ret = l2tp_validate_socket(sock->sk, net, tunnel->encap); +- if (ret < 0) +- goto err_sock; + } + ++ sk = sock->sk; ++ write_lock(&sk->sk_callback_lock); ++ ++ ret = l2tp_validate_socket(sk, net, tunnel->encap); ++ if (ret < 0) ++ goto err_sock; ++ + tunnel->l2tp_net = net; + pn = l2tp_pernet(net); + +- sk = sock->sk; + sock_hold(sk); + tunnel->sock = sk; + +@@ -1506,7 +1510,7 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net, + + setup_udp_tunnel_sock(net, sock, &udp_cfg); + } else { +- sk->sk_user_data = tunnel; ++ rcu_assign_sk_user_data(sk, tunnel); + } + + tunnel->old_sk_destruct = sk->sk_destruct; +@@ -1520,6 +1524,7 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net, + if (tunnel->fd >= 0) + sockfd_put(sock); + ++ write_unlock(&sk->sk_callback_lock); + return 0; + + err_sock: +@@ -1527,6 +1532,8 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net, + sock_release(sock); + else + sockfd_put(sock); ++ ++ write_unlock(&sk->sk_callback_lock); + err: + return ret; + } +-- +2.35.1 + diff --git a/queue-5.10/net-fix-a-concurrency-bug-in-l2tp_tunnel_register.patch b/queue-5.10/net-fix-a-concurrency-bug-in-l2tp_tunnel_register.patch new file mode 100644 index 00000000000..15c8b4337fb --- /dev/null +++ b/queue-5.10/net-fix-a-concurrency-bug-in-l2tp_tunnel_register.patch @@ -0,0 +1,76 @@ +From 81910e59f8971e9939e76923de503aef9e126c27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Apr 2021 15:04:24 +0000 +Subject: net: fix a concurrency bug in l2tp_tunnel_register() + +From: Gong, Sishuai + +[ Upstream commit 69e16d01d1de4f1249869de342915f608feb55d5 ] + +l2tp_tunnel_register() registers a tunnel without fully +initializing its attribute. This can allow another kernel thread +running l2tp_xmit_core() to access the uninitialized data and +then cause a kernel NULL pointer dereference error, as shown below. + +Thread 1 Thread 2 +//l2tp_tunnel_register() +list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list); + //pppol2tp_connect() + tunnel = l2tp_tunnel_get(sock_net(sk), info.tunnel_id); + // Fetch the new tunnel + ... + //l2tp_xmit_core() + struct sock *sk = tunnel->sock; + ... + bh_lock_sock(sk); + //Null pointer error happens +tunnel->sock = sk; + +Fix this bug by initializing tunnel->sock before adding the +tunnel into l2tp_tunnel_list. + +Reviewed-by: Cong Wang +Signed-off-by: Sishuai Gong +Reported-by: Sishuai Gong +Signed-off-by: David S. Miller +Stable-dep-of: b68777d54fac ("l2tp: Serialize access to sk_user_data with sk_callback_lock") +Signed-off-by: Sasha Levin +--- + net/l2tp/l2tp_core.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c +index 561b6d67ab8b..dc8987ed08ad 100644 +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -1480,11 +1480,15 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net, + tunnel->l2tp_net = net; + pn = l2tp_pernet(net); + ++ sk = sock->sk; ++ sock_hold(sk); ++ tunnel->sock = sk; ++ + spin_lock_bh(&pn->l2tp_tunnel_list_lock); + list_for_each_entry(tunnel_walk, &pn->l2tp_tunnel_list, list) { + if (tunnel_walk->tunnel_id == tunnel->tunnel_id) { + spin_unlock_bh(&pn->l2tp_tunnel_list_lock); +- ++ sock_put(sk); + ret = -EEXIST; + goto err_sock; + } +@@ -1492,10 +1496,6 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net, + list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list); + spin_unlock_bh(&pn->l2tp_tunnel_list_lock); + +- sk = sock->sk; +- sock_hold(sk); +- tunnel->sock = sk; +- + if (tunnel->encap == L2TP_ENCAPTYPE_UDP) { + struct udp_tunnel_sock_cfg udp_cfg = { + .sk_user_data = tunnel, +-- +2.35.1 + diff --git a/queue-5.10/net-use-struct_group-to-copy-ip-ipv6-header-addresse.patch b/queue-5.10/net-use-struct_group-to-copy-ip-ipv6-header-addresse.patch new file mode 100644 index 00000000000..6a17f00f585 --- /dev/null +++ b/queue-5.10/net-use-struct_group-to-copy-ip-ipv6-header-addresse.patch @@ -0,0 +1,111 @@ +From 8b2733594317cb6a52021f0942d878cc020d4234 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 22:24:00 +0800 +Subject: net: use struct_group to copy ip/ipv6 header addresses +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Hangbin Liu + +[ Upstream commit 58e0be1ef6118c5352b56a4d06e974c5599993a5 ] + +kernel test robot reported warnings when build bonding module with +make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/net/bonding/: + + from ../drivers/net/bonding/bond_main.c:35: +In function ‘fortify_memcpy_chk’, + inlined from ‘iph_to_flow_copy_v4addrs’ at ../include/net/ip.h:566:2, + inlined from ‘bond_flow_ip’ at ../drivers/net/bonding/bond_main.c:3984:3: +../include/linux/fortify-string.h:413:25: warning: call to ‘__read_overflow2_field’ declared with attribute warning: detected read beyond size of f +ield (2nd parameter); maybe use struct_group()? [-Wattribute-warning] + 413 | __read_overflow2_field(q_size_field, size); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In function ‘fortify_memcpy_chk’, + inlined from ‘iph_to_flow_copy_v6addrs’ at ../include/net/ipv6.h:900:2, + inlined from ‘bond_flow_ip’ at ../drivers/net/bonding/bond_main.c:3994:3: +../include/linux/fortify-string.h:413:25: warning: call to ‘__read_overflow2_field’ declared with attribute warning: detected read beyond size of f +ield (2nd parameter); maybe use struct_group()? [-Wattribute-warning] + 413 | __read_overflow2_field(q_size_field, size); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is because we try to copy the whole ip/ip6 address to the flow_key, +while we only point the to ip/ip6 saddr. Note that since these are UAPI +headers, __struct_group() is used to avoid the compiler warnings. + +Reported-by: kernel test robot +Fixes: c3f8324188fa ("net: Add full IPv6 addresses to flow_keys") +Signed-off-by: Hangbin Liu +Link: https://lore.kernel.org/r/20221115142400.1204786-1-liuhangbin@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + include/net/ip.h | 2 +- + include/net/ipv6.h | 2 +- + include/uapi/linux/ip.h | 6 ++++-- + include/uapi/linux/ipv6.h | 6 ++++-- + 4 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/include/net/ip.h b/include/net/ip.h +index c5822d7824cd..4b775af57268 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -545,7 +545,7 @@ static inline void iph_to_flow_copy_v4addrs(struct flow_keys *flow, + BUILD_BUG_ON(offsetof(typeof(flow->addrs), v4addrs.dst) != + offsetof(typeof(flow->addrs), v4addrs.src) + + sizeof(flow->addrs.v4addrs.src)); +- memcpy(&flow->addrs.v4addrs, &iph->saddr, sizeof(flow->addrs.v4addrs)); ++ memcpy(&flow->addrs.v4addrs, &iph->addrs, sizeof(flow->addrs.v4addrs)); + flow->control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; + } + +diff --git a/include/net/ipv6.h b/include/net/ipv6.h +index 60601896d474..89ce8a50f236 100644 +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -842,7 +842,7 @@ static inline void iph_to_flow_copy_v6addrs(struct flow_keys *flow, + BUILD_BUG_ON(offsetof(typeof(flow->addrs), v6addrs.dst) != + offsetof(typeof(flow->addrs), v6addrs.src) + + sizeof(flow->addrs.v6addrs.src)); +- memcpy(&flow->addrs.v6addrs, &iph->saddr, sizeof(flow->addrs.v6addrs)); ++ memcpy(&flow->addrs.v6addrs, &iph->addrs, sizeof(flow->addrs.v6addrs)); + flow->control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS; + } + +diff --git a/include/uapi/linux/ip.h b/include/uapi/linux/ip.h +index e42d13b55cf3..d2f143393780 100644 +--- a/include/uapi/linux/ip.h ++++ b/include/uapi/linux/ip.h +@@ -100,8 +100,10 @@ struct iphdr { + __u8 ttl; + __u8 protocol; + __sum16 check; +- __be32 saddr; +- __be32 daddr; ++ __struct_group(/* no tag */, addrs, /* no attrs */, ++ __be32 saddr; ++ __be32 daddr; ++ ); + /*The options start here. */ + }; + +diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h +index 13e8751bf24a..766ab5c8ee65 100644 +--- a/include/uapi/linux/ipv6.h ++++ b/include/uapi/linux/ipv6.h +@@ -130,8 +130,10 @@ struct ipv6hdr { + __u8 nexthdr; + __u8 hop_limit; + +- struct in6_addr saddr; +- struct in6_addr daddr; ++ __struct_group(/* no tag */, addrs, /* no attrs */, ++ struct in6_addr saddr; ++ struct in6_addr daddr; ++ ); + }; + + +-- +2.35.1 + diff --git a/queue-5.10/ring-buffer-include-dropped-pages-in-counting-dirty-.patch b/queue-5.10/ring-buffer-include-dropped-pages-in-counting-dirty-.patch new file mode 100644 index 00000000000..2d903cbd0c9 --- /dev/null +++ b/queue-5.10/ring-buffer-include-dropped-pages-in-counting-dirty-.patch @@ -0,0 +1,95 @@ +From e11b9bdd91df8b0fe3d85beab0bcb8df22d92252 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Oct 2022 12:30:13 -0400 +Subject: ring-buffer: Include dropped pages in counting dirty patches + +From: Steven Rostedt (Google) + +[ Upstream commit 31029a8b2c7e656a0289194ef16415050ae4c4ac ] + +The function ring_buffer_nr_dirty_pages() was created to find out how many +pages are filled in the ring buffer. There's two running counters. One is +incremented whenever a new page is touched (pages_touched) and the other +is whenever a page is read (pages_read). The dirty count is the number +touched minus the number read. This is used to determine if a blocked task +should be woken up if the percentage of the ring buffer it is waiting for +is hit. + +The problem is that it does not take into account dropped pages (when the +new writes overwrite pages that were not read). And then the dirty pages +will always be greater than the percentage. + +This makes the "buffer_percent" file inaccurate, as the number of dirty +pages end up always being larger than the percentage, event when it's not +and this causes user space to be woken up more than it wants to be. + +Add a new counter to keep track of lost pages, and include that in the +accounting of dirty pages so that it is actually accurate. + +Link: https://lkml.kernel.org/r/20221021123013.55fb6055@gandalf.local.home + +Fixes: 2c2b0a78b3739 ("ring-buffer: Add percentage of ring buffer full to wake up reader") +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/ring_buffer.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index 9a1f82cafad4..49ebb8c66268 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -517,6 +517,7 @@ struct ring_buffer_per_cpu { + local_t committing; + local_t commits; + local_t pages_touched; ++ local_t pages_lost; + local_t pages_read; + long last_pages_touch; + size_t shortest_full; +@@ -771,10 +772,18 @@ size_t ring_buffer_nr_pages(struct trace_buffer *buffer, int cpu) + size_t ring_buffer_nr_dirty_pages(struct trace_buffer *buffer, int cpu) + { + size_t read; ++ size_t lost; + size_t cnt; + + read = local_read(&buffer->buffers[cpu]->pages_read); ++ lost = local_read(&buffer->buffers[cpu]->pages_lost); + cnt = local_read(&buffer->buffers[cpu]->pages_touched); ++ ++ if (WARN_ON_ONCE(cnt < lost)) ++ return 0; ++ ++ cnt -= lost; ++ + /* The reader can read an empty page, but not more than that */ + if (cnt < read) { + WARN_ON_ONCE(read > cnt + 1); +@@ -1897,6 +1906,7 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned long nr_pages) + */ + local_add(page_entries, &cpu_buffer->overrun); + local_sub(BUF_PAGE_SIZE, &cpu_buffer->entries_bytes); ++ local_inc(&cpu_buffer->pages_lost); + } + + /* +@@ -2387,6 +2397,7 @@ rb_handle_head_page(struct ring_buffer_per_cpu *cpu_buffer, + */ + local_add(entries, &cpu_buffer->overrun); + local_sub(BUF_PAGE_SIZE, &cpu_buffer->entries_bytes); ++ local_inc(&cpu_buffer->pages_lost); + + /* + * The entries will be zeroed out when we move the +@@ -4981,6 +4992,7 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) + local_set(&cpu_buffer->committing, 0); + local_set(&cpu_buffer->commits, 0); + local_set(&cpu_buffer->pages_touched, 0); ++ local_set(&cpu_buffer->pages_lost, 0); + local_set(&cpu_buffer->pages_read, 0); + cpu_buffer->last_pages_touch = 0; + cpu_buffer->shortest_full = 0; +-- +2.35.1 + diff --git a/queue-5.10/scsi-scsi_debug-fix-possible-uaf-in-sdebug_add_host_.patch b/queue-5.10/scsi-scsi_debug-fix-possible-uaf-in-sdebug_add_host_.patch new file mode 100644 index 00000000000..e763cb99fdd --- /dev/null +++ b/queue-5.10/scsi-scsi_debug-fix-possible-uaf-in-sdebug_add_host_.patch @@ -0,0 +1,44 @@ +From c90d2940b92e49636babe1f48200bf6096c21de3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 08:44:21 +0000 +Subject: scsi: scsi_debug: Fix possible UAF in sdebug_add_host_helper() + +From: Yuan Can + +[ Upstream commit e208a1d795a08d1ac0398c79ad9c58106531bcc5 ] + +If device_register() fails in sdebug_add_host_helper(), it will goto clean +and sdbg_host will be freed, but sdbg_host->host_list will not be removed +from sdebug_host_list, then list traversal may cause UAF. Fix it. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Yuan Can +Link: https://lore.kernel.org/r/20221117084421.58918-1-yuancan@huawei.com +Acked-by: Douglas Gilbert +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/scsi_debug.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c +index 5eb959b5f701..261b915835b4 100644 +--- a/drivers/scsi/scsi_debug.c ++++ b/drivers/scsi/scsi_debug.c +@@ -7079,8 +7079,12 @@ static int sdebug_add_host_helper(int per_host_idx) + dev_set_name(&sdbg_host->dev, "adapter%d", sdebug_num_hosts); + + error = device_register(&sdbg_host->dev); +- if (error) ++ if (error) { ++ spin_lock(&sdebug_host_list_lock); ++ list_del(&sdbg_host->host_list); ++ spin_unlock(&sdebug_host_list_lock); + goto clean; ++ } + + ++sdebug_num_hosts; + return 0; +-- +2.35.1 + diff --git a/queue-5.10/scsi-target-tcm_loop-fix-possible-name-leak-in-tcm_l.patch b/queue-5.10/scsi-target-tcm_loop-fix-possible-name-leak-in-tcm_l.patch new file mode 100644 index 00000000000..5f539badb8c --- /dev/null +++ b/queue-5.10/scsi-target-tcm_loop-fix-possible-name-leak-in-tcm_l.patch @@ -0,0 +1,51 @@ +From 9bf9344de09326c564568057ac8ec4b2c371346c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 09:50:42 +0800 +Subject: scsi: target: tcm_loop: Fix possible name leak in + tcm_loop_setup_hba_bus() + +From: Yang Yingliang + +[ Upstream commit bc68e428d4963af0201e92159629ab96948f0893 ] + +If device_register() fails in tcm_loop_setup_hba_bus(), the name allocated +by dev_set_name() need be freed. As comment of device_register() says, it +should use put_device() to give up the reference in the error path. So fix +this by calling put_device(), then the name can be freed in kobject_cleanup(). +The 'tl_hba' will be freed in tcm_loop_release_adapter(), so it don't need +goto error label in this case. + +Fixes: 3703b2c5d041 ("[SCSI] tcm_loop: Add multi-fabric Linux/SCSI LLD fabric module") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221115015042.3652261-1-yangyingliang@huawei.com +Reviewed-by: Mike Christie +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/target/loopback/tcm_loop.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c +index 16d5a4e117a2..5ae5d94c5b93 100644 +--- a/drivers/target/loopback/tcm_loop.c ++++ b/drivers/target/loopback/tcm_loop.c +@@ -394,6 +394,7 @@ static int tcm_loop_setup_hba_bus(struct tcm_loop_hba *tl_hba, int tcm_loop_host + ret = device_register(&tl_hba->dev); + if (ret) { + pr_err("device_register() failed for tl_hba->dev: %d\n", ret); ++ put_device(&tl_hba->dev); + return -ENODEV; + } + +@@ -1072,7 +1073,7 @@ static struct se_wwn *tcm_loop_make_scsi_hba( + */ + ret = tcm_loop_setup_hba_bus(tl_hba, tcm_loop_hba_no_cnt); + if (ret) +- goto out; ++ return ERR_PTR(ret); + + sh = tl_hba->sh; + tcm_loop_hba_no_cnt++; +-- +2.35.1 + diff --git a/queue-5.10/series b/queue-5.10/series index d858d2163d1..e909a1dcf68 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -125,3 +125,13 @@ misc-vmw_vmci-fix-an-infoleak-in-vmci_host_do_receive_datagram.patch perf-x86-intel-pt-fix-sampling-using-single-range-output.patch nvme-restrict-management-ioctls-to-admin.patch nvme-ensure-subsystem-reset-is-single-threaded.patch +net-fix-a-concurrency-bug-in-l2tp_tunnel_register.patch +l2tp-serialize-access-to-sk_user_data-with-sk_callba.patch +ring-buffer-include-dropped-pages-in-counting-dirty-.patch +usbnet-smsc95xx-fix-deadlock-on-runtime-resume.patch +stddef-introduce-struct_group-helper-macro.patch +net-use-struct_group-to-copy-ip-ipv6-header-addresse.patch +scsi-target-tcm_loop-fix-possible-name-leak-in-tcm_l.patch +scsi-scsi_debug-fix-possible-uaf-in-sdebug_add_host_.patch +kprobes-skip-clearing-aggrprobe-s-post_handler-in-kp.patch +input-i8042-fix-leaking-of-platform-device-on-module.patch diff --git a/queue-5.10/stddef-introduce-struct_group-helper-macro.patch b/queue-5.10/stddef-introduce-struct_group-helper-macro.patch new file mode 100644 index 00000000000..4ca1397e75e --- /dev/null +++ b/queue-5.10/stddef-introduce-struct_group-helper-macro.patch @@ -0,0 +1,262 @@ +From 3ce381dd279808d9bd2fac5f4e57f9ccaa5b665b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 May 2021 20:01:15 -0700 +Subject: stddef: Introduce struct_group() helper macro + +From: Kees Cook + +[ Upstream commit 50d7bd38c3aafc4749e05e8d7fcb616979143602 ] + +Kernel code has a regular need to describe groups of members within a +structure usually when they need to be copied or initialized separately +from the rest of the surrounding structure. The generally accepted design +pattern in C is to use a named sub-struct: + + struct foo { + int one; + struct { + int two; + int three, four; + } thing; + int five; + }; + +This would allow for traditional references and sizing: + + memcpy(&dst.thing, &src.thing, sizeof(dst.thing)); + +However, doing this would mean that referencing struct members enclosed +by such named structs would always require including the sub-struct name +in identifiers: + + do_something(dst.thing.three); + +This has tended to be quite inflexible, especially when such groupings +need to be added to established code which causes huge naming churn. +Three workarounds exist in the kernel for this problem, and each have +other negative properties. + +To avoid the naming churn, there is a design pattern of adding macro +aliases for the named struct: + + #define f_three thing.three + +This ends up polluting the global namespace, and makes it difficult to +search for identifiers. + +Another common work-around in kernel code avoids the pollution by avoiding +the named struct entirely, instead identifying the group's boundaries using +either a pair of empty anonymous structs of a pair of zero-element arrays: + + struct foo { + int one; + struct { } start; + int two; + int three, four; + struct { } finish; + int five; + }; + + struct foo { + int one; + int start[0]; + int two; + int three, four; + int finish[0]; + int five; + }; + +This allows code to avoid needing to use a sub-struct named for member +references within the surrounding structure, but loses the benefits of +being able to actually use such a struct, making it rather fragile. Using +these requires open-coded calculation of sizes and offsets. The efforts +made to avoid common mistakes include lots of comments, or adding various +BUILD_BUG_ON()s. Such code is left with no way for the compiler to reason +about the boundaries (e.g. the "start" object looks like it's 0 bytes +in length), making bounds checking depend on open-coded calculations: + + if (length > offsetof(struct foo, finish) - + offsetof(struct foo, start)) + return -EINVAL; + memcpy(&dst.start, &src.start, offsetof(struct foo, finish) - + offsetof(struct foo, start)); + +However, the vast majority of places in the kernel that operate on +groups of members do so without any identification of the grouping, +relying either on comments or implicit knowledge of the struct contents, +which is even harder for the compiler to reason about, and results in +even more fragile manual sizing, usually depending on member locations +outside of the region (e.g. to copy "two" and "three", use the start of +"four" to find the size): + + BUILD_BUG_ON((offsetof(struct foo, four) < + offsetof(struct foo, two)) || + (offsetof(struct foo, four) < + offsetof(struct foo, three)); + if (length > offsetof(struct foo, four) - + offsetof(struct foo, two)) + return -EINVAL; + memcpy(&dst.two, &src.two, length); + +In order to have a regular programmatic way to describe a struct +region that can be used for references and sizing, can be examined for +bounds checking, avoids forcing the use of intermediate identifiers, +and avoids polluting the global namespace, introduce the struct_group() +macro. This macro wraps the member declarations to create an anonymous +union of an anonymous struct (no intermediate name) and a named struct +(for references and sizing): + + struct foo { + int one; + struct_group(thing, + int two; + int three, four; + ); + int five; + }; + + if (length > sizeof(src.thing)) + return -EINVAL; + memcpy(&dst.thing, &src.thing, length); + do_something(dst.three); + +There are some rare cases where the resulting struct_group() needs +attributes added, so struct_group_attr() is also introduced to allow +for specifying struct attributes (e.g. __align(x) or __packed). +Additionally, there are places where such declarations would like to +have the struct be tagged, so struct_group_tagged() is added. + +Given there is a need for a handful of UAPI uses too, the underlying +__struct_group() macro has been defined in UAPI so it can be used there +too. + +To avoid confusing scripts/kernel-doc, hide the macro from its struct +parsing. + +Co-developed-by: Keith Packard +Signed-off-by: Keith Packard +Acked-by: Gustavo A. R. Silva +Link: https://lore.kernel.org/lkml/20210728023217.GC35706@embeddedor +Enhanced-by: Rasmus Villemoes +Link: https://lore.kernel.org/lkml/41183a98-bdb9-4ad6-7eab-5a7292a6df84@rasmusvillemoes.dk +Enhanced-by: Dan Williams +Link: https://lore.kernel.org/lkml/1d9a2e6df2a9a35b2cdd50a9a68cac5991e7e5f0.camel@intel.com +Enhanced-by: Daniel Vetter +Link: https://lore.kernel.org/lkml/YQKa76A6XuFqgM03@phenom.ffwll.local +Acked-by: Dan Williams +Signed-off-by: Kees Cook +Stable-dep-of: 58e0be1ef611 ("net: use struct_group to copy ip/ipv6 header addresses") +Signed-off-by: Sasha Levin +--- + include/linux/stddef.h | 48 +++++++++++++++++++++++++++++++++++++ + include/uapi/linux/stddef.h | 21 ++++++++++++++++ + scripts/kernel-doc | 7 ++++++ + 3 files changed, 76 insertions(+) + +diff --git a/include/linux/stddef.h b/include/linux/stddef.h +index 998a4ba28eba..938216f8ab7e 100644 +--- a/include/linux/stddef.h ++++ b/include/linux/stddef.h +@@ -36,4 +36,52 @@ enum { + #define offsetofend(TYPE, MEMBER) \ + (offsetof(TYPE, MEMBER) + sizeof_field(TYPE, MEMBER)) + ++/** ++ * struct_group() - Wrap a set of declarations in a mirrored struct ++ * ++ * @NAME: The identifier name of the mirrored sub-struct ++ * @MEMBERS: The member declarations for the mirrored structs ++ * ++ * Used to create an anonymous union of two structs with identical ++ * layout and size: one anonymous and one named. The former can be ++ * used normally without sub-struct naming, and the latter can be ++ * used to reason about the start, end, and size of the group of ++ * struct members. ++ */ ++#define struct_group(NAME, MEMBERS...) \ ++ __struct_group(/* no tag */, NAME, /* no attrs */, MEMBERS) ++ ++/** ++ * struct_group_attr() - Create a struct_group() with trailing attributes ++ * ++ * @NAME: The identifier name of the mirrored sub-struct ++ * @ATTRS: Any struct attributes to apply ++ * @MEMBERS: The member declarations for the mirrored structs ++ * ++ * Used to create an anonymous union of two structs with identical ++ * layout and size: one anonymous and one named. The former can be ++ * used normally without sub-struct naming, and the latter can be ++ * used to reason about the start, end, and size of the group of ++ * struct members. Includes structure attributes argument. ++ */ ++#define struct_group_attr(NAME, ATTRS, MEMBERS...) \ ++ __struct_group(/* no tag */, NAME, ATTRS, MEMBERS) ++ ++/** ++ * struct_group_tagged() - Create a struct_group with a reusable tag ++ * ++ * @TAG: The tag name for the named sub-struct ++ * @NAME: The identifier name of the mirrored sub-struct ++ * @MEMBERS: The member declarations for the mirrored structs ++ * ++ * Used to create an anonymous union of two structs with identical ++ * layout and size: one anonymous and one named. The former can be ++ * used normally without sub-struct naming, and the latter can be ++ * used to reason about the start, end, and size of the group of ++ * struct members. Includes struct tag argument for the named copy, ++ * so the specified layout can be reused later. ++ */ ++#define struct_group_tagged(TAG, NAME, MEMBERS...) \ ++ __struct_group(TAG, NAME, /* no attrs */, MEMBERS) ++ + #endif +diff --git a/include/uapi/linux/stddef.h b/include/uapi/linux/stddef.h +index ee8220f8dcf5..610204f7c275 100644 +--- a/include/uapi/linux/stddef.h ++++ b/include/uapi/linux/stddef.h +@@ -4,3 +4,24 @@ + #ifndef __always_inline + #define __always_inline inline + #endif ++ ++/** ++ * __struct_group() - Create a mirrored named and anonyomous struct ++ * ++ * @TAG: The tag name for the named sub-struct (usually empty) ++ * @NAME: The identifier name of the mirrored sub-struct ++ * @ATTRS: Any struct attributes (usually empty) ++ * @MEMBERS: The member declarations for the mirrored structs ++ * ++ * Used to create an anonymous union of two structs with identical layout ++ * and size: one anonymous and one named. The former's members can be used ++ * normally without sub-struct naming, and the latter can be used to ++ * reason about the start, end, and size of the group of struct members. ++ * The named struct can also be explicitly tagged for layer reuse, as well ++ * as both having struct attributes appended. ++ */ ++#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \ ++ union { \ ++ struct { MEMBERS } ATTRS; \ ++ struct TAG { MEMBERS } ATTRS NAME; \ ++ } +diff --git a/scripts/kernel-doc b/scripts/kernel-doc +index 6325bec3f66f..19af6dd160e6 100755 +--- a/scripts/kernel-doc ++++ b/scripts/kernel-doc +@@ -1215,6 +1215,13 @@ sub dump_struct($$) { + $members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos; + $members =~ s/\s*____cacheline_aligned_in_smp/ /gos; + $members =~ s/\s*____cacheline_aligned/ /gos; ++ # unwrap struct_group(): ++ # - first eat non-declaration parameters and rewrite for final match ++ # - then remove macro, outer parens, and trailing semicolon ++ $members =~ s/\bstruct_group\s*\(([^,]*,)/STRUCT_GROUP(/gos; ++ $members =~ s/\bstruct_group_(attr|tagged)\s*\(([^,]*,){2}/STRUCT_GROUP(/gos; ++ $members =~ s/\b__struct_group\s*\(([^,]*,){3}/STRUCT_GROUP(/gos; ++ $members =~ s/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/$2/gos; + + # replace DECLARE_BITMAP + $members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos; +-- +2.35.1 + diff --git a/queue-5.10/usbnet-smsc95xx-fix-deadlock-on-runtime-resume.patch b/queue-5.10/usbnet-smsc95xx-fix-deadlock-on-runtime-resume.patch new file mode 100644 index 00000000000..059e2957820 --- /dev/null +++ b/queue-5.10/usbnet-smsc95xx-fix-deadlock-on-runtime-resume.patch @@ -0,0 +1,194 @@ +From 42d9e50404659f76a1b583b06c503b676d7531db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Jul 2022 22:47:51 +0200 +Subject: usbnet: smsc95xx: Fix deadlock on runtime resume + +From: Lukas Wunner + +[ Upstream commit 7b960c967f2aa01ab8f45c5a0bd78e754cffdeee ] + +Commit 05b35e7eb9a1 ("smsc95xx: add phylib support") amended +smsc95xx_resume() to call phy_init_hw(). That function waits for the +device to runtime resume even though it is placed in the runtime resume +path, causing a deadlock. + +The problem is that phy_init_hw() calls down to smsc95xx_mdiobus_read(), +which never uses the _nopm variant of usbnet_read_cmd(). + +Commit b4df480f68ae ("usbnet: smsc95xx: add reset_resume function with +reset operation") causes a similar deadlock on resume if the device was +already runtime suspended when entering system sleep: + +That's because the commit introduced smsc95xx_reset_resume(), which +calls down to smsc95xx_reset(), which neglects to use _nopm accessors. + +Fix by auto-detecting whether a device access is performed by the +suspend/resume task_struct and use the _nopm variant if so. This works +because the PM core guarantees that suspend/resume callbacks are run in +task context. + +Stacktrace for posterity: + + INFO: task kworker/2:1:49 blocked for more than 122 seconds. + Workqueue: usb_hub_wq hub_event + schedule + rpm_resume + __pm_runtime_resume + usb_autopm_get_interface + usbnet_read_cmd + __smsc95xx_read_reg + __smsc95xx_phy_wait_not_busy + __smsc95xx_mdio_read + smsc95xx_mdiobus_read + __mdiobus_read + mdiobus_read + smsc_phy_reset + phy_init_hw + smsc95xx_resume + usb_resume_interface + usb_resume_both + usb_runtime_resume + __rpm_callback + rpm_callback + rpm_resume + __pm_runtime_resume + usb_autoresume_device + hub_event + process_one_work + +Fixes: b4df480f68ae ("usbnet: smsc95xx: add reset_resume function with reset operation") +Signed-off-by: Lukas Wunner +Cc: stable@vger.kernel.org # v3.16+ +Cc: Andre Edich +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/usb/smsc95xx.c | 27 +++++++++++++++++++++------ + 1 file changed, 21 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c +index 65d42f5d42a3..e1cd4c2de2d3 100644 +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -61,6 +61,7 @@ struct smsc95xx_priv { + u8 suspend_flags; + struct mii_bus *mdiobus; + struct phy_device *phydev; ++ struct task_struct *pm_task; + }; + + static bool turbo_mode = true; +@@ -70,13 +71,14 @@ MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); + static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, + u32 *data, int in_pm) + { ++ struct smsc95xx_priv *pdata = dev->driver_priv; + u32 buf; + int ret; + int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16); + + BUG_ON(!dev); + +- if (!in_pm) ++ if (current != pdata->pm_task) + fn = usbnet_read_cmd; + else + fn = usbnet_read_cmd_nopm; +@@ -100,13 +102,14 @@ static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, + static int __must_check __smsc95xx_write_reg(struct usbnet *dev, u32 index, + u32 data, int in_pm) + { ++ struct smsc95xx_priv *pdata = dev->driver_priv; + u32 buf; + int ret; + int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16); + + BUG_ON(!dev); + +- if (!in_pm) ++ if (current != pdata->pm_task) + fn = usbnet_write_cmd; + else + fn = usbnet_write_cmd_nopm; +@@ -1468,9 +1471,12 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message) + u32 val, link_up; + int ret; + ++ pdata->pm_task = current; ++ + ret = usbnet_suspend(intf, message); + if (ret < 0) { + netdev_warn(dev->net, "usbnet_suspend error\n"); ++ pdata->pm_task = NULL; + return ret; + } + +@@ -1717,6 +1723,7 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message) + if (ret && PMSG_IS_AUTO(message)) + usbnet_resume(intf); + ++ pdata->pm_task = NULL; + return ret; + } + +@@ -1737,29 +1744,31 @@ static int smsc95xx_resume(struct usb_interface *intf) + /* do this first to ensure it's cleared even in error case */ + pdata->suspend_flags = 0; + ++ pdata->pm_task = current; ++ + if (suspend_flags & SUSPEND_ALLMODES) { + /* clear wake-up sources */ + ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val); + if (ret < 0) +- return ret; ++ goto done; + + val &= ~(WUCSR_WAKE_EN_ | WUCSR_MPEN_); + + ret = smsc95xx_write_reg_nopm(dev, WUCSR, val); + if (ret < 0) +- return ret; ++ goto done; + + /* clear wake-up status */ + ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val); + if (ret < 0) +- return ret; ++ goto done; + + val &= ~PM_CTL_WOL_EN_; + val |= PM_CTL_WUPS_; + + ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val); + if (ret < 0) +- return ret; ++ goto done; + } + + ret = usbnet_resume(intf); +@@ -1767,15 +1776,21 @@ static int smsc95xx_resume(struct usb_interface *intf) + netdev_warn(dev->net, "usbnet_resume error\n"); + + phy_init_hw(pdata->phydev); ++ ++done: ++ pdata->pm_task = NULL; + return ret; + } + + static int smsc95xx_reset_resume(struct usb_interface *intf) + { + struct usbnet *dev = usb_get_intfdata(intf); ++ struct smsc95xx_priv *pdata = dev->driver_priv; + int ret; + ++ pdata->pm_task = current; + ret = smsc95xx_reset(dev); ++ pdata->pm_task = NULL; + if (ret < 0) + return ret; + +-- +2.35.1 + -- 2.47.3