aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2021-09-13 15:24:34 +0000
committerAndrew Turner <andrew@FreeBSD.org>2021-09-13 15:32:50 +0000
commitb029ef7fe618c6fa0482958422cc362905c15376 (patch)
tree1b474bd1561069532b878271e12a27817ea90c92
parentddedf2a11eb20af1ee52cb3da70a57c21904af8f (diff)
downloadsrc-b029ef7fe618c6fa0482958422cc362905c15376.tar.gz
src-b029ef7fe618c6fa0482958422cc362905c15376.zip
Restrict spsr updated in the arm64 set_regs*
When using ptrace(2) on arm64 to set registers in a 32-bit program we need to take care to only set some of the fields. Follow the existing arm64 path and only let the user set the flags fields. This is also the case in the arm kernel so fixes a change in behaviour between the two. While here update set_regs to only set spsr and elr once. Sponsored by: The FreeBSD Foundation
-rw-r--r--sys/arm64/arm64/machdep.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c
index ee6f5157f5f3..89c4f21134f8 100644
--- a/sys/arm64/arm64/machdep.c
+++ b/sys/arm64/arm64/machdep.c
@@ -254,9 +254,7 @@ set_regs(struct thread *td, struct reg *regs)
frame = td->td_frame;
frame->tf_sp = regs->sp;
frame->tf_lr = regs->lr;
- frame->tf_elr = regs->elr;
frame->tf_spsr &= ~PSR_FLAGS;
- frame->tf_spsr |= regs->spsr & PSR_FLAGS;
memcpy(frame->tf_x, regs->x, sizeof(frame->tf_x));
@@ -268,9 +266,13 @@ set_regs(struct thread *td, struct reg *regs)
* it put it.
*/
frame->tf_elr = regs->x[15];
- frame->tf_spsr = regs->x[16] & PSR_FLAGS;
- }
+ frame->tf_spsr |= regs->x[16] & PSR_FLAGS;
+ } else
#endif
+ {
+ frame->tf_elr = regs->elr;
+ frame->tf_spsr |= regs->spsr & PSR_FLAGS;
+ }
return (0);
}
@@ -490,7 +492,8 @@ set_regs32(struct thread *td, struct reg32 *regs)
tf->tf_x[13] = regs->r_sp;
tf->tf_x[14] = regs->r_lr;
tf->tf_elr = regs->r_pc;
- tf->tf_spsr = regs->r_cpsr;
+ tf->tf_spsr &= ~PSR_FLAGS;
+ tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS;
return (0);
}