Changing program execution flow by signal and return address

494 Views Asked by At

I'm trying to change program execution flow by changing return address of functions in this code:

void s(int signum) {
    int b = 1;
    *(&b+3) = *(&b+3) + 4;
}

void f() {
    while(true);
    printf("f exit\n");
}

int main() {
    signal( SIGCONT, s );

    f();

    printf("end of prog");

    return 0;
}

For this purpose I invoke f function. So it gets stuck at while(true). Then I send a SIGCONT signal to program using kill -SIGCONT <PID> command. Now the program must interrupt executing while(true) in f and execute s function. In s function I defined b to find return address of s function in runtime stack which is *(&b+3). I try to change this value with *(&b+3) = *(&b+3) + 4 so that when it gets back to f, skip execution of while(true) and execute printf("f exit\n"). but it keeps getting stuck at while and I have no idea how to make this work.

NOTE: I verified *(&b+3) as return address by comparing it to value returned by __builtin_return_address(0) before.

Body of functions main and f must be unchanged.

Thanks.

1

There are 1 best solutions below

2
On

The solution is tell somehow the while loop that something changed. For example

volatile int flag = 0 ;

void s(int signum) {
    int b = 1;
    __sync_fetch_and_add( &flag, 1 ) ;
}

void f() {
    while(__sync_fetch_and_add( &flag, 0 ) == 0);
    printf("f exit\n");
}

The atomic intrinsic (function __sync_fetch_and_add) is added to avoid having the loop optimized away. I am not sure a simple volatile is enough. Waiting for comments myself on this....