Skip to content

Commit

Permalink
Prevent rt_sigqueueinfo and rt_tgsigqueueinfo from spoofing the signa…
Browse files Browse the repository at this point in the history
…l code

Userland should be able to trust the pid and uid of the sender of a
signal if the si_code is SI_TKILL.

Unfortunately, the kernel has historically allowed sigqueueinfo() to
send any si_code at all (as long as it was negative - to distinguish it
from kernel-generated signals like SIGILL etc), so it could spoof a
SI_TKILL with incorrect siginfo values.

Happily, it looks like glibc has always set si_code to the appropriate
SI_QUEUE, so there are probably no actual user code that ever uses
anything but the appropriate SI_QUEUE flag.

So just tighten the check for si_code (we used to allow any negative
value), and add a (one-time) warning in case there are binaries out
there that might depend on using other si_code values.

Signed-off-by: Julien Tinnes <jln@google.com>
Acked-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Julien Tinnes authored and Linus Torvalds committed Mar 21, 2011
1 parent b52307c commit da48524
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -2421,9 +2421,13 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig,
return -EFAULT;

/* Not even root can pretend to send signals from the kernel.
Nor can they impersonate a kill(), which adds source info. */
if (info.si_code >= 0)
* Nor can they impersonate a kill()/tgkill(), which adds source info.
*/
if (info.si_code != SI_QUEUE) {
/* We used to allow any < 0 si_code */
WARN_ON_ONCE(info.si_code < 0);
return -EPERM;
}
info.si_signo = sig;

/* POSIX.1b doesn't mention process groups. */
Expand All @@ -2437,9 +2441,13 @@ long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info)
return -EINVAL;

/* Not even root can pretend to send signals from the kernel.
Nor can they impersonate a kill(), which adds source info. */
if (info->si_code >= 0)
* Nor can they impersonate a kill()/tgkill(), which adds source info.
*/
if (info->si_code != SI_QUEUE) {
/* We used to allow any < 0 si_code */
WARN_ON_ONCE(info->si_code < 0);
return -EPERM;
}
info->si_signo = sig;

return do_send_specific(tgid, pid, sig, info);
Expand Down

0 comments on commit da48524

Please sign in to comment.