tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Libc support for old BSD-style "sigcontext" signal handlers is broken, let's just kill it.



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



Home | Main Index | Thread Index | Old Index