Hey folks —

I was looking into the request for a libc function that determined if a program 
counter was inside a signal trampoline (see 
https://mail-index.netbsd.org/tech-kern/2021/10/15/msg027703.html), and the 
first thing I decided to do as part of this was unify all of the 
__libc_sigaction14() functions … each architecture has its own copy, and 
they’re mostly identical, except for in their support (or not) for old-style 
“sigcontext” handlers and their trampoline ABI versions (VAX had actually rev’d 
its sigcontext trampoline ABI before “siginfo” support was added).  Anyway, a 
few defines in <sys/signal.h> with the ability to override values in 
<machine/signal.h> will do the trick.

However, as I was adding an #ifdef conditional to the sigcontext handling in 
the new unified __sigaction14_sigtramp.c (because new architectures added after 
“siginfo” support was added never really needed it, and didn’t define a “struct 
sigcontext”), I realized that in 2006, support for sigcontext handling was 
broken on platforms that previously supported it (each copy gained a 
__LIBC12_SOURCE__ conditional around the sigcontext support, but nothing ever 
defined __LIBC12_SOURCE__ for those files).

I went ahead and listed it out by architecture in my own notes, but the TL;DR 
is that “sigcontext” style signal handlers don’t work on any architecture.

For those not familiar, there are 3 basic types of signal handlers:

1. void handler(int sig);  // simple traditional handler

2. void handler(int sig, int code, struct sigcontext *scp);  // sigcontext 
handler

3. void handler(int sig, struct siginfo *info, ucontext_t *ctx);  // siginfo 
handler

Originally, the code in libc to select the correct trampoline for each type 
selected the “siginfo” trampoline if SA_SIGINFO was set in the sigaction, 
otherwise it used the “sigcontext” trampoline.  The trampoline is responsible 
to restoring the previous program flow, and it needs to know what format the 
saved registers are in to do so, which is why there are two types.

Since Feb 2006 (with one minor exception; don’t worry, it was broken a few 
months later), the “siginfo” trampoline has always been chosen, meaning that 
any old program dynamically linked against libc that uses style “2” above would 
get garbage in the “code” and “scp” arguments.

Obviously, the practical impact of this is nil, since no one apparently noticed 
(and I guess we didn’t break any programs that people were using).  We haven’t 
documented that style of handler for a VERY long time but presumably the intent 
was for it to continue to work because the code remained and was modified 
several times over the years. (it was certainly my original intent when I first 
added support for multiple signal trampolines in a single process ~20 years 
ago, and it did in fact work for the first few years that code existed).

At this point, I don’t see any value in going back and actually fixing 
sigcontext style handlers.  My preference here is to simply remove that 
trampoline from libc.  I do think kernel support should remain, because we 
generally are sticklers for binary compatibility, but we should completely hide 
the “struct sigcontext” definitions from user-space in <machine/signal.h>.

Thoughts?

-- thorpej

Reply via email to