diff options
| -rw-r--r-- | arch/Kconfig | 3 | ||||
| -rw-r--r-- | include/linux/compat.h | 4 | ||||
| -rw-r--r-- | kernel/signal.c | 45 |
3 files changed, 39 insertions, 13 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 18c0383dcc42..c612b5ccfd84 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
| @@ -365,6 +365,9 @@ config GENERIC_COMPAT_RT_SIGPROCMASK | |||
| 365 | config GENERIC_COMPAT_RT_SIGPENDING | 365 | config GENERIC_COMPAT_RT_SIGPENDING |
| 366 | bool | 366 | bool |
| 367 | 367 | ||
| 368 | config GENERIC_COMPAT_RT_SIGQUEUEINFO | ||
| 369 | bool | ||
| 370 | |||
| 368 | # | 371 | # |
| 369 | # ABI hall of shame | 372 | # ABI hall of shame |
| 370 | # | 373 | # |
diff --git a/include/linux/compat.h b/include/linux/compat.h index 75548a43a1c5..bbee15ef3ae9 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
| @@ -602,6 +602,10 @@ asmlinkage long compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set, | |||
| 602 | asmlinkage long compat_sys_rt_sigpending(compat_sigset_t __user *uset, | 602 | asmlinkage long compat_sys_rt_sigpending(compat_sigset_t __user *uset, |
| 603 | compat_size_t sigsetsize); | 603 | compat_size_t sigsetsize); |
| 604 | #endif | 604 | #endif |
| 605 | #ifdef CONFIG_GENERIC_COMPAT_RT_SIGQUEUEINFO | ||
| 606 | asmlinkage long compat_sys_rt_sigqueueinfo(compat_pid_t pid, int sig, | ||
| 607 | struct compat_siginfo __user *uinfo); | ||
| 608 | #endif | ||
| 605 | asmlinkage long compat_sys_sysinfo(struct compat_sysinfo __user *info); | 609 | asmlinkage long compat_sys_sysinfo(struct compat_sysinfo __user *info); |
| 606 | asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, | 610 | asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, |
| 607 | unsigned long arg); | 611 | unsigned long arg); |
diff --git a/kernel/signal.c b/kernel/signal.c index 3040c349b0e1..6cd3023cc66b 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -2983,6 +2983,22 @@ SYSCALL_DEFINE2(tkill, pid_t, pid, int, sig) | |||
| 2983 | return do_tkill(0, pid, sig); | 2983 | return do_tkill(0, pid, sig); |
| 2984 | } | 2984 | } |
| 2985 | 2985 | ||
| 2986 | static int do_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *info) | ||
| 2987 | { | ||
| 2988 | /* Not even root can pretend to send signals from the kernel. | ||
| 2989 | * Nor can they impersonate a kill()/tgkill(), which adds source info. | ||
| 2990 | */ | ||
| 2991 | if (info->si_code >= 0 || info->si_code == SI_TKILL) { | ||
| 2992 | /* We used to allow any < 0 si_code */ | ||
| 2993 | WARN_ON_ONCE(info->si_code < 0); | ||
| 2994 | return -EPERM; | ||
| 2995 | } | ||
| 2996 | info->si_signo = sig; | ||
| 2997 | |||
| 2998 | /* POSIX.1b doesn't mention process groups. */ | ||
| 2999 | return kill_proc_info(sig, info, pid); | ||
| 3000 | } | ||
| 3001 | |||
| 2986 | /** | 3002 | /** |
| 2987 | * sys_rt_sigqueueinfo - send signal information to a signal | 3003 | * sys_rt_sigqueueinfo - send signal information to a signal |
| 2988 | * @pid: the PID of the thread | 3004 | * @pid: the PID of the thread |
| @@ -2993,23 +3009,26 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig, | |||
| 2993 | siginfo_t __user *, uinfo) | 3009 | siginfo_t __user *, uinfo) |
| 2994 | { | 3010 | { |
| 2995 | siginfo_t info; | 3011 | siginfo_t info; |
| 2996 | |||
| 2997 | if (copy_from_user(&info, uinfo, sizeof(siginfo_t))) | 3012 | if (copy_from_user(&info, uinfo, sizeof(siginfo_t))) |
| 2998 | return -EFAULT; | 3013 | return -EFAULT; |
| 3014 | return do_rt_sigqueueinfo(pid, sig, &info); | ||
| 3015 | } | ||
| 2999 | 3016 | ||
| 3000 | /* Not even root can pretend to send signals from the kernel. | 3017 | #ifdef CONFIG_COMPAT |
| 3001 | * Nor can they impersonate a kill()/tgkill(), which adds source info. | 3018 | #ifdef CONFIG_GENERIC_COMPAT_RT_SIGQUEUEINFO |
| 3002 | */ | 3019 | COMPAT_SYSCALL_DEFINE3(rt_sigqueueinfo, |
| 3003 | if (info.si_code >= 0 || info.si_code == SI_TKILL) { | 3020 | compat_pid_t, pid, |
| 3004 | /* We used to allow any < 0 si_code */ | 3021 | int, sig, |
| 3005 | WARN_ON_ONCE(info.si_code < 0); | 3022 | struct compat_siginfo __user *, uinfo) |
| 3006 | return -EPERM; | 3023 | { |
| 3007 | } | 3024 | siginfo_t info; |
| 3008 | info.si_signo = sig; | 3025 | int ret = copy_siginfo_from_user32(&info, uinfo); |
| 3009 | 3026 | if (unlikely(ret)) | |
| 3010 | /* POSIX.1b doesn't mention process groups. */ | 3027 | return ret; |
| 3011 | return kill_proc_info(sig, &info, pid); | 3028 | return do_rt_sigqueueinfo(pid, sig, &info); |
| 3012 | } | 3029 | } |
| 3030 | #endif | ||
| 3031 | #endif | ||
| 3013 | 3032 | ||
| 3014 | long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info) | 3033 | long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info) |
| 3015 | { | 3034 | { |
