簡體   English   中英

WIFSIGNALED 沒有捕捉到 SEGFAULT 信號

[英]WIFSIGNALED not catching SEGFAULT signal

我相當確定 WIFEXITED 和 WIFSIGNALED 是什么以及它們是如何工作的。 我不知道為什么它不工作,因為程序發生了段錯誤,我可以很好地看到(調試)第三次迭代的信號是 SEGFAULT。 感謝您提供任何信息。

segfault_prog

#include <stdlib.h>
#include <stdio.h>
int main() {
        int *i = 0x478734;
        printf("%d", *i);
}
int main(void) {
    int status;
    int ret = fork();

    if (ret == 0) {
        ptrace(PTRACE_TRACEME, ret, NULL, NULL);
        raise(SIGSTOP);
        execve(argv[1], &argv[1], NULL);
        return 1;
    }
    else {
        while (1) {
            pid_t val = waitpid(ret, &status, 0);
            ptrace(PTRACE_SETOPTIONS, ret, 0,PTRACE_O_EXITKILL | PTRACE_O_TRACEEXEC);

            if (WIFEXITED(status) && val == ret){
                printf("exited normally");
                return WEXITSTATUS (status);
            }
            else if (WIFSIGNALED(status)){
//if I change for WEXITSTATUS(status) == SIGSEGV. then it works. First while iteration wIFEXITVAL(SIGSTOP/19), 2nd (SIGTRAP/5), 3rd (SIGSEGV 11);
                printf("signal error");
                return WEXITSTATUS (status);
            }

            ptrace(PTRACE_CONT, val, 0, 0);
        }
    }
    return (0);
}

幾個問題...

  1. 當tracee/child 停止時(即WIFSTOPPED),信號(即WSTOPSIG)必須向下發送到tracee。 這是PTRACE_CONT的最后一個參數

  2. 僅在第一個waitpid之后才需要執行PTRACE_SETOPTIONS

  3. waitpid的第一個參數應該是-1來捕獲所有的孩子

通過通過PTRACE_CONT [AFAICT] 向下發送信號,信號被延遲[直到跟蹤器選擇向下發送信號]。 因此,被跟蹤者/孩子生成了信號,但它從未發送給被跟蹤者/孩子。

另外,正如我所提到的,您可能想看看我最近的回答: ptrace options not working in parent process


這是重構的代碼。 它帶有錯誤和修復注釋:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/wait.h>

int
main(int argc,char **argv)
{
    int status;
    int ret = fork();

    if (ret == 0) {
        ptrace(PTRACE_TRACEME, ret, NULL, NULL);
// NOTE/BUG: not needed
#if 0
        raise(SIGSTOP);
#endif
        execve(argv[1], &argv[1], NULL);
#if 0
        return 1;
#else
        exit(1);
#endif
    }

#if TEST
    int iter = 20;
#else
    int iter = 0x7FFFFFFF;
#endif

    int first = 1;

    for (;  iter > 0;  --iter) {
// NOTE/BUG: we should catch all children (tracee might do fork but not wait
// and orphan/zombie its child (our grandchild) and we'd want to see that)
#if 0
        pid_t val = waitpid(ret, &status, 0);
#else
        pid_t val = waitpid(-1, &status, 0);
#endif

#if 1
        if (first) {
            ptrace(PTRACE_SETOPTIONS, ret, 0,
                PTRACE_O_EXITKILL | PTRACE_O_TRACEEXEC);
            first = 0;
        }
#endif

        printf("pt: status=%8.8X\n",status);

        int signo = 0;

        if (WIFEXITED(status)) {
            printf("pt: WIFEXITED %d\n",WEXITSTATUS(status));
        }

        if (WIFSTOPPED(status)) {
            signo = WSTOPSIG(status);
            printf("pt: WIFSTOPPED %d\n",signo);
            if (signo == SIGTRAP)
                signo = 0;
        }

        if (WIFSIGNALED(status)) {
            printf("pt: WIFSIGNALED %d\n",WTERMSIG(status));
        }

        if (WIFEXITED(status) && val == ret) {
            printf("exited normally");
            return WEXITSTATUS(status);
        }
        else if (WIFSIGNALED(status)) {
            // if I change for WEXITSTATUS(status) == SIGSEGV. then it works.
            // First while iteration wIFEXITVAL(SIGSTOP/19), 2nd (SIGTRAP/5),
            // 3rd (SIGSEGV 11);
#if 0
            printf("signal error");
#else
            printf("signal error -- %d\n",WTERMSIG(status));
#endif
            return WEXITSTATUS(status);
        }

// NOTE/BUG: must send signo from WIFSTOPPED/WSTOPSIG to tracee
#if SHOWBUG
        ptrace(PTRACE_CONT, val, 0, 0);
#else
        ptrace(PTRACE_CONT, val, 0, signo);
#endif
    }

    if (iter <= 0)
        printf("pt: fault -- not seen\n");

    return (0);
}

在上面的代碼中,我使用cpp條件來表示舊代碼和新代碼:

#if 0
// old code
#else
// new code
#endif

#if 1
// new code
#endif

這是原始行為(使用-DTEST -DSHOWBUG編譯):

pt: status=0000057F
pt: WIFSTOPPED 5
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: fault -- not seen

這是修復后的輸出:

pt: status=0000057F
pt: WIFSTOPPED 5
pt: status=00000B7F
pt: WIFSTOPPED 11
pt: status=0000008B
pt: WIFSIGNALED 11
signal error -- 11

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM