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