如何修改C代码以使用sudo杀死OpenSUSE 42.3中的子进程?

yeotifhr  于 2023-05-28  发布在  其他
关注(0)|答案(1)|浏览(105)

在测试OpenSUSE中遗留程序更新的兼容性时,我将问题追溯到一个奇怪的版本差异。下面的C程序在sudo中创建一个子进程,然后在sudo中杀死这个进程:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main (int argc, char *argv[]) 
{
    char execName[80] = "/usr/bin/sudo";
    char cmd[128];
    int pid = 0;
    int SIG = 15;
    if (argc > 1) SIG = atoi(argv[1]);

    printf("Sudo sleeping for 30 seconds.\n");
    printf("Sudo killing with signal %d.\n", SIG);
    printf("Use `ps aux | grep sleep` within 30 seconds to verify it was killed. Only this grep should show.\n");
    if ((pid = vfork()) == 0) {
        execl (execName, execName, "/bin/sleep", "30", (char *)NULL);
        perror(execName);
        exit (-1); 
    } else {
        if (pid == -1) perror("Bad PID for sleeper");
        fprintf( stderr, "sleeper process PID = %d\n", pid );
    }
    sprintf(cmd, "/usr/bin/sudo kill -%d %d", SIG, pid);
    system(cmd);
}

为了执行这段代码,用户需要访问sudosudoers需要访问kill。这准确地表示了遗留程序是如何工作的,除了睡眠程序是一个连续运行的过程,并且中间有更多的步骤。不幸的是,完全放弃这个计划是不现实的。
在OpenSUSE 13.2中,这个程序成功地杀死了睡眠者。但是,在OpenSUSE 42.3中,仍然保留了睡眠者。为什么?我如何重写它,以便我可以给予我自己的OpenSUSE 42. 3中的sudo子级一个kill信号?
作为实验,我将最后一个系统调用更改为/usr/bin/sudo pkill -15 -P %d,其中%d是进程ID。出于某种原因,这在不同版本中都有效,尽管并不可靠。我所拥有的关于为什么这些不同的理论都不能充分解释为什么 * 这 * 有效。

gfttwv5a

gfttwv5a1#

睡眠进程是sudo的子进程。您只会终止sudo进程,而不会终止其子进程。
您可以通过取消进程组前导的PID来终止整个进程组。只要sudo不为子进程创建新的进程组(这似乎不太可能),这就可以工作。

sprintf(cmd, "/usr/bin/sudo kill -%d %d", SIG, -pid);

此外,如果fork()返回-1,则应在打印错误消息后退出。通常的结构看起来像这样:

if ((pid = vfork()) == 0) {
    // child code
} else if (pid == -1) {
    // report error
} else {
    // parent code
}

相关问题