【问题标题】:How is bash able to kill children processes with CTRL+Cbash 如何使用 CTRL+C 杀死子进程
【发布时间】:2021-02-23 02:50:45
【问题描述】:

我写了一个简单的程序如下-

int main(int argc, char* argv[]) {
    setuid(0); 
    setgid(0);
    printf("Current uid and euid are %d, %d\n", getuid(), geteuid());
    while(1);
}

我将它编译为 root 并使用 sudo chmod +s test 设置 setuid 位。

当这个程序作为非特权用户从 bash 运行时,程序会打印 -

当前 uid 和 euid 为 0, 0

然后陷入无限循环。

但是我仍然可以通过按 Crl+C 来终止此进程。如果我理解正确,bash(以非特权用户身份运行)应该无法将 SIGINT 发送到根进程。

我也对kill <pid of test> 进行了同样的尝试,但由于例外而失败。

bash 是如何杀死进程的?父进程和子进程之间是否有特殊关系?

我也试过这个其他的包装程序 -

int main(int argc, char* argv[]) {
        pid_t p = fork();
        if (p == 0) {
                char * args[] = {"./test", NULL};
                execv("./test", args);
        } else {
                sleep(4);
                int ret = kill(p, 9);
                printf("Kill returned = %d\n", ret);
                return 0;
        }
}

并以非特权用户身份运行它(test 的 setuid 位由 root 设置)。在这种情况下,父母无法杀死孩子。 kill 调用返回 -1,test 进程被孤立。

这里发生了什么? bash 有什么特别之处可以杀死它产生的子进程?

【问题讨论】:

    标签: linux setuid


    【解决方案1】:

    Bash 不需要任何权限,因为 bash 没有做任何事情。当您点击 ^C 时,tty 驱动程序会将 SIGINT 发送到前台进程组中的所有进程。信号来自系统,而不是来自另一个进程,因此与一个进程向另一个进程发送信号相关的权限检查不适用。

    【讨论】:

    • 我明白了,这更有意义。顺便说一句,我正在通过ssh 进行测试。在这种情况下,sshd 是否只是将 ^C 交给服务器 tty 驱动程序?还是这里sshd(以root身份运行)直接发送信号?
    • sshd 已将远程进程连接到伪终端。运行tty,它应该类似于/dev/pts/1。那是远程机器上的终端,它响应中断字符并向前台进程组发送信号。使用tcsetattr(3),您可以将其关闭或更改字符。
    • @AjayBrahmakshatriya 不,ssh 服务器只是将 ^C 字符写入它在远程计算机上分配的伪 tty 的主端。
    • @TrentP 这是有道理的。谢谢
    猜你喜欢
    • 1970-01-01
    • 2019-11-13
    • 2019-07-13
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多