aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/kernel/signal32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc/kernel/signal32.c')
-rw-r--r--arch/parisc/kernel/signal32.c42
1 files changed, 32 insertions, 10 deletions
diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c
index a6b4231cafa1..1c1a37f73053 100644
--- a/arch/parisc/kernel/signal32.c
+++ b/arch/parisc/kernel/signal32.c
@@ -1,6 +1,8 @@
1/* Signal support for 32-bit kernel builds 1/* Signal support for 32-bit kernel builds
2 * 2 *
3 * Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org> 3 * Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
4 * Copyright (C) 2006 Kyle McMartin <kyle at parisc-linux.org>
5 *
4 * Code was mostly borrowed from kernel/signal.c. 6 * Code was mostly borrowed from kernel/signal.c.
5 * See kernel/signal.c for additional Copyrights. 7 * See kernel/signal.c for additional Copyrights.
6 * 8 *
@@ -401,7 +403,7 @@ setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __
401int 403int
402copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from) 404copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
403{ 405{
404 unsigned long tmp; 406 compat_uptr_t addr;
405 int err; 407 int err;
406 408
407 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t))) 409 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
@@ -424,8 +426,8 @@ copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
424 err |= __get_user(to->si_uid, &from->si_uid); 426 err |= __get_user(to->si_uid, &from->si_uid);
425 break; 427 break;
426 case __SI_FAULT >> 16: 428 case __SI_FAULT >> 16:
427 err |= __get_user(tmp, &from->si_addr); 429 err |= __get_user(addr, &from->si_addr);
428 to->si_addr = (void __user *) tmp; 430 to->si_addr = compat_ptr(addr);
429 break; 431 break;
430 case __SI_POLL >> 16: 432 case __SI_POLL >> 16:
431 err |= __get_user(to->si_band, &from->si_band); 433 err |= __get_user(to->si_band, &from->si_band);
@@ -445,7 +447,8 @@ copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
445int 447int
446copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from) 448copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from)
447{ 449{
448 unsigned int addr; 450 compat_uptr_t addr;
451 compat_int_t val;
449 int err; 452 int err;
450 453
451 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) 454 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
@@ -474,8 +477,8 @@ copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from)
474 err |= __put_user(from->si_uid, &to->si_uid); 477 err |= __put_user(from->si_uid, &to->si_uid);
475 break; 478 break;
476 case __SI_FAULT >> 16: 479 case __SI_FAULT >> 16:
477 /* avoid type-checking warnings by copying _pad[0] in lieu of si_addr... */ 480 addr = ptr_to_compat(from->si_addr);
478 err |= __put_user(from->_sifields._pad[0], &to->si_addr); 481 err |= __put_user(addr, &to->si_addr);
479 break; 482 break;
480 case __SI_POLL >> 16: 483 case __SI_POLL >> 16:
481 err |= __put_user(from->si_band, &to->si_band); 484 err |= __put_user(from->si_band, &to->si_band);
@@ -484,17 +487,36 @@ copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from)
484 case __SI_TIMER >> 16: 487 case __SI_TIMER >> 16:
485 err |= __put_user(from->si_tid, &to->si_tid); 488 err |= __put_user(from->si_tid, &to->si_tid);
486 err |= __put_user(from->si_overrun, &to->si_overrun); 489 err |= __put_user(from->si_overrun, &to->si_overrun);
487 addr = (unsigned long) from->si_ptr; 490 val = (compat_int_t)from->si_int;
488 err |= __put_user(addr, &to->si_ptr); 491 err |= __put_user(val, &to->si_int);
489 break; 492 break;
490 case __SI_RT >> 16: /* Not generated by the kernel as of now. */ 493 case __SI_RT >> 16: /* Not generated by the kernel as of now. */
491 case __SI_MESGQ >> 16: 494 case __SI_MESGQ >> 16:
492 err |= __put_user(from->si_uid, &to->si_uid); 495 err |= __put_user(from->si_uid, &to->si_uid);
493 err |= __put_user(from->si_pid, &to->si_pid); 496 err |= __put_user(from->si_pid, &to->si_pid);
494 addr = (unsigned long) from->si_ptr; 497 val = (compat_int_t)from->si_int;
495 err |= __put_user(addr, &to->si_ptr); 498 err |= __put_user(val, &to->si_int);
496 break; 499 break;
497 } 500 }
498 } 501 }
499 return err; 502 return err;
500} 503}
504
505asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
506 struct compat_siginfo __user *uinfo)
507{
508 siginfo_t info;
509
510 if (copy_siginfo_from_user32(&info, uinfo))
511 return -EFAULT;
512
513 /* Not even root can pretend to send signals from the kernel.
514 Nor can they impersonate a kill(), which adds source info. */
515 if (info.si_code >= 0)
516 return -EPERM;
517 info.si_signo = sig;
518
519 /* POSIX.1b doesn't mention process groups. */
520 return kill_proc_info(sig, &info, pid);
521}
522