-
Notifications
You must be signed in to change notification settings - Fork 0
Tool that ensures only async-signal-safe functions are called in signal handlers
License
dwks/asyncsafe
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
This is asyncsafe, which makes sure you only call async-signal-safe functions
from within signal handlers. It works by hijacking the PLT entries of all
functions that are not supposed to be called from signal handlers, and
printing an error message if any one is. Supports 64-bit x86_64 Linux only.
signal and sigaction are both overloaded to catch any signal handler
registration, instrumenting the handlers to automatically enable and disable
the PLT hijacking. The hijacking works by resetting PLT entries to point within
the table so that they must be resolved (as in lazy function resolving, see
ld.so(8)). The resolution function is hijacked to print an error message
(including the name of the function that was called), and defer to the real
resolution function. The PLT entries are restored when the signal handler exits
(though one could rely on the normal resolution mechanism to re-resolve them,
at a speed penalty).
The function names and PLT entries are found by parsing the ELF file of the
main executable. This will only work if the signal handler is within the main
executable, and not in a shared library.
Example:
$ make
gcc -Wall -Wextra -Wno-unused-parameter test.c -o test
gcc -Wall -Wextra -Wno-unused-parameter test2.c -o test2
gcc -Wall -Wextra -O -shared -fPIC safe.c allow.c print.c elfmap.c plt.c resolve.s violation.c -o libasyncsafe.so -ldl
$ ./test
This handler is fine
This handler is bad :(
$ LD_PRELOAD=./libasyncsafe.so ./test
This handler is fine
asyncsafe violation! handler for signal 12 called [puts]
This handler is bad :(
The violation message will only be printed the first time a function is called.
After that, the true function's address will be stored in the PLT.
It is also possible to link asyncsafe.so into your program directly:
$ gcc test.c -o test -L. -lasyncsafe -Wl,-rpath=.
$ ./test
This handler is fine
asyncsafe violation! handler for signal 12 called [puts]
This handler is bad :(
$
Finally, for debugging purposes or to learn how it works, turn on debugging
info:
$ ASYNCSAFE_LOGGING=1 LD_PRELOAD=./libasyncsafe.so ./test
getting ELF info for [/proc/16387/exe]
asyncsafe: intercept signal 10 registration of handler 0x400726
asyncsafe: intercept signal 12 registration of handler 0x400748
asyncsafe on vvv
handler 600bf0
allow plt entry at 600bf8 (index 1) for [raise]
BLOCK plt entry at 600c00 (index 3) for [puts]
allow plt entry at 600c08 (index 4) for [write]
BLOCK plt entry at 600c10 (index 5) for [__libc_start_main]
allow plt entry at 600c18 (index 8) for [signal]
This handler is fine
asyncsafe off ^^^
handler 600bf0
restore original plt entries
asyncsafe on vvv
handler 600bf0
allow plt entry at 600bf8 (index 1) for [raise]
BLOCK plt entry at 600c00 (index 3) for [puts]
allow plt entry at 600c08 (index 4) for [write]
BLOCK plt entry at 600c10 (index 5) for [__libc_start_main]
allow plt entry at 600c18 (index 8) for [signal]
asyncsafe violation! handler for signal 12 called [puts]
This handler is bad :(
asyncsafe off ^^^
handler 600bf0
restore original plt entries
$
For greater efficiency, compile with -DDISABLE_LOGGING to remove all print
statements at compile time (meaning the debugging will not work).
This project was created by David Williams-King in a few hours using ELF
parsing code from other projects. It is released under a BSD license. If you
like this tool and have suggestions to improve it or ideas for another tool,
please email me, dwk at cs dot columbia period edu. Thanks!
About
Tool that ensures only async-signal-safe functions are called in signal handlers
Resources
License
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published