Skip to contentSkip to conversation

arm64: only advance singlestep for user instruction traps

PATCH New Mark Rutland 2 participants 3 messages Apr 3, 2018 – Apr 5, 2018 arm64

lore
Share & tools
lore

Mark Rutland

author reviewer
#0 lore raw

PATCH 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.

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
index ba964da31a25..75625a401a4e 100644
@@ -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
#1 lore raw

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
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
index ba964da31a25..75625a401a4e 100644
@@ -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
author reviewer
#2 lore raw

PATCH 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_SINGLESTEP set 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
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
index ba964da31a25..75625a401a4e 100644
@@ -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