diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 45 |
1 files changed, 32 insertions, 13 deletions
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 | { |