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

#linux #setuid

#linux #setuid

Вопрос:

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

 int main(int argc, char* argv[]) {
    setuid(0); 
    setgid(0);
    printf("Current uid and euid are %d, %dn", 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 = %dn", ret);
                return 0;
        }
}
  

И запустил его как непривилегированный пользователь (где test бит setuid установлен root). В этом случае родитель не может убить дочернего процесса. kill вызов возвращает -1, и test процесс становится потерянным.

Что здесь происходит? Что особенного делает bash, что он может убивать дочерние процессы, которые он порождает?

Ответ №1:

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

Комментарии:

1. Я вижу, это имеет гораздо больше смысла. Просто в стороне, я тестирую это снова ssh . sshd В этом случае просто передает ^C драйверу tty сервера? Или здесь sshd (запуск от имени root) напрямую отправляет сигнал?

2. sshd подключил удаленный процесс к псевдотерминалу. Запустите tty , это должно быть что-то вроде /dev/pts/1 . Это терминал на удаленном компьютере, который отвечает на символ прерывания и отправляет сигнал группе процессов переднего плана. Используя tcsetattr(3) , вы можете отключить это или изменить символ.

3. @AjayBrahmakshatriya нет, ssh-сервер просто записывает ^C символ на главную сторону псевдо-tty, который он выделил на удаленной машине.

4. @TrentP это имеет смысл. Спасибо