(VG_(do__NR_sigaction)): Don't allow setting of
handlers for SIGKILL or SIGSTOP. This fixes
valgrind: vg_signals.c:723 (vgPlain_do__NR_sigaction):
Assertion `our_old_handler == ((void *)0)' failed.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@40 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/ChangeLog b/ChangeLog
index d51cc8d..e3265b3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2002-03-29 Julian Seward <sewardj@localhost.localdomain>
+
+ * vg_signals.c (VG_(do__NR_sigaction)): Don't allow setting of
+ handlers for SIGKILL or SIGSTOP. This fixes
+ valgrind: vg_signals.c:723 (vgPlain_do__NR_sigaction):
+ Assertion `our_old_handler == ((void *)0)' failed.
+
2002-03-29 Alexandre Duret-Lutz <duret_g@epita.fr>
* vg_syscall_mem.c: wrapper for ioctl TIOCGPGRP.
diff --git a/coregrind/vg_kerneliface.h b/coregrind/vg_kerneliface.h
index 480188c..15ce80d 100644
--- a/coregrind/vg_kerneliface.h
+++ b/coregrind/vg_kerneliface.h
@@ -132,6 +132,11 @@
#define VKI_MAP_PRIVATE 0x02 /* Changes are private. */
+/* Copied from /usr/src/linux-2.4.9-13/include/asm/errno.h */
+
+#define VKI_EINVAL 22 /* Invalid argument */
+
+
/* Gawd ... hack ... */
typedef struct vki__user_cap_header_struct {
diff --git a/coregrind/vg_signals.c b/coregrind/vg_signals.c
index ed7ef67..2372fc4 100644
--- a/coregrind/vg_signals.c
+++ b/coregrind/vg_signals.c
@@ -688,7 +688,17 @@
(UInt)(new_action ? new_action->ksa_flags : 0) );
/* VG_(ppSigProcMask)(); */
- if (param1 < 1 || param1 >= VKI_KNSIG) goto bad;
+ /* Rule out various error conditions. The aim is to ensure that if
+ the call is passed to the kernel it will definitely succeed. */
+
+ /* Reject out-of-range signal numbers. */
+ if (param1 < 1 || param1 >= VKI_KNSIG) goto bad_signo;
+
+ /* Reject attempts to set a handler (or set ignore) for SIGKILL. */
+ if ( (param1 == VKI_SIGKILL || param1 == VKI_SIGSTOP)
+ && new_action
+ && new_action->ksa_handler != VKI_SIG_DFL)
+ goto bad_sigkill;
our_old_handler = VG_(sighandler)[param1];
/* VG_(printf)("old handler = 0x%x\n", our_old_handler); */
@@ -714,6 +724,7 @@
KERNEL_DO_SYSCALL(res);
/* VG_(printf)("RES = %d\n", res); */
+
/* If the client asks for the old handler, maintain our fiction
by stuffing in the handler it thought it asked for ... */
if (old_action) {
@@ -742,11 +753,18 @@
VG_(baseBlock)[VGOFF_(m_eax)] = (UInt)0;
return;
- bad:
+ bad_signo:
VG_(message)(Vg_UserMsg,
"Warning: bad signal number %d in __NR_sigaction.",
param1);
- VG_(baseBlock)[VGOFF_(m_eax)] = (UInt)(-1);
+ VG_(baseBlock)[VGOFF_(m_eax)] = (UInt)(-VKI_EINVAL);
+ return;
+
+ bad_sigkill:
+ VG_(message)(Vg_UserMsg,
+ "Warning: attempt to set SIGKILL handler in __NR_sigaction.",
+ param1);
+ VG_(baseBlock)[VGOFF_(m_eax)] = (UInt)(-VKI_EINVAL);
return;
}
diff --git a/tests/sigkill.c b/tests/sigkill.c
new file mode 100644
index 0000000..c4c7b77
--- /dev/null
+++ b/tests/sigkill.c
@@ -0,0 +1,35 @@
+
+#include <errno.h>
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+
+static void
+abend (int sig)
+{
+ printf ("Abended on signal %d\n", sig);
+ exit (2);
+}
+
+int
+main (void)
+{
+ struct sigaction sa;
+
+ int i;
+ for (i = 1; i <= 64; i++) {
+ sa.sa_flags = 0;
+ sigemptyset( &sa.sa_mask );
+ sa.sa_handler = abend;
+ errno = 0;
+ fprintf(stderr, "setting signal %d: ", i);
+ sigaction (i /*SIGKILL*/, &sa, NULL);
+ perror ("");
+ errno = 0;
+ fprintf(stderr, "getting signal %d: ", i);
+ sigaction (i /*SIGKILL*/, NULL, &sa);
+ perror ("");
+ fprintf(stderr, "\n");
+ }
+ return 0;
+}
diff --git a/tests/signal1.c b/tests/signal1.c
index 68a5cad..a35975c 100644
--- a/tests/signal1.c
+++ b/tests/signal1.c
@@ -11,7 +11,7 @@
printf ( "signal returns\n" );
}
-void main ( void )
+int main ( void )
{
spin = 1;
printf ( "installing sig handler\n" );
@@ -19,4 +19,5 @@
printf ( "entering busy wait\n" );
while (spin) { };
printf ( "exited\n" );
+ return 0;
}
diff --git a/tests/signal2.c b/tests/signal2.c
index 6892d33..5797537 100644
--- a/tests/signal2.c
+++ b/tests/signal2.c
@@ -8,11 +8,12 @@
exit(1);
}
-void main ( void )
+int main ( void )
{
printf ( "installing sig handler\n" );
signal(SIGSEGV, sig_hdlr);
printf ( "doing bad thing\n" );
* (int*) 0 = 0;
printf ( "exited normally ?!\n" );
+ return 0;
}
diff --git a/tests/signal3.c b/tests/signal3.c
index e2b4d17..6c1cc68 100644
--- a/tests/signal3.c
+++ b/tests/signal3.c
@@ -26,8 +26,9 @@
assert(ret == 0);
}
-void main ( void )
+int main ( void )
{
hdp_init_profiling();
while (1) {}
+ return 0;
}
diff --git a/vg_kerneliface.h b/vg_kerneliface.h
index 480188c..15ce80d 100644
--- a/vg_kerneliface.h
+++ b/vg_kerneliface.h
@@ -132,6 +132,11 @@
#define VKI_MAP_PRIVATE 0x02 /* Changes are private. */
+/* Copied from /usr/src/linux-2.4.9-13/include/asm/errno.h */
+
+#define VKI_EINVAL 22 /* Invalid argument */
+
+
/* Gawd ... hack ... */
typedef struct vki__user_cap_header_struct {
diff --git a/vg_signals.c b/vg_signals.c
index ed7ef67..2372fc4 100644
--- a/vg_signals.c
+++ b/vg_signals.c
@@ -688,7 +688,17 @@
(UInt)(new_action ? new_action->ksa_flags : 0) );
/* VG_(ppSigProcMask)(); */
- if (param1 < 1 || param1 >= VKI_KNSIG) goto bad;
+ /* Rule out various error conditions. The aim is to ensure that if
+ the call is passed to the kernel it will definitely succeed. */
+
+ /* Reject out-of-range signal numbers. */
+ if (param1 < 1 || param1 >= VKI_KNSIG) goto bad_signo;
+
+ /* Reject attempts to set a handler (or set ignore) for SIGKILL. */
+ if ( (param1 == VKI_SIGKILL || param1 == VKI_SIGSTOP)
+ && new_action
+ && new_action->ksa_handler != VKI_SIG_DFL)
+ goto bad_sigkill;
our_old_handler = VG_(sighandler)[param1];
/* VG_(printf)("old handler = 0x%x\n", our_old_handler); */
@@ -714,6 +724,7 @@
KERNEL_DO_SYSCALL(res);
/* VG_(printf)("RES = %d\n", res); */
+
/* If the client asks for the old handler, maintain our fiction
by stuffing in the handler it thought it asked for ... */
if (old_action) {
@@ -742,11 +753,18 @@
VG_(baseBlock)[VGOFF_(m_eax)] = (UInt)0;
return;
- bad:
+ bad_signo:
VG_(message)(Vg_UserMsg,
"Warning: bad signal number %d in __NR_sigaction.",
param1);
- VG_(baseBlock)[VGOFF_(m_eax)] = (UInt)(-1);
+ VG_(baseBlock)[VGOFF_(m_eax)] = (UInt)(-VKI_EINVAL);
+ return;
+
+ bad_sigkill:
+ VG_(message)(Vg_UserMsg,
+ "Warning: attempt to set SIGKILL handler in __NR_sigaction.",
+ param1);
+ VG_(baseBlock)[VGOFF_(m_eax)] = (UInt)(-VKI_EINVAL);
return;
}