diff options
Diffstat (limited to 'arch/parisc/kernel/signal32.c')
-rw-r--r-- | arch/parisc/kernel/signal32.c | 42 |
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 __ | |||
401 | int | 403 | int |
402 | copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from) | 404 | copy_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) | |||
445 | int | 447 | int |
446 | copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from) | 448 | copy_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 | |||
505 | asmlinkage 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 | |||