summaryrefslogtreecommitdiff
path: root/kernel/signal.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2018-09-25 12:04:47 +0200
committerEric W. Biederman <ebiederm@xmission.com>2018-10-03 16:46:28 +0200
commite75dc036c445b91b8b2ad4e6c9b05f04b6be6d3f (patch)
tree629998c30d946e656f969a40eeaca77da6249fbd /kernel/signal.c
parent018303a931a89b91dacd76140b8ebe51893dc5fe (diff)
signal: Fail sigqueueinfo if si_signo != sig
The kernel needs to validate that the contents of struct siginfo make sense as siginfo is copied into the kernel, so that the proper union members can be put in the appropriate locations. The field si_signo is a fundamental part of that validation. As such changing the contents of si_signo after the validation make no sense and can result in nonsense values in the kernel. As such simply fail if someone is silly enough to set si_signo out of sync with the signal number passed to sigqueueinfo. I don't expect a problem as glibc's sigqueue implementation sets "si_signo = sig" and CRIU just returns to the kernel what the kernel gave to it. If there is some application that calls sigqueueinfo directly that has a problem with this added sanity check we can revisit this when we see what kind of crazy that application is doing. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 7b49c31d3fdb..e445b0a63faa 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3306,7 +3306,8 @@ static int do_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *info)
(task_pid_vnr(current) != pid))
return -EPERM;
- info->si_signo = sig;
+ if (info->si_signo != sig)
+ return -EINVAL;
/* POSIX.1b doesn't mention process groups. */
return kill_proc_info(sig, info, pid);
@@ -3354,7 +3355,8 @@ static int do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info)
(task_pid_vnr(current) != pid))
return -EPERM;
- info->si_signo = sig;
+ if (info->si_signo != sig)
+ return -EINVAL;
return do_send_specific(tgid, pid, sig, info);
}