diff options
Diffstat (limited to 'arch/s390/kernel/compat_signal.c')
-rw-r--r-- | arch/s390/kernel/compat_signal.c | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index b537cb0e9b55..eee999853a7c 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c | |||
@@ -39,6 +39,7 @@ typedef struct | |||
39 | struct sigcontext32 sc; | 39 | struct sigcontext32 sc; |
40 | _sigregs32 sregs; | 40 | _sigregs32 sregs; |
41 | int signo; | 41 | int signo; |
42 | __u32 gprs_high[NUM_GPRS]; | ||
42 | __u8 retcode[S390_SYSCALL_SIZE]; | 43 | __u8 retcode[S390_SYSCALL_SIZE]; |
43 | } sigframe32; | 44 | } sigframe32; |
44 | 45 | ||
@@ -48,6 +49,7 @@ typedef struct | |||
48 | __u8 retcode[S390_SYSCALL_SIZE]; | 49 | __u8 retcode[S390_SYSCALL_SIZE]; |
49 | compat_siginfo_t info; | 50 | compat_siginfo_t info; |
50 | struct ucontext32 uc; | 51 | struct ucontext32 uc; |
52 | __u32 gprs_high[NUM_GPRS]; | ||
51 | } rt_sigframe32; | 53 | } rt_sigframe32; |
52 | 54 | ||
53 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) | 55 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) |
@@ -344,6 +346,30 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) | |||
344 | return 0; | 346 | return 0; |
345 | } | 347 | } |
346 | 348 | ||
349 | static int save_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs) | ||
350 | { | ||
351 | __u32 gprs_high[NUM_GPRS]; | ||
352 | int i; | ||
353 | |||
354 | for (i = 0; i < NUM_GPRS; i++) | ||
355 | gprs_high[i] = regs->gprs[i] >> 32; | ||
356 | |||
357 | return __copy_to_user(uregs, &gprs_high, sizeof(gprs_high)); | ||
358 | } | ||
359 | |||
360 | static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs) | ||
361 | { | ||
362 | __u32 gprs_high[NUM_GPRS]; | ||
363 | int err, i; | ||
364 | |||
365 | err = __copy_from_user(&gprs_high, uregs, sizeof(gprs_high)); | ||
366 | if (err) | ||
367 | return err; | ||
368 | for (i = 0; i < NUM_GPRS; i++) | ||
369 | *(__u32 *)®s->gprs[i] = gprs_high[i]; | ||
370 | return 0; | ||
371 | } | ||
372 | |||
347 | asmlinkage long sys32_sigreturn(void) | 373 | asmlinkage long sys32_sigreturn(void) |
348 | { | 374 | { |
349 | struct pt_regs *regs = task_pt_regs(current); | 375 | struct pt_regs *regs = task_pt_regs(current); |
@@ -363,6 +389,8 @@ asmlinkage long sys32_sigreturn(void) | |||
363 | 389 | ||
364 | if (restore_sigregs32(regs, &frame->sregs)) | 390 | if (restore_sigregs32(regs, &frame->sregs)) |
365 | goto badframe; | 391 | goto badframe; |
392 | if (restore_sigregs_gprs_high(regs, frame->gprs_high)) | ||
393 | goto badframe; | ||
366 | 394 | ||
367 | return regs->gprs[2]; | 395 | return regs->gprs[2]; |
368 | 396 | ||
@@ -394,6 +422,8 @@ asmlinkage long sys32_rt_sigreturn(void) | |||
394 | 422 | ||
395 | if (restore_sigregs32(regs, &frame->uc.uc_mcontext)) | 423 | if (restore_sigregs32(regs, &frame->uc.uc_mcontext)) |
396 | goto badframe; | 424 | goto badframe; |
425 | if (restore_sigregs_gprs_high(regs, frame->gprs_high)) | ||
426 | goto badframe; | ||
397 | 427 | ||
398 | err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp); | 428 | err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp); |
399 | st.ss_sp = compat_ptr(ss_sp); | 429 | st.ss_sp = compat_ptr(ss_sp); |
@@ -474,6 +504,8 @@ static int setup_frame32(int sig, struct k_sigaction *ka, | |||
474 | 504 | ||
475 | if (save_sigregs32(regs, &frame->sregs)) | 505 | if (save_sigregs32(regs, &frame->sregs)) |
476 | goto give_sigsegv; | 506 | goto give_sigsegv; |
507 | if (save_sigregs_gprs_high(regs, frame->gprs_high)) | ||
508 | goto give_sigsegv; | ||
477 | if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs)) | 509 | if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs)) |
478 | goto give_sigsegv; | 510 | goto give_sigsegv; |
479 | 511 | ||
@@ -529,13 +561,14 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
529 | goto give_sigsegv; | 561 | goto give_sigsegv; |
530 | 562 | ||
531 | /* Create the ucontext. */ | 563 | /* Create the ucontext. */ |
532 | err |= __put_user(0, &frame->uc.uc_flags); | 564 | err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags); |
533 | err |= __put_user(0, &frame->uc.uc_link); | 565 | err |= __put_user(0, &frame->uc.uc_link); |
534 | err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | 566 | err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); |
535 | err |= __put_user(sas_ss_flags(regs->gprs[15]), | 567 | err |= __put_user(sas_ss_flags(regs->gprs[15]), |
536 | &frame->uc.uc_stack.ss_flags); | 568 | &frame->uc.uc_stack.ss_flags); |
537 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | 569 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); |
538 | err |= save_sigregs32(regs, &frame->uc.uc_mcontext); | 570 | err |= save_sigregs32(regs, &frame->uc.uc_mcontext); |
571 | err |= save_sigregs_gprs_high(regs, frame->gprs_high); | ||
539 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 572 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
540 | if (err) | 573 | if (err) |
541 | goto give_sigsegv; | 574 | goto give_sigsegv; |