Question

"No functions registered by atexit() in the calling process image are registered in the new process image".

Here is code:

pid = fork();
if (pid == 0) {
    atexit(check_mem);
    return execv(...);
}

check_mem function not getting called after execv(). Because of above "line". Any hacks to get the function registered after execv call ??

Thanks in advance for your help.

Was it helpful?

Solution

The perfect solution is using ptrace() as below :

pid = fork();
if (pid == 0) {
    ptrace(PTRACE_TRACEME, 0, 0, 0);
    return execve(...);
}

wait(NULL);
ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACEEXIT);
ptrace(PTRACE_CONT, pid, 0, (void*)0);

    while(1){
    waitpid(pid, &status, 0);
    if((WSTOPSIG(status) == SIGTRAP) && (status & (PTRACE_EVENT_EXIT << 8)))
        break;

    ptrace(PTRACE_CONT, pid, 0, WSTOPSIG(status));
}

check_mem();

ptrace(PTRACE_CONT, pid, 0, 0);

Acknowledgments : www.wienand.org/junkcode/linux/stopper.c

OTHER TIPS

atexit handlers will not execute when you exec* something.

execv replaces the current process image, including any atexit handlers you've registered, so there's really not a lot you can do - your code is gone.

A little tricky but doable - create a shared library (let's call it check_mem.so) with a a function like so:

__attribute__((constructor)) void runs_first(void) {
  atexit(check_mem);
};

Note that check_mem needs to be defined in the library, not your program.

Now in execve, put LD_PRELOAD=/path/to/check_mem.so into the environment variables passed to the program (last argument to execve).

What will happen is that when the new program will run it will load the your check_mem library and run the runs_first function before (almost) every other code.

It will only work if the program you are execve'ing is dynamically linked, but AFAIK that is the only limitation.

EDIT: as comment rightfully stated, it wont work on setuid programs either. I still think there is a good chance it'll cover your use case though.

Like nos said, exec replaces your process. You might try using < stdlib.h >'s int system (char *s) function instead to start a program with args. Unlike execve, system returns when the spawned process exits, e.g.

pid = fork();
if (pid == 0) {
    atexit(check_mem);
    system ("program arg1 arg2 ...");
    exit (0); /* Calls atexit handlers. */
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top