aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/signal.c')
-rw-r--r--arch/s390/kernel/signal.c49
1 files changed, 28 insertions, 21 deletions
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index c45becf82e01..fb535874a246 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -57,40 +57,48 @@ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
57 57
58 /* Copy a 'clean' PSW mask to the user to avoid leaking 58 /* Copy a 'clean' PSW mask to the user to avoid leaking
59 information about whether PER is currently on. */ 59 information about whether PER is currently on. */
60 user_sregs.regs.psw.mask = psw_user_bits | 60 user_sregs.regs.psw.mask = PSW_USER_BITS |
61 (regs->psw.mask & PSW_MASK_USER); 61 (regs->psw.mask & (PSW_MASK_USER | PSW_MASK_RI));
62 user_sregs.regs.psw.addr = regs->psw.addr; 62 user_sregs.regs.psw.addr = regs->psw.addr;
63 memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs)); 63 memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs));
64 memcpy(&user_sregs.regs.acrs, current->thread.acrs, 64 memcpy(&user_sregs.regs.acrs, current->thread.acrs,
65 sizeof(sregs->regs.acrs)); 65 sizeof(user_sregs.regs.acrs));
66 /* 66 /*
67 * We have to store the fp registers to current->thread.fp_regs 67 * We have to store the fp registers to current->thread.fp_regs
68 * to merge them with the emulated registers. 68 * to merge them with the emulated registers.
69 */ 69 */
70 save_fp_regs(&current->thread.fp_regs); 70 save_fp_ctl(&current->thread.fp_regs.fpc);
71 save_fp_regs(current->thread.fp_regs.fprs);
71 memcpy(&user_sregs.fpregs, &current->thread.fp_regs, 72 memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
72 sizeof(s390_fp_regs)); 73 sizeof(user_sregs.fpregs));
73 return __copy_to_user(sregs, &user_sregs, sizeof(_sigregs)); 74 if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs)))
75 return -EFAULT;
76 return 0;
74} 77}
75 78
76/* Returns positive number on error */
77static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) 79static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
78{ 80{
79 int err;
80 _sigregs user_sregs; 81 _sigregs user_sregs;
81 82
82 /* Alwys make any pending restarted system call return -EINTR */ 83 /* Alwys make any pending restarted system call return -EINTR */
83 current_thread_info()->restart_block.fn = do_no_restart_syscall; 84 current_thread_info()->restart_block.fn = do_no_restart_syscall;
84 85
85 err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs)); 86 if (__copy_from_user(&user_sregs, sregs, sizeof(user_sregs)))
86 if (err) 87 return -EFAULT;
87 return err; 88
88 /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */ 89 if (!is_ri_task(current) && (user_sregs.regs.psw.mask & PSW_MASK_RI))
90 return -EINVAL;
91
92 /* Loading the floating-point-control word can fail. Do that first. */
93 if (restore_fp_ctl(&user_sregs.fpregs.fpc))
94 return -EINVAL;
95
96 /* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
89 regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | 97 regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
90 (user_sregs.regs.psw.mask & PSW_MASK_USER); 98 (user_sregs.regs.psw.mask & (PSW_MASK_USER | PSW_MASK_RI));
91 /* Check for invalid user address space control. */ 99 /* Check for invalid user address space control. */
92 if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) 100 if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_HOME)
93 regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | 101 regs->psw.mask = PSW_ASC_PRIMARY |
94 (regs->psw.mask & ~PSW_MASK_ASC); 102 (regs->psw.mask & ~PSW_MASK_ASC);
95 /* Check for invalid amode */ 103 /* Check for invalid amode */
96 if (regs->psw.mask & PSW_MASK_EA) 104 if (regs->psw.mask & PSW_MASK_EA)
@@ -98,14 +106,13 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
98 regs->psw.addr = user_sregs.regs.psw.addr; 106 regs->psw.addr = user_sregs.regs.psw.addr;
99 memcpy(&regs->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs)); 107 memcpy(&regs->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs));
100 memcpy(&current->thread.acrs, &user_sregs.regs.acrs, 108 memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
101 sizeof(sregs->regs.acrs)); 109 sizeof(current->thread.acrs));
102 restore_access_regs(current->thread.acrs); 110 restore_access_regs(current->thread.acrs);
103 111
104 memcpy(&current->thread.fp_regs, &user_sregs.fpregs, 112 memcpy(&current->thread.fp_regs, &user_sregs.fpregs,
105 sizeof(s390_fp_regs)); 113 sizeof(current->thread.fp_regs));
106 current->thread.fp_regs.fpc &= FPC_VALID_MASK;
107 114
108 restore_fp_regs(&current->thread.fp_regs); 115 restore_fp_regs(current->thread.fp_regs.fprs);
109 clear_thread_flag(TIF_SYSCALL); /* No longer in a system call */ 116 clear_thread_flag(TIF_SYSCALL); /* No longer in a system call */
110 return 0; 117 return 0;
111} 118}
@@ -224,7 +231,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
224 regs->gprs[15] = (unsigned long) frame; 231 regs->gprs[15] = (unsigned long) frame;
225 /* Force default amode and default user address space control. */ 232 /* Force default amode and default user address space control. */
226 regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | 233 regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
227 (psw_user_bits & PSW_MASK_ASC) | 234 (PSW_USER_BITS & PSW_MASK_ASC) |
228 (regs->psw.mask & ~PSW_MASK_ASC); 235 (regs->psw.mask & ~PSW_MASK_ASC);
229 regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; 236 regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
230 237
@@ -295,7 +302,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
295 regs->gprs[15] = (unsigned long) frame; 302 regs->gprs[15] = (unsigned long) frame;
296 /* Force default amode and default user address space control. */ 303 /* Force default amode and default user address space control. */
297 regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | 304 regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
298 (psw_user_bits & PSW_MASK_ASC) | 305 (PSW_USER_BITS & PSW_MASK_ASC) |
299 (regs->psw.mask & ~PSW_MASK_ASC); 306 (regs->psw.mask & ~PSW_MASK_ASC);
300 regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; 307 regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
301 308