Subject: port-i386/34112: i386 __sigtramp_siginfo_2 violates C calling convention
To: None <,,>
From: None <>
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
System: NetBSD 2.0 NetBSD 2.0 (PLANETAR) #2: Thu Dec 2 21:21:42 EST 2004 i386
Architecture: i386
Machine: i386

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.


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("...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.


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.)