The debug monitor's cleanup code calls xTaskResumeAll to re-enable the FreeRTOS scheduler and effectively unpause the system. However, this will usually yield immediately, switching to a different task by saving limited thread-local state including r0-r12, lr, and a few other registers (but notably not SP_abt and SPSR_abt). If another task then clobbers these registers (e.g. by entering the debug monitor itself), the remaining debug monitor cleanup code in the original task will use the wrong SP_abt and SPSR_abt values.
Impact
This could lead to one task "stealing" data from another's stack, e.g. in this situation:
- Task A hits a breakpoint, is debugged, and then exits the debug monitor. The abort mode stack and SPSR hold Task A's information.
- v5gdb's debug monitor teardown code unpauses the FreeRTOS scheduler, causing an immediate yield and switch to Task B.
- Task B hits a breakpoint, is debugged, and then exits the debug monitor. The abort mode stack and SPSR are overwritten to hold Task B's information.
- v5gdb's debug monitor teardown code unpauses the FreeRTOS scheduler, and we switch back to Task A which is still cleaning up from being in the debug monitor.
- Task A's cleanup code pops Task B's registers from the abort mode stack, then resumes execution in Task A's main code.
Thus we end up with Task A having a copy of Task B's registers. Additionally, if Task B later runs, it will probably pop too much from the stack and have garbage values in its registers.
Suggested fix
Find a way to resume the scheduler only after returning to the task's own environment, when the abort mode registers are now irrelevant.
The debug monitor's cleanup code calls
xTaskResumeAllto re-enable the FreeRTOS scheduler and effectively unpause the system. However, this will usually yield immediately, switching to a different task by saving limited thread-local state including r0-r12, lr, and a few other registers (but notably not SP_abt and SPSR_abt). If another task then clobbers these registers (e.g. by entering the debug monitor itself), the remaining debug monitor cleanup code in the original task will use the wrong SP_abt and SPSR_abt values.Impact
This could lead to one task "stealing" data from another's stack, e.g. in this situation:
Thus we end up with Task A having a copy of Task B's registers. Additionally, if Task B later runs, it will probably pop too much from the stack and have garbage values in its registers.
Suggested fix
Find a way to resume the scheduler only after returning to the task's own environment, when the abort mode registers are now irrelevant.