wrong pid in siginfo_t

From: Ulrich Drepper (drepper@redhat.com)
Date: Fri Jul 04 2003 - 16:05:16 EST

Hash: SHA1

If a signal is sent via kill() or tkill() the kernel fills in the wrong
PID value in the siginfo_t structure (obviously only if the handler has
SA_SIGINFO set). POSIX specifies the the si_pid field is filled with
the process ID. The kernel currently fills in the thread ID. The
thread IDs are not useful at all at userlevel. They are not exposed

One might argue that sending up the ID of the thread as well is a good
thing but I don't agree. This is what sigqueue is for: one can attach
arbitrary data to the signal and get it transmitted (the sigval_t

I've attached a patch for the current 2.5 kernel and a test case.
Whoever collects kernel tests might want to add the program.

- --
- --------------. ,-. 444 Castro Street
Ulrich Drepper \ ,-----------------' \ Mountain View, CA 94041 USA
Red Hat `--' drepper at redhat.com `---------------------------
Version: GnuPG v1.2.1 (GNU/Linux)


--- kernel/signal.c-save 2003-06-03 10:14:55.000000000 -0700
+++ kernel/signal.c 2003-07-04 13:46:55.000000000 -0700
@@ -2081,7 +2081,7 @@ sys_kill(int pid, int sig)
         info.si_signo = sig;
         info.si_errno = 0;
         info.si_code = SI_USER;
- info.si_pid = current->pid;
+ info.si_pid = current->tgid;
         info.si_uid = current->uid;
         return kill_something_info(sig, &info, pid);
@@ -2104,7 +2104,7 @@ sys_tkill(int pid, int sig)
         info.si_signo = sig;
         info.si_errno = 0;
         info.si_code = SI_TKILL;
- info.si_pid = current->pid;
+ info.si_pid = current->tgid;
         info.si_uid = current->uid;

#include <semaphore.h>
#include <signal.h>
#include <unistd.h>

static int failed;
static pid_t pid;
static uid_t uid;
static sem_t sem;
static int is_kill;


static void
sh (int sig, siginfo_t *si, void *ctx)
  if (sig != si->si_signo)
      printf ("sig != si->si_signo: %d vs %d\n", sig, (int) si->si_signo);
      failed = 1;
  if (si->si_code != is_kill ? SI_USER : SI_QUEUE)
      printf ("si->si_code wrong: %d\n", si->si_code);
      failed = 1;
  if (si->si_pid != pid)
      printf ("si->si_pid wrong: %d vs %d\n", (int) si->si_pid, (int) pid);
      failed = 1;
  if (si->si_uid != uid)
      printf ("si->si_uid wrong: %d vs %d\n", (int) si->si_uid, (int) uid);
      failed = 1;
  sem_post (&sem);

static void *
tf (void *arg)
  puts ("trying kill");
  is_kill = 1;
  kill (pid, THESIG);
  sem_wait (&sem);

  puts ("trying sigqueue");
  sigval_t sv;
  sv.sival_int = 42;
  is_kill = 0;
  sigqueue (pid, THESIG, sv);
  sem_wait (&sem);

main (void)
  pid = getpid ();
  uid = getuid ();

  struct sigaction sa;
  sa.sa_sigaction = sh;
  sa.sa_flags = SA_SIGINFO;
  sigemptyset (&sa.sa_mask);
  sigaction (THESIG, &sa, NULL);

  sem_init (&sem, 0, 0);

  pthread_t th;
  puts ("starting 1st thread");
  pthread_create (&th, NULL, tf, NULL);
  pthread_join (th, NULL);
  puts ("starting 2nd thread");
  pthread_create (&th, NULL, tf, NULL);
  pthread_join (th, NULL);

  return failed;

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

This archive was generated by hypermail 2b29 : Mon Jul 07 2003 - 22:00:24 EST