Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect recursion robustly even in the presence of non-local jumps

I have a particular function (a signal handler) for which I'd like to detect recursion, i.e. to figure out if the function has directly or indirectly called itself. The tricky bit is that the function calls some code not under its control at one point, and that code could do anything.

Normally, I'd just write something like

void foo() {
    static int recursed = 0;
    if(recursed) {
        ...
    }
    recursed = 1;
    othercode();
    recursed = 0;
}

but in this case, I'm concerned that othercode could use a longjmp or similar to break out, resulting in recursed remaining at 1. In the event that my function is jumped out of in this way, I want to ensure it doesn't see itself as recursing if is called later (the fact that it is longjmp'd out of is not a problem otherwise).

Note: I consider longjmp to be likely. The othercode is a chained signal handler from some other in-the-wild code, and there do exist handlers for e.g. SIGSEGV which use longjmp to restore context (e.g. as "fault protection" exception handlers). Note that using longjmp in a synchronous signal handler is generally safe. In any case, I don't particularly care whether the other code is safe at all, because it's not something under my control.

like image 681
nneonneo Avatar asked Jun 05 '13 04:06

nneonneo


1 Answers

Not sure what exactly the code would look like to do it, but instead of a static int, you could have a static void *. Instead of setting it to 1, set it to point to the current stack frame. In addition to checking if it's nonzero, you check to make sure that the return address from the next stack frame after recursed in fact points to a location in foo's code, and also that recursed is above the current stack pointer, i.e. not popped.

Sounds very fragile and architecture-dependent.

like image 137
morningstar Avatar answered Sep 23 '22 00:09

morningstar