2011-10-15 26 views
0

「調用過程映像中沒有atexit()註冊的功能註冊到新過程映像中」。在atexit()的Execv註冊問題()

這裏是代碼:

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

check_mem功能execv後沒有得到所謂的()。由於上面的「線」。任何黑客獲得execv調用後註冊函數?

在此先感謝您的幫助。

回答

1

完美的解決方案是使用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

7

當你執行*某事時,atexit處理程序將不會執行。

execv取代了當前的過程映像,包括你已經註冊的任何atexit處理程序,所以實際上你可以做的事情不多 - 你的代碼已經沒有了。

+0

那麼,什麼是另一種方法做同樣的 – Mohyt

+2

@Mohyt那你需要做什麼完全取決於。你的checkmem()函數做了什麼,這對另一個進程是否有興趣? – nos

1

就像nos說的,exec取代你的過程。您可以嘗試使用< stdlib.h>的int system (char *s)函數,而不是使用args啓動程序。與execve不同,系統在產生的進程退出時返回,例如,

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

有點棘手,但可行的 - 創建一個像這樣AA功能的共享庫(讓我們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庫並在幾乎每一個其他代碼之前運行runs_first函數。

它只會在您正在執行的程序動態鏈接時起作用,但AFAIK是唯一的限制。

編輯:作爲評論正確地說,它不會在setuid程序工作。我仍然認爲它很有可能會覆蓋你的用例。

+1

它也不適用於setuid或setgid程序。 –