Commit f8544ec4 authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky

s390/compat,signal: change return values to -EFAULT

Instead of returnin the number of bytes not copied and/or -EFAULT let the
signal handler helper functions always return -EFAULT if a user space
access failed.
This doesn't fix a bug in the current code, but makes is harder to get it
wrong in the future.
Also "smatch" won't complain anymore about the fact that the number of
remaining bytes gets returned instead of -EFAULT.
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent f5be85a2
...@@ -166,11 +166,14 @@ static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs) ...@@ -166,11 +166,14 @@ static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
memcpy(regs32.acrs, current->thread.acrs, sizeof(regs32.acrs)); memcpy(regs32.acrs, current->thread.acrs, sizeof(regs32.acrs));
err = __copy_to_user(&sregs->regs, &regs32, sizeof(regs32)); err = __copy_to_user(&sregs->regs, &regs32, sizeof(regs32));
if (err) if (err)
return err; return -EFAULT;
save_fp_regs(&current->thread.fp_regs); save_fp_regs(&current->thread.fp_regs);
/* s390_fp_regs and _s390_fp_regs32 are the same ! */ /* s390_fp_regs and _s390_fp_regs32 are the same ! */
return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs, err = __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
sizeof(_s390_fp_regs32)); sizeof(_s390_fp_regs32));
if (err)
return -EFAULT;
return 0;
} }
static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
...@@ -183,7 +186,7 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) ...@@ -183,7 +186,7 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32)); err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
if (err) if (err)
return err; return -EFAULT;
regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
(__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 | (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
(__u64)(regs32.psw.addr & PSW32_ADDR_AMODE); (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
...@@ -201,7 +204,7 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) ...@@ -201,7 +204,7 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
sizeof(_s390_fp_regs32)); sizeof(_s390_fp_regs32));
current->thread.fp_regs.fpc &= FPC_VALID_MASK; current->thread.fp_regs.fpc &= FPC_VALID_MASK;
if (err) if (err)
return err; return -EFAULT;
restore_fp_regs(&current->thread.fp_regs); restore_fp_regs(&current->thread.fp_regs);
clear_thread_flag(TIF_SYSCALL); /* No longer in a system call */ clear_thread_flag(TIF_SYSCALL); /* No longer in a system call */
...@@ -215,18 +218,18 @@ static int save_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs) ...@@ -215,18 +218,18 @@ static int save_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
for (i = 0; i < NUM_GPRS; i++) for (i = 0; i < NUM_GPRS; i++)
gprs_high[i] = regs->gprs[i] >> 32; gprs_high[i] = regs->gprs[i] >> 32;
if (__copy_to_user(uregs, &gprs_high, sizeof(gprs_high)))
return __copy_to_user(uregs, &gprs_high, sizeof(gprs_high)); return -EFAULT;
return 0;
} }
static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs) static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
{ {
__u32 gprs_high[NUM_GPRS]; __u32 gprs_high[NUM_GPRS];
int err, i; int i;
err = __copy_from_user(&gprs_high, uregs, sizeof(gprs_high)); if (__copy_from_user(&gprs_high, uregs, sizeof(gprs_high)))
if (err) return -EFAULT;
return err;
for (i = 0; i < NUM_GPRS; i++) for (i = 0; i < NUM_GPRS; i++)
*(__u32 *)&regs->gprs[i] = gprs_high[i]; *(__u32 *)&regs->gprs[i] = gprs_high[i];
return 0; return 0;
......
...@@ -70,21 +70,20 @@ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs) ...@@ -70,21 +70,20 @@ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
save_fp_regs(&current->thread.fp_regs); save_fp_regs(&current->thread.fp_regs);
memcpy(&user_sregs.fpregs, &current->thread.fp_regs, memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
sizeof(s390_fp_regs)); sizeof(s390_fp_regs));
return __copy_to_user(sregs, &user_sregs, sizeof(_sigregs)); if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs)))
return -EFAULT;
return 0;
} }
/* Returns positive number on error */
static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
{ {
int err;
_sigregs user_sregs; _sigregs user_sregs;
/* Alwys make any pending restarted system call return -EINTR */ /* Alwys make any pending restarted system call return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall; current_thread_info()->restart_block.fn = do_no_restart_syscall;
err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs)); if (__copy_from_user(&user_sregs, sregs, sizeof(_sigregs)))
if (err) return -EFAULT;
return err;
/* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */ /* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
(user_sregs.regs.psw.mask & PSW_MASK_USER); (user_sregs.regs.psw.mask & PSW_MASK_USER);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment