views:

82

answers:

3

Hello all,

I'm wondering if its at all possible to sandbox a dynamically linked library via dlopen and friends. The aim is to recover from an error within the library without tearing down the hole application e.g SEGFAULT, etc...

Anyone had any experience in this area?

Cheers

+4  A: 

You can fork() before calling the library, then pass the result to your mother process. Let mother process wait for data from child, or report error if it crashes.

che
Thank you for your time. I had considered this method however this is a fairly heavy handed approach and was hoping for a more elegant solution.
When you link library code, you share memory with it, which means that its errors can not only segfault, but also overwrite your memory with garbage. If you want to guard against that, process separation is really the best way to go.
che
A fork is not the proper way to go since it creates a completely new context (even though it's essentially identical, it is still a copy) something as simple as increasing a usage count of the library you are liking is "different"
Elf King
Of course if you have an application with some run-time context (or worse, threads) you should not fork and continue to run the whole thing. The child should `exec()` some minimal stub that will just get necessary data for library call, do the call, and pass the result.
che
+1  A: 

OK well generally speaking exception handling is highly operating system dependent. I am going to make some assumptions and try to provide some generic guidance. Please know that this is by no means an exhaustive reply, but should serve as a place to start.

I will assume that:

  1. For the most part, you are interested in safeguarding against memory leaks.

  2. You are not interested in Windows (which is whole-other-ball-of-wax) since you mentioned dlopen (you would have said LoadLibrary otherwise)

  3. That you are aware of the nuances of linking against C++ symbols. If you are not read up on it at mini howto on dlopen c++

Generally speaking

There is no general solution to the described problem without involving specialized operating systems that provide data and code segment sand-boxing there are Trusted Systems and specialty operating system kernels that can do this, but i assume that you want to do this on a good old *nix or windows environment.

Compiler stuff further complicates issues (does your C++ compiler generate weak symbols by default? typically it would) This affects how exception handling happens in a try-catch.

Simple operating system exception handling that raises signals (SIGSEGV, SIGFPE etc.):

Under POSIX system supporting sigaction...

Let's say you want to protect against generic things like bad memory addressing. Trap the SIGSEG using sigaction before dlopening a library (to protect against .init functions) and then also do a signal check before calling a function within the library. Consider using SA_STACK to ensure that your handler jumps into a stack you have good control over, and SA_SIGINFO to ensure that your handler gets info about the source.

A good place to start on this is at the Signal handling on GNU libc manual

Under C++: use wrappers and with try-catch to catch soft exceptions

try { foo(); } catch() { // do something }

where foo is a weak symbol pointing to a function in your dll see c++ dlopen mini-howto for a lot more examples and details on loading classes etc.

If you have more specific needs, post them, i'll see if i can provide more info.

Cheers

Elf King
A: 

How would you differentiate a segfault from your application and the dynamic library in question? Creating a separate process to fence off the library as che described seems like the best approach.

edit:

found this related question, pointing at a CERT advisory suggesting not to return from a SIGSEGV handler if you desire portability.

Sam Miller
Using sigaction SA_SIGINFO you can determine the context under which the signal was sent which means you can actually figure out the function that raised the signal if you backtrace programatically, and figure out whether it was a function within the library or not, and since you are catching the signal, you can the resume properly. Performing a fork() is not a good way to determine resilience of a library ...
Elf King