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.c78
1 files changed, 32 insertions, 46 deletions
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 42b49f9e19bf..469c4c6d9182 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -200,15 +200,15 @@ static int setup_frame(int sig, struct k_sigaction *ka,
200 frame = get_sigframe(ka, regs, sizeof(sigframe)); 200 frame = get_sigframe(ka, regs, sizeof(sigframe));
201 201
202 if (frame == (void __user *) -1UL) 202 if (frame == (void __user *) -1UL)
203 goto give_sigsegv; 203 return -EFAULT;
204 204
205 if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE)) 205 if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE))
206 goto give_sigsegv; 206 return -EFAULT;
207 207
208 if (save_sigregs(regs, &frame->sregs)) 208 if (save_sigregs(regs, &frame->sregs))
209 goto give_sigsegv; 209 return -EFAULT;
210 if (__put_user(&frame->sregs, &frame->sc.sregs)) 210 if (__put_user(&frame->sregs, &frame->sc.sregs))
211 goto give_sigsegv; 211 return -EFAULT;
212 212
213 /* Set up to return from userspace. If provided, use a stub 213 /* Set up to return from userspace. If provided, use a stub
214 already in userspace. */ 214 already in userspace. */
@@ -220,12 +220,12 @@ static int setup_frame(int sig, struct k_sigaction *ka,
220 frame->retcode | PSW_ADDR_AMODE; 220 frame->retcode | PSW_ADDR_AMODE;
221 if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, 221 if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
222 (u16 __user *)(frame->retcode))) 222 (u16 __user *)(frame->retcode)))
223 goto give_sigsegv; 223 return -EFAULT;
224 } 224 }
225 225
226 /* Set up backchain. */ 226 /* Set up backchain. */
227 if (__put_user(regs->gprs[15], (addr_t __user *) frame)) 227 if (__put_user(regs->gprs[15], (addr_t __user *) frame))
228 goto give_sigsegv; 228 return -EFAULT;
229 229
230 /* Set up registers for signal handler */ 230 /* Set up registers for signal handler */
231 regs->gprs[15] = (unsigned long) frame; 231 regs->gprs[15] = (unsigned long) frame;
@@ -250,27 +250,23 @@ static int setup_frame(int sig, struct k_sigaction *ka,
250 250
251 /* Place signal number on stack to allow backtrace from handler. */ 251 /* Place signal number on stack to allow backtrace from handler. */
252 if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) 252 if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
253 goto give_sigsegv; 253 return -EFAULT;
254 return 0; 254 return 0;
255
256give_sigsegv:
257 force_sigsegv(sig, current);
258 return -EFAULT;
259} 255}
260 256
261static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 257static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
262 sigset_t *set, struct pt_regs * regs) 258 struct pt_regs *regs)
263{ 259{
264 int err = 0; 260 int err = 0;
265 rt_sigframe __user *frame; 261 rt_sigframe __user *frame;
266 262
267 frame = get_sigframe(ka, regs, sizeof(rt_sigframe)); 263 frame = get_sigframe(&ksig->ka, regs, sizeof(rt_sigframe));
268 264
269 if (frame == (void __user *) -1UL) 265 if (frame == (void __user *) -1UL)
270 goto give_sigsegv; 266 return -EFAULT;
271 267
272 if (copy_siginfo_to_user(&frame->info, info)) 268 if (copy_siginfo_to_user(&frame->info, &ksig->info))
273 goto give_sigsegv; 269 return -EFAULT;
274 270
275 /* Create the ucontext. */ 271 /* Create the ucontext. */
276 err |= __put_user(0, &frame->uc.uc_flags); 272 err |= __put_user(0, &frame->uc.uc_flags);
@@ -279,24 +275,24 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
279 err |= save_sigregs(regs, &frame->uc.uc_mcontext); 275 err |= save_sigregs(regs, &frame->uc.uc_mcontext);
280 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 276 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
281 if (err) 277 if (err)
282 goto give_sigsegv; 278 return -EFAULT;
283 279
284 /* Set up to return from userspace. If provided, use a stub 280 /* Set up to return from userspace. If provided, use a stub
285 already in userspace. */ 281 already in userspace. */
286 if (ka->sa.sa_flags & SA_RESTORER) { 282 if (ksig->ka.sa.sa_flags & SA_RESTORER) {
287 regs->gprs[14] = (unsigned long) 283 regs->gprs[14] = (unsigned long)
288 ka->sa.sa_restorer | PSW_ADDR_AMODE; 284 ksig->ka.sa.sa_restorer | PSW_ADDR_AMODE;
289 } else { 285 } else {
290 regs->gprs[14] = (unsigned long) 286 regs->gprs[14] = (unsigned long)
291 frame->retcode | PSW_ADDR_AMODE; 287 frame->retcode | PSW_ADDR_AMODE;
292 if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, 288 if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
293 (u16 __user *)(frame->retcode))) 289 (u16 __user *)(frame->retcode)))
294 goto give_sigsegv; 290 return -EFAULT;
295 } 291 }
296 292
297 /* Set up backchain. */ 293 /* Set up backchain. */
298 if (__put_user(regs->gprs[15], (addr_t __user *) frame)) 294 if (__put_user(regs->gprs[15], (addr_t __user *) frame))
299 goto give_sigsegv; 295 return -EFAULT;
300 296
301 /* Set up registers for signal handler */ 297 /* Set up registers for signal handler */
302 regs->gprs[15] = (unsigned long) frame; 298 regs->gprs[15] = (unsigned long) frame;
@@ -304,34 +300,27 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
304 regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | 300 regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
305 (PSW_USER_BITS & PSW_MASK_ASC) | 301 (PSW_USER_BITS & PSW_MASK_ASC) |
306 (regs->psw.mask & ~PSW_MASK_ASC); 302 (regs->psw.mask & ~PSW_MASK_ASC);
307 regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; 303 regs->psw.addr = (unsigned long) ksig->ka.sa.sa_handler | PSW_ADDR_AMODE;
308 304
309 regs->gprs[2] = map_signal(sig); 305 regs->gprs[2] = map_signal(ksig->sig);
310 regs->gprs[3] = (unsigned long) &frame->info; 306 regs->gprs[3] = (unsigned long) &frame->info;
311 regs->gprs[4] = (unsigned long) &frame->uc; 307 regs->gprs[4] = (unsigned long) &frame->uc;
312 regs->gprs[5] = task_thread_info(current)->last_break; 308 regs->gprs[5] = task_thread_info(current)->last_break;
313 return 0; 309 return 0;
314
315give_sigsegv:
316 force_sigsegv(sig, current);
317 return -EFAULT;
318} 310}
319 311
320static void handle_signal(unsigned long sig, struct k_sigaction *ka, 312static void handle_signal(struct ksignal *ksig, sigset_t *oldset,
321 siginfo_t *info, sigset_t *oldset, 313 struct pt_regs *regs)
322 struct pt_regs *regs)
323{ 314{
324 int ret; 315 int ret;
325 316
326 /* Set up the stack frame */ 317 /* Set up the stack frame */
327 if (ka->sa.sa_flags & SA_SIGINFO) 318 if (ksig->ka.sa.sa_flags & SA_SIGINFO)
328 ret = setup_rt_frame(sig, ka, info, oldset, regs); 319 ret = setup_rt_frame(ksig, oldset, regs);
329 else 320 else
330 ret = setup_frame(sig, ka, oldset, regs); 321 ret = setup_frame(ksig->sig, &ksig->ka, oldset, regs);
331 if (ret) 322
332 return; 323 signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLE_STEP));
333 signal_delivered(sig, info, ka, regs,
334 test_thread_flag(TIF_SINGLE_STEP));
335} 324}
336 325
337/* 326/*
@@ -345,9 +334,7 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
345 */ 334 */
346void do_signal(struct pt_regs *regs) 335void do_signal(struct pt_regs *regs)
347{ 336{
348 siginfo_t info; 337 struct ksignal ksig;
349 int signr;
350 struct k_sigaction ka;
351 sigset_t *oldset = sigmask_to_save(); 338 sigset_t *oldset = sigmask_to_save();
352 339
353 /* 340 /*
@@ -357,9 +344,8 @@ void do_signal(struct pt_regs *regs)
357 */ 344 */
358 current_thread_info()->system_call = 345 current_thread_info()->system_call =
359 test_pt_regs_flag(regs, PIF_SYSCALL) ? regs->int_code : 0; 346 test_pt_regs_flag(regs, PIF_SYSCALL) ? regs->int_code : 0;
360 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
361 347
362 if (signr > 0) { 348 if (get_signal(&ksig)) {
363 /* Whee! Actually deliver the signal. */ 349 /* Whee! Actually deliver the signal. */
364 if (current_thread_info()->system_call) { 350 if (current_thread_info()->system_call) {
365 regs->int_code = current_thread_info()->system_call; 351 regs->int_code = current_thread_info()->system_call;
@@ -370,7 +356,7 @@ void do_signal(struct pt_regs *regs)
370 regs->gprs[2] = -EINTR; 356 regs->gprs[2] = -EINTR;
371 break; 357 break;
372 case -ERESTARTSYS: 358 case -ERESTARTSYS:
373 if (!(ka.sa.sa_flags & SA_RESTART)) { 359 if (!(ksig.ka.sa.sa_flags & SA_RESTART)) {
374 regs->gprs[2] = -EINTR; 360 regs->gprs[2] = -EINTR;
375 break; 361 break;
376 } 362 }
@@ -387,9 +373,9 @@ void do_signal(struct pt_regs *regs)
387 clear_pt_regs_flag(regs, PIF_SYSCALL); 373 clear_pt_regs_flag(regs, PIF_SYSCALL);
388 374
389 if (is_compat_task()) 375 if (is_compat_task())
390 handle_signal32(signr, &ka, &info, oldset, regs); 376 handle_signal32(&ksig, oldset, regs);
391 else 377 else
392 handle_signal(signr, &ka, &info, oldset, regs); 378 handle_signal(&ksig, oldset, regs);
393 return; 379 return;
394 } 380 }
395 381