summaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/ptrace.c
diff options
context:
space:
mode:
authorHeiko Carstens <hca@linux.ibm.com>2023-11-30 18:56:02 +0100
committerAlexander Gordeev <agordeev@linux.ibm.com>2023-12-11 14:33:06 +0100
commit702644249d3e03333f16273a3a3ebedecfb7f2c6 (patch)
tree4c491a98a1018c316688b5a9735fb1549bb6f88d /arch/s390/kernel/ptrace.c
parent3b2e00f167f493ca1de7451310f1ce56f0b27fcb (diff)
downloadlinux-702644249d3e03333f16273a3a3ebedecfb7f2c6.tar.gz
linux-702644249d3e03333f16273a3a3ebedecfb7f2c6.tar.bz2
linux-702644249d3e03333f16273a3a3ebedecfb7f2c6.zip
s390/fpu: get rid of test_fp_ctl()
It is quite subtle to use test_fp_ctl() correctly. Therefore remove it - instead copy whatever new floating point control (fpc) register values are supposed to be used into its save area. Test the validity of the new value when loading it. If the new value is invalid, load the fpc register with zero. This seems to be a the best way to approach this problem. Even though this changes behavior: - sigreturn with an invalid fpc value on the stack will succeed, and continue with zero value, instead of returning with SIGSEGV - ptraced processes will also use a zero value instead of letting the request fail with -EINVAL However all of this seems to acceptable. After all testing of the value was only implemented to avoid that user space can crash the kernel. It is not there to test values for validity; and the assumption is that there is no existing user space which is doing this. Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
Diffstat (limited to 'arch/s390/kernel/ptrace.c')
-rw-r--r--arch/s390/kernel/ptrace.c13
1 files changed, 5 insertions, 8 deletions
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index c7ed302a6b59..df2ee1b88024 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -392,9 +392,7 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
/*
* floating point control reg. is in the thread structure
*/
- save_fpu_regs();
- if ((unsigned int) data != 0 ||
- test_fp_ctl(data >> (BITS_PER_LONG - 32)))
+ if ((unsigned int)data != 0)
return -EINVAL;
child->thread.fpu.fpc = data >> (BITS_PER_LONG - 32);
@@ -749,9 +747,6 @@ static int __poke_user_compat(struct task_struct *child,
/*
* floating point control reg. is in the thread structure
*/
- save_fpu_regs();
- if (test_fp_ctl(tmp))
- return -EINVAL;
child->thread.fpu.fpc = data;
} else if (addr < offsetof(struct compat_user, regs.fp_regs) + sizeof(s390_fp_regs)) {
@@ -913,7 +908,9 @@ static int s390_fpregs_set(struct task_struct *target,
int rc = 0;
freg_t fprs[__NUM_FPRS];
- save_fpu_regs();
+ if (target == current)
+ save_fpu_regs();
+
if (MACHINE_HAS_VX)
convert_vx_to_fp(fprs, target->thread.fpu.vxrs);
else
@@ -926,7 +923,7 @@ static int s390_fpregs_set(struct task_struct *target,
0, offsetof(s390_fp_regs, fprs));
if (rc)
return rc;
- if (ufpc[1] != 0 || test_fp_ctl(ufpc[0]))
+ if (ufpc[1] != 0)
return -EINVAL;
target->thread.fpu.fpc = ufpc[0];
}