Execv регистрация проблемы в atexit () - PullRequest
0 голосов
/ 15 октября 2011

"В новом образе процесса не зарегистрированы функции, зарегистрированные atexit () в образе вызывающего процесса".

Вот код:

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

Функция check_mem не вызывается после execv (). Из-за вышеупомянутой "линии". Любые хаки, чтобы зарегистрировать функцию после вызова execv ??

Заранее спасибо за помощь.

Ответы [ 4 ]

7 голосов
/ 15 октября 2011

обработчики atexit не будут выполняться, когда вы выполняете * что-то.

execv заменяет текущий образ процесса, включая любые зарегистрированные обработчики atexit, так что на самом деле вы ничего не можете сделать - ваш код пропал.

2 голосов
/ 15 октября 2011

Немного сложно, но выполнимо - создайте разделяемую библиотеку (назовем ее check_mem.so) с такой функцией:

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

Обратите внимание, что check_mem должен быть определен в библиотеке, а не в вашей программе.

Теперь в execve поместите LD_PRELOAD = / path / to / check_mem.so в переменные окружения, переданные программе (последний аргумент для execve).

Что произойдет, когдановая программа запустится, она загрузит вашу библиотеку check_mem и запустит функцию run_first перед (почти) любым другим кодом.

Это будет работать только в том случае, если программа, которую вы выполняете, динамически связана, но AFAIK, которыйединственное ограничение.

РЕДАКТИРОВАТЬ: как правильно сказано в комментарии, он также не будет работать на программах setuid.Я все еще думаю, что есть большая вероятность, что он охватит ваш вариант использования.

1 голос
/ 17 октября 2011

Идеальным решением является использование ptrace (), как показано ниже:

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);

Благодарности: www.wienand.org / junkcode / linux / stopper.c

1 голос
/ 15 октября 2011

Как сказал nos, exec заменяет ваш процесс. Вместо этого вы можете попробовать использовать функцию int system (char *s) , чтобы запустить программу с аргументами. В отличие от execve, система возвращается при выходе из порожденного процесса, например,

pid = fork();
if (pid == 0) {
    atexit(check_mem);
    system ("program arg1 arg2 ...");
    exit (0); /* Calls atexit handlers. */
}
...