#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 это имеет смысл. Спасибо