Как bash может убивать дочерние процессы с помощью CTRL+C

Я написал простую программу следующим образом:

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

Я скомпилировал это как root и установил бит setuid, используя sudo chmod +s test.

Когда эта программа запускается от имени непривилегированного пользователя из 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 особенным, что он может убить порожденные им дочерние процессы?


person Ajay Brahmakshatriya    schedule 11.11.2020    source источник


Ответы (1)


Bash не нужны никакие разрешения, потому что bash ничего не делает. Когда вы нажимаете ^C, драйвер tty отправляет SIGINT всем процессам в группе процессов переднего плана. Сигнал исходит от системы, а не от другого процесса, поэтому проверки разрешений, относящиеся к одному процессу, отправляющему сигнал другому, не применяются.

person hobbs    schedule 11.11.2020
comment
Я вижу, это имеет больше смысла. Кроме того, я проверяю это на ssh. В этом случае sshd просто передает ^C драйверу tty сервера? Или здесь sshd (запущенный как root) напрямую посылает сигнал? - person Ajay Brahmakshatriya; 11.11.2020
comment
sshd подключил удаленный процесс к псевдотерминалу. Запустите tty, это должно быть что-то вроде /dev/pts/1. Это терминал на удаленной машине, который отвечает на символ прерывания и отправляет сигнал группе процессов переднего плана. Используя tcsetattr(3), вы можете отключить это или изменить символ. - person TrentP; 11.11.2020
comment
@AjayBrahmakshatriya нет, ssh-сервер просто записывает символ ^C на главную сторону псевдотерминала, который он выделил на удаленной машине. - person user414777; 11.11.2020
comment
@TrentP, это имеет смысл. Спасибо - person Ajay Brahmakshatriya; 12.11.2020