kernel/debug: Fix handling of sInvokeCommandLevel.
* Check for overflows in invoke_debugger_command.
* Reset it inside invoke_debugger_command always.
It wasn't reset in the case of INVOKE_COMMAND_FAULT, meaning
we would "leak" command levels, thus leading to crashes
and other problems inside the kernel debugger.
Fixes recursive KDLs or even triple faults caused by faulting
commands and pipes inside the kernel debugger.
Diff
src/system/kernel/debug/debug_commands.cpp | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
@@ -304,19 +304,25 @@
if (gInvokeCommandDirectly)
return command->func(argc, argv);
sInCommand = true;
if (sInvokeCommandLevel >= kMaxInvokeCommandDepth) {
kprintf_unfiltered("\n[*** MAX COMMAND DEPTH HIT ***]\n");
return B_KDEBUG_ERROR;
}
invoke_command_parameters parameters;
parameters.command = command;
parameters.argc = argc;
parameters.argv = argv;
sInCommand = true;
int result = debug_call_with_fault_handler(
sInvokeCommandEnv[sInvokeCommandLevel++],
&invoke_command_trampoline, ¶meters);
sInvokeCommandLevel--;
sInCommand = false;
switch (debug_call_with_fault_handler(
sInvokeCommandEnv[sInvokeCommandLevel++],
&invoke_command_trampoline, ¶meters)) {
switch (result) {
case 0:
sInvokeCommandLevel--;
sInCommand = false;
return parameters.result;
case INVOKE_COMMAND_FAULT:
@@ -338,7 +344,6 @@
break;
}
sInCommand = false;
return B_KDEBUG_ERROR;
}
@@ -351,7 +356,7 @@
abort_debugger_command()
{
if (!gInvokeCommandDirectly && sInvokeCommandLevel > 0) {
longjmp(sInvokeCommandEnv[--sInvokeCommandLevel],
longjmp(sInvokeCommandEnv[sInvokeCommandLevel - 1],
INVOKE_COMMAND_ERROR);
}
}