[PATCH] kgdb: Resolve races during kgdb_io_register/unregister_module

From: Daniel Thompson
Date: Mon Jun 29 2020 - 15:43:34 EST


Currently kgdb_register_callbacks() and kgdb_unregister_callbacks()
are called outside the scope of the kgdb_registration_lock. This
allows them to race with each other. This could do all sorts of crazy
things up to and including dbg_io_ops becoming NULL partway through the
execution of the kgdb trap handler (which isn't allowed and would be
fatal).

Fix this by bringing the trap handler setup and teardown into the scope
of the registration lock.

Signed-off-by: Daniel Thompson <daniel.thompson@xxxxxxxxxx>
---
kernel/debug/debug_core.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index 9e5934780f41..9799f2c6dc94 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -1117,9 +1117,8 @@ int kgdb_register_io_module(struct kgdb_io *new_dbg_io_ops)

dbg_io_ops = new_dbg_io_ops;

- spin_unlock(&kgdb_registration_lock);
-
if (old_dbg_io_ops) {
+ spin_unlock(&kgdb_registration_lock);
old_dbg_io_ops->deinit();
return 0;
}
@@ -1129,6 +1128,8 @@ int kgdb_register_io_module(struct kgdb_io *new_dbg_io_ops)
/* Arm KGDB now. */
kgdb_register_callbacks();

+ spin_unlock(&kgdb_registration_lock);
+
if (kgdb_break_asap &&
(!dbg_is_early || IS_ENABLED(CONFIG_ARCH_HAS_EARLY_DEBUG)))
kgdb_initial_breakpoint();
@@ -1147,13 +1148,14 @@ void kgdb_unregister_io_module(struct kgdb_io *old_dbg_io_ops)
{
BUG_ON(kgdb_connected);

+ spin_lock(&kgdb_registration_lock);
+
/*
* KGDB is no longer able to communicate out, so
* unregister our callbacks and reset state.
*/
kgdb_unregister_callbacks();

- spin_lock(&kgdb_registration_lock);

WARN_ON_ONCE(dbg_io_ops != old_dbg_io_ops);
dbg_io_ops = NULL;

base-commit: 9ebcfadb0610322ac537dd7aa5d9cbc2b2894c68
--
2.25.4