diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2015-10-27 08:13:38 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2015-11-03 08:40:42 -0500 |
commit | 55a423b6f105fa323168f15f4bb67f23b21da44e (patch) | |
tree | 518b2d2983596039f5ab0ba4d1d069aa8b7cc0b8 | |
parent | ef12cb904e096335ef179bfe30e637a9c2464343 (diff) |
s390/kernel: fix ptrace peek/poke for floating point registers
git commit 155e839a814834a3b4b31e729f4716e59d3d2dd4
"s390/kernel: dynamically allocate FP register save area"
introduced a regression in regard to ptrace.
If the vector register extension is not present or unused the
ptrace peek of a floating pointer register return incorrect data
and the ptrace poke to a floating pointer register overwrites the
task structure starting at task->thread.fpu.fprs.
Cc: stable@kernel.org # v4.3
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | arch/s390/kernel/ptrace.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 3ccd9008a4dc..01c37b36caf9 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
@@ -244,7 +244,7 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr) | |||
244 | ((addr_t) child->thread.fpu.vxrs + 2*offset); | 244 | ((addr_t) child->thread.fpu.vxrs + 2*offset); |
245 | else | 245 | else |
246 | tmp = *(addr_t *) | 246 | tmp = *(addr_t *) |
247 | ((addr_t) &child->thread.fpu.fprs + offset); | 247 | ((addr_t) child->thread.fpu.fprs + offset); |
248 | 248 | ||
249 | } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { | 249 | } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { |
250 | /* | 250 | /* |
@@ -388,7 +388,7 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data) | |||
388 | child->thread.fpu.vxrs + 2*offset) = data; | 388 | child->thread.fpu.vxrs + 2*offset) = data; |
389 | else | 389 | else |
390 | *(addr_t *)((addr_t) | 390 | *(addr_t *)((addr_t) |
391 | &child->thread.fpu.fprs + offset) = data; | 391 | child->thread.fpu.fprs + offset) = data; |
392 | 392 | ||
393 | } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { | 393 | } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { |
394 | /* | 394 | /* |
@@ -622,7 +622,7 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr) | |||
622 | ((addr_t) child->thread.fpu.vxrs + 2*offset); | 622 | ((addr_t) child->thread.fpu.vxrs + 2*offset); |
623 | else | 623 | else |
624 | tmp = *(__u32 *) | 624 | tmp = *(__u32 *) |
625 | ((addr_t) &child->thread.fpu.fprs + offset); | 625 | ((addr_t) child->thread.fpu.fprs + offset); |
626 | 626 | ||
627 | } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { | 627 | } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { |
628 | /* | 628 | /* |
@@ -747,7 +747,7 @@ static int __poke_user_compat(struct task_struct *child, | |||
747 | child->thread.fpu.vxrs + 2*offset) = tmp; | 747 | child->thread.fpu.vxrs + 2*offset) = tmp; |
748 | else | 748 | else |
749 | *(__u32 *)((addr_t) | 749 | *(__u32 *)((addr_t) |
750 | &child->thread.fpu.fprs + offset) = tmp; | 750 | child->thread.fpu.fprs + offset) = tmp; |
751 | 751 | ||
752 | } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { | 752 | } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { |
753 | /* | 753 | /* |