linux-为什么在附加到跟踪时,GDB可以屏蔽跟踪的SIGKILL

signal(7)手册页指出SIGKILL不能被捕获,阻止或忽略.但是我只是观察到,在使用GDB附加到进程之后,我无法再将SIGKILL发送到该进程(类似地,其他信号也无法传递).但是在我分离并退出GDB之后,SIGKILL照常交付.

在我看来,GDB在附加时已阻止该信号(代表示踪),而在分离时已取消阻止了该信号.但是,ptrace(2)手册页显示:

While being traced, the tracee will stop each time a signal is delivered, even if the signal is being ignored. (An exception is SIGKILL, which has its usual effect.)

那么为什么会这样呢? GDB使用什么技巧?

这是一个简单的演示示例:

1.测试程序

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <string.h>

/* Simple error handling functions */

#define handle_error_en(en, msg) \
    do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

struct sigaction act;

void sighandler(int signum, siginfo_t *info, void *ptr) {
    printf("Received signal: %d\n", signum);
    printf("signal originate from pid[%d]\n", info->si_pid);
}

int
main(int argc, char *argv[])
{
    printf("Pid of the current process: %d\n", getpid());

    memset(&act, 0, sizeof(act));

    act.sa_sigaction = sighandler;
    act.sa_flags = SA_SIGINFO;

    sigaction(SIGQUIT, &act, NULL);

    while(1) {
        ;
    }

    return 0;
}

如果您尝试使用SIGKILL终止该程序(即使用kill -KILL ${pid}),它将按预期终止.如果您尝试将其发送为SIGQUIT(即使用kill -QUIT ${pid}),则将按预期执行那些printf语句.但是,如果在发送信号之前将其附加到GDB,则不会发生任何事情:

$##### in shell 1 #####
$gdb
(gdb) attach ${pid}
(gdb)

/ *现在gdb已成功附加到另一个shell中:* /

$#### in shell 2 ####
$kill -QUIT ${pid}    # nothing happen
$kill -KILL ${pid}    # again, nothing happen!

/ *现在gdb已分离* /

##### in shell 1 ####
(gdb) quit

/ *该进程将收到SIGKILL * /

##### in shell 2 ####
$Killed    # the tracee receive **SIGKILL** eventually...

仅供参考,我使用的是CentOS-6u3,uname -r结果在2.6.32_1-16-0-0中.我的GDB版本是:GNU gdb(GDB)红帽企业Linux(7.2-56.el6),我的GCC版本是:gcc(GCC)3.4.6 20060404(红帽3.4.6-19.el6).一台旧机器…

任何想法将不胜感激;-)

解决方法:

$##### in shell 1 #####
$gdb
(gdb) attach ${pid}
(gdb)

问题在于,一旦GDB附加到${pid},劣等(正在调试)的进程就不再运行-它将停止.

直到它继续执行(使用(gdb)continue命令)或不再被跟踪((gdb)分离或退出),内核才会对其执行任何操作.

如果您发出继续命令(在杀死-QUIT之前或之后),则会看到以下内容:

(gdb) c
Continuing.

在另一个shell中执行kill -QUIT $pid:

Program received signal SIGQUIT, Quit.
main (argc=1, argv=0x7ffdcc9c1518) at t.c:35
35      }

(gdb) c
Continuing.
Received signal: 3
signal originate from pid[123419]

kill -KILL在另一个窗口中执行:

Program terminated with signal SIGKILL, Killed.
The program no longer exists.
(gdb)
上一篇:GDB调试系列之了解GDB


下一篇:Linux内核提权漏洞(CVE-2019-13272)