arm64: only advance singlestep for user instruction traps
Mark Rutland
reviewerPATCH 1/1 arm64: only advance singlestep for user instruction traps
Our arm64_skip_faulting_instruction() helper advances the userspace singlestep state machine, but this is also called by the kernel BRK handler, as used for WARN*().
Thus, if we happen to hit a WARN*() while the user singlestep state machine is in the active-no-pending state, we'll advance to the active-pending state without having executed a user instruction, and will take a step exception earlier than expected when we return to userspace.
Let's fix this by only advancing the state machine when skipping a user instruction.
--- arch/arm64/kernel/traps.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm64/kernel/traps.c +2 -1
@@ -277,7 +277,8 @@ void arm64_skip_faulting_instruction(struct pt_regs *regs, unsigned long size)* If we were single stepping, we want to get the step exception after * we return from the trap. */ -user_fastforward_single_step (current); +if (user_mode (regs)) +user_fastforward_single_step (current); }static LIST_HEAD (undef_hook);
Signature · 1 line
2.11.0
PATCH 1/1 arm64: only advance singlestep for user instruction traps
Quoted 4 lines · Mark Rutland
Our
arm64_skip_faulting_instruction()helper advances the userspace singlestep state machine, but this is also called by the kernel BRK handler, as used for WARN*().
Quoted 8 lines
Thus, if we happen to hit a WARN*() while the user singlestep state machine is in the active-no-pending state, we'll advance to the active-pending state without having executed a user instruction, and will take a step exception earlier than expected when we return to userspace.
Let's fix this by only advancing the state machine when skipping a user instruction.
Is it possible to have TIF_SINGLESTEP set even if !user_mode()?
If WARN*() is only an issue, why not fix bug_handler() directly?
-Takahiro AKASHI
Quoted 30 lines
Signed-off-by Mark Rutland <[email protected]>Cc Andrey Konovalov <[email protected]>Cc Catalin Marinas <[email protected]>Cc Will Deacon <[email protected]>--- arch/arm64/kernel/traps.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)arch/arm64/kernel/traps.c +2
-1@@ -277,7 +277,8 @@ void arm64_skip_faulting_instruction(struct pt_regs *regs, unsigned long size)* If we were single stepping, we want to get the step exception after * we return from the trap. */ -user_fastforward_single_step (current); +if (user_mode (regs)) +user_fastforward_single_step (current); }static LIST_HEAD (undef_hook);Signature · 7 lines
2.11.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel at lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Mark Rutland
reviewerPATCH 1/1 arm64: only advance singlestep for user instruction traps
Quoted 11 lines · AKASHI Takahiro
Quoted 10 lines · Mark Rutland
Our
arm64_skip_faulting_instruction()helper advances the userspace singlestep state machine, but this is also called by the kernel BRK handler, as used for WARN*().Thus, if we happen to hit a WARN*() while the user singlestep state machine is in the active-no-pending state, we'll advance to the active-pending state without having executed a user instruction, and will take a step exception earlier than expected when we return to userspace.
Quoted 4 lines
Quoted 2 lines
Let's fix this by only advancing the state machine when skipping a user instruction.
Is it possible to have
TIF_SINGLESTEPset even if !user_mode()?
I believe this can happen if we're single-stepping a user task, then in the process of handling some exception (e.g. an instruction abort) we hit a WARN(). That WARN() will have a BRK, triggering an EL1 BRK64 exception, where !user_mode(regs), but as we're in the context of the user task, TIF_SINGLESTEP can be set.
Quoted 1 line
If WARN*() is only an issue, why not fix
bug_handler()directly?
In bug_handler() we call arm64_skip_faulting_instruction(), so we'd either need to open-code the PC modification there, or have a separate arm64_skip_faulting_{user,kernel}_instruction() helpers.
I'd prototyped the latter, but it was very churny, and this seemed the simlpest option.
Thanks,
Mark.
Quoted 30 lines
Quoted 30 lines
Signed-off-by Mark Rutland <[email protected]>Cc Andrey Konovalov <[email protected]>Cc Catalin Marinas <[email protected]>Cc Will Deacon <[email protected]>--- arch/arm64/kernel/traps.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)arch/arm64/kernel/traps.c +2
-1@@ -277,7 +277,8 @@ void arm64_skip_faulting_instruction(struct pt_regs *regs, unsigned long size)* If we were single stepping, we want to get the step exception after * we return from the trap. */ -user_fastforward_single_step (current); +if (user_mode (regs)) +user_fastforward_single_step (current); }static LIST_HEAD (undef_hook);Signature · 7 lines
2.11.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel at lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel