]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: netconsole: Disable target before netpoll cleanup
authorBreno Leitao <leitao@debian.org>
Fri, 12 Jul 2024 14:34:15 +0000 (07:34 -0700)
committerJakub Kicinski <kuba@kernel.org>
Sun, 14 Jul 2024 14:38:44 +0000 (07:38 -0700)
Currently, netconsole cleans up the netpoll structure before disabling
the target. This approach can lead to race conditions, as message
senders (write_ext_msg() and write_msg()) check if the target is
enabled before using netpoll. The sender can validate that the target is
enabled, but, the netpoll might be de-allocated already, causing
undesired behaviours.

This patch reverses the order of operations:
1. Disable the target
2. Clean up the netpoll structure

This change eliminates the potential race condition, ensuring that
no messages are sent through a partially cleaned-up netpoll structure.

Fixes: 2382b15bcc39 ("netconsole: take care of NETDEV_UNREGISTER event")
Cc: stable@vger.kernel.org
Signed-off-by: Breno Leitao <leitao@debian.org>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20240712143415.1141039-1-leitao@debian.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/netconsole.c

index d7070dd4fe7367cb3aec7aa88a83d6e93e03537a..aa66c923790ffbb8890f678864f425650652d499 100644 (file)
@@ -974,6 +974,7 @@ restart:
                                /* rtnl_lock already held
                                 * we might sleep in __netpoll_cleanup()
                                 */
+                               nt->enabled = false;
                                spin_unlock_irqrestore(&target_list_lock, flags);
 
                                __netpoll_cleanup(&nt->np);
@@ -981,7 +982,6 @@ restart:
                                spin_lock_irqsave(&target_list_lock, flags);
                                netdev_put(nt->np.dev, &nt->np.dev_tracker);
                                nt->np.dev = NULL;
-                               nt->enabled = false;
                                stopped = true;
                                netconsole_target_put(nt);
                                goto restart;