This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Saving errno around signal handlers
- From: Florian Weimer <fweimer at redhat dot com>
- To: GNU C Library <libc-alpha at sourceware dot org>
- Date: Fri, 28 Feb 2014 12:49:45 +0100
- Subject: Saving errno around signal handlers
- Authentication-results: sourceware.org; auth=none
POSIX has green-lighted saving errno around signal handlers. So the
question now is how we implement that.
* glibc-only solution
We need to wrap the signal handler with a function that calls the actual
handler, saving and restoring errno around it. We do not have a place
to store the real handler address, so we need to use separate
trampolines, either generated dynamically or a from a static,
pre-allocated pool. There are only a few signal handlers, so a static
set of trampolines would work if we deallocate trampolines.
The problem with deallocation is that when sigaction is used to obtain
the address of the existing handler, we have to translate it back, and
concurrently freeing the trampoline will result in the wrong handler
address. So we'd need some form of locking, and it still needs to be
fully reentrant, so this will be difficult.
On the other hand, a trampoline just needs a few bytes on most
architectures (an indirect call to a machine language helper), so we
might get away with leaking the trampoline permanently, particularly if
we use a hash table to reuse the same trampoline for the same handler.
The trampolines are architecture-specific, but the rest would be generic.
* kernel-based solutions
We could teach the kernel about the location of the errno variable in
the TLS data structure and save and restore that. But this a gross
layering violation, so I won't consider it further.
We could add a process-wide callback function, settable with prctl, that
will be called by the kernel instead of the actual signal handler. It
would receive the same arguments as the handler, and an additional
argument that contains the address of the configured signal handler.
We could a flag which replaces SA_RESTORER and switches on this callback
behavior for a specific signal handler, using the existing sa_restorer
field as the address of the wrapper function.
The kernel-based approaches need architecture-specific changes in the
signal stack frame setup.
In all cases (kernel and glibc implementation), we can use a tail call
to make sure that the stack layout looks like it is at present (at least
on architectures with an available callee-saved register), and we would
not have to adjust GDB and other tools.
I'm not sure which approach would be the best way to proceed here.
Comments?
--
Florian Weimer / Red Hat Product Security Team