This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Saving errno around signal handlers


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]