Subject: port-i386/34112: i386 __sigtramp_siginfo_2 violates C calling convention
To: None <port-i386-maintainer@netbsd.org, gnats-admin@netbsd.org,>
From: None <jld@NetBSD.org>
List: netbsd-bugs
Date: 07/29/2006 11:00:01
>Number: 34112
>Category: port-i386
>Synopsis: i386 __sigtramp_siginfo_2 violates C calling convention
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: port-i386-maintainer
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Jul 29 11:00:01 +0000 2006
>Originator: Jed Davis
>Release: NetBSD 2.0
>Organization:
[]
>Environment:
System: NetBSD planetarium.xlerb.net 2.0 NetBSD 2.0 (PLANETAR) #2: Thu Dec 2 21:21:42 EST 2004 jdev@planetarium.xlerb.net:/usr/src/sys/arch/i386/compile/PLANETAR i386
Architecture: i386
Machine: i386
>Description:
The signal handling function is (as far as I can tell) permitted by the
C ABI to arbitrarily scribble on the stack space holding its arguments,
what with C being call-by-value and all.
However, __sigtramp_siginfo_2 attempts to read the ucontext_t* to
setcontext back to from the location in which it was passed at the
sigaction function's third argument. If that syscall fails (because,
e.g., the number 3 was passed instead of a valid pointer), the
trampoline will then call _exit.
This can lead to a situation where a program works fine when compiled
with -O0, but with optimization enabled will mysteriously exit with a
bizarre status value for no comprehensible reason when returning from a
signal handler.
>How-To-Repeat:
As a more or less minimal test case, this C program:
#include <signal.h>
#include <stdio.h>
static void safu(int s, siginfo_t *si, void* ctx)
{
ctx = (void*)3;
}
int main()
{
struct sigaction sa;
sigaction(SIGUSR1, 0, &sa);
sa.sa_flags |= SA_SIGINFO;
sa.sa_sigaction = safu;
sigaction(SIGUSR1, &sa, 0);
printf("Raising...\n");
raise(SIGUSR1);
printf("...should get here.\n");
return 0;
}
will, if compiled *without* optimization, reproduce the problem (exits
before getting to "should get here"); with optimization turned on, GCC
will delete the store to ctx and the sigaction will return normally.
>Fix:
That which sets up the call to the signal handler should push an
extra copy of the context pointer onto the stack before the function
arguments; the trampoline should then use that instead of the possibly
clobbered one.
(That assumes there's no other/better way for the trampoline to obtain
the correct context pointer.)