5 ms·
Having Fun with Signal Handlers
- deleted 6y ago[deleted]
- zX41ZdbW 6y agoIt can be done easier with sigsetjmp, siglongjmp.
- zX41ZdbW 6y agoAlso you can check it with the `write` syscall (just write a byte pointed by address to /dev/null). If a pointer is invalid, it will return setting errno to EFAULT.
- scottlamb 6y agoNeat trick. I suppose you could also write the bytes to a self-pipe, avoiding the race the article mentions between ensuring the bytes are readable and actually reading them.
- jmgao 6y agoAnd if you're on Linux, you can read the memory directly with process_vm_readv.
- oomo 6y agoLeaving this here as comments on that blog seem broken. TL;DR: access(2) is a bit more lightweight than write(2) for this purpose. Consider the following (from memory, untested): word_t peek(word_t addr, int success) { word_t ret; errno = 0; access(addr, F_OK); if (success) success = (errno != EFAULT); if (errno != EFAULT) ret = *addr; return ret; } I first learnt about this trick in http://www.gcu-squad.org/2005/08/non-ce-n-est-pas-sale%21/ http://www.gcu-squad.org/2005/08/non-ce-n-est-pas-sale%21/
- s_gourichon 6y agoThe link posted by oomo contains (in French) an explanation about why it just works and is clean, general and guaranteed: from the page "les syscall ne peuvent pas segfault [dek\] Donc tous ceux qui acceptent une adresse [dek\] Sont obligées de checker qu’elles est valide [dek\] Et retournent EFAULT en cas d’erreur" In English: "syscalls cannot segfault, so all that accept an address (as parameter) have to check if it is valid and return EFAULT in case of error." (Since C code actually calls libc not system calls directly, this rationale fails on calls that do something on pointers before calling the actual kernel system call.) Also, given the time cost of making a system call, one has to has an approach finer than "pay a system call for each byte to write" if there are many. Anyway, TL;DR : it's not a dirty hack, it has some general validity!
- jez 6y agoAnother place where SIGSEGV handlers are common: showing backtraces and "how to report a bug" messages. For example here's where it's done in the Ruby VM: https://github.com/ruby/ruby/blob/5445e0435260b449decf2ac16f9d09bae3cafe72/signal.c#L946 https://github.com/ruby/ruby/blob/5445e0435260b449decf2ac16f... They have a bug report handler that shows a bunch of helpful information: - the Ruby-level backtrace - the stack of VM control frames (an internal data structure) - the C-level backtrace (which Ruby implementation functions were running) - which files had been required and loaded into memory - what segments of memory are mapped and what aren't Another thing: it's designed to work even when the program ran out of memory! The sigaltstack(2) system call lets you preallocate a buffer that the kernel knows how to set up before it runs your SIGSEGV handler, so you can have just enough stack memory to compute and print all this debug info before the program ultimately crashes. Here's that code, again in the Ruby VM: https://github.com/ruby/ruby/blob/5445e0435260b449decf2ac16f9d09bae3cafe72/signal.c#L548-L561 https://github.com/ruby/ruby/blob/5445e0435260b449decf2ac16f...
- linux2647 6y agoIn college, my database professor once told us about an object-oriented database that handled SIGSEGVs and created objects on the fly that were supposed to exist but didn’t (exact details are fuzzy)
- r-bryan 6y agoMaybe it was ObjectStore (read about it on Wikipedia). Pretty clever, I thought.
- linux2647 6y agoOoh that may be it. For everyone else, checkout this side deck (start at side 22): http://www.odbms.org/wp-content/uploads/2013/11/ObjectStoreIntro-v2.pdf http://www.odbms.org/wp-content/uploads/2013/11/ObjectStoreI...
- gpderetta 6y agoprobably related to https://en.wikipedia.org/wiki/Pointer_swizzling https://en.wikipedia.org/wiki/Pointer_swizzling
- ChickeNES 6y agoThe "fastmem" technique used by some emulators (Dolphin, for one) also uses a SIGSEGV handler to emulate the target machine's MMU using the host's MMU.
- wallstprog 6y agoInteresting that the Java VM installs signal handlers for SEGV, rather than checking for null pointers: https://www.ateam-oracle.com/why-am-i-seeing-sigsegv-when-i-strace-a-java-application-on-linux https://www.ateam-oracle.com/why-am-i-seeing-sigsegv-when-i-...