lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Wed, 11 Jul 2007 05:12:15 +0400 From: Anton Salikhmetov <salikhmetov@...il.com> To: linux-kernel@...r.kernel.org Subject: [PATCH] signals: real-time signals delivery order From: Anton Salikhmetov <salikhmetov@...il.com> According to the POSIX standard, multiple real-time signals pending to a process should be delivered in a strict order. Specifically, the lowest-numbered signal should be delivered first and multiple occurrences of signals with the same number should be delivered in FIFO order. Current Linux kernel delivers the highest-numbered signals pending to a process first, not the lowest-numbered ones. This contradicts to the requirement explained above. The problem can be demonstrated by the following test program: #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <time.h> #include <unistd.h> #define SIG_RAND (SIGRTMIN + rand() % (SIGRTMAX - SIGRTMIN + 1)) #define NUMSIG 7 struct { int sig, num; } seq[NUMSIG]; void sh(int sig, siginfo_t *info, void *unused) { static int cnt; seq[cnt].num = info->si_value.sival_int; seq[cnt++].sig = sig; } int main(int argc, char *argv[]) { int i; pid_t p = getpid(); struct sigaction sa; sigset_t ss, ssold; union sigval sv; sigemptyset(&ss); for (i = SIGRTMIN; i <= SIGRTMAX; i++) { sa.sa_sigaction = sh; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sigaction(i, &sa, NULL); sigaddset(&ss, i); } sigprocmask(SIG_BLOCK, &ss, &ssold); switch (fork()) { case -1: perror("fork()"); return 1; case 0: srand(time(NULL)); for (i = 0; i < NUMSIG; i++) { sv.sival_int = i; sigqueue(p, SIG_RAND, sv); } return 0; default: wait(NULL); } sigprocmask(SIG_SETMASK, &ssold, NULL); for (i = 0; i < NUMSIG; i++) printf("SIGRTMIN + %2d, sent with number %d\n", seq[i].sig - SIGRTMIN, seq[i].num); return 0; } Example of the program output for the original kernel: SIGRTMIN + 23, sent with number 0 SIGRTMIN + 21, sent with number 1 SIGRTMIN + 21, sent with number 6 SIGRTMIN + 16, sent with number 2 SIGRTMIN + 15, sent with number 3 SIGRTMIN + 14, sent with number 4 SIGRTMIN + 5, sent with number 5 Example of the program output for the patched kernel: SIGRTMIN + 2, sent with number 1 SIGRTMIN + 3, sent with number 0 SIGRTMIN + 17, sent with number 3 SIGRTMIN + 23, sent with number 5 SIGRTMIN + 25, sent with number 2 SIGRTMIN + 29, sent with number 6 SIGRTMIN + 30, sent with number 4 Patch for the Linux 2.6.22.1 kernel: Signed-off-by: Anton Salikhmetov <salikhmetov@...il.com> --- --- linux-2.6.22.1.orig/kernel/signal.c 2007-07-10 22:56:30.000000000 +0400 +++ linux-2.6.22.1/kernel/signal.c 2007-07-11 04:42:17.000000000 +0400 @@ -134,34 +134,11 @@ int next_signal(struct sigpending *pending, sigset_t *mask) { - unsigned long i, *s, *m, x; - int sig = 0; - - s = pending->signal.sig; - m = mask->sig; - switch (_NSIG_WORDS) { - default: - for (i = 0; i < _NSIG_WORDS; ++i, ++s, ++m) - if ((x = *s &~ *m) != 0) { - sig = ffz(~x) + i*_NSIG_BPW + 1; - break; - } - break; - - case 2: if ((x = s[0] &~ m[0]) != 0) - sig = 1; - else if ((x = s[1] &~ m[1]) != 0) - sig = _NSIG_BPW + 1; - else - break; - sig += ffz(~x); - break; - - case 1: if ((x = *s &~ *m) != 0) - sig = ffz(~x) + 1; - break; - } - + unsigned long *s = pending->signal.sig, *m = mask->sig, x; + int sig = 0, i; + for (i = 0; i < _NSIG_WORDS; i++, s++, m++) + if ((x = (*s & ~*m))) + sig = fls(x) + i * _NSIG_BPW; return sig; } - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists