Я не знаю issetugid()
, но я могу учиться, читая страницы руководства BSD или Solaris. Функция исходит от OpenBSD.
1) Руководство OpenBSD для issetugid(2) говорит: «Функция issetugid() возвращает 1, если процесс был выполнен setuid или setgid в результате последнего или другого предыдущего вызова execve(), в противном случае он возвращает 0." Затем он предлагает использовать issetugid() для проверки того, можно ли безопасно открывать файлы, указанные в переменных среды.
2) Нет, ваш код Linux и Solaris не эквивалентны. Процесс, выполняющий setuid, может установить свой реальный uid на его эффективный uid без очистки его переменных окружения. Например, uid_t uid = geteuid(); setresuid(uid, uid, uid);
установит как реальный uid, так и сохраненный uid для эффективного uid. Тогда ваш Linux issetugid() вернет 0, но Solaris isetugid() вернется 1.
Solaris проверяет флаг процесса во время выполнения. Illumos, свободная вилка Solaris, устанавливает SUGID в src/uts/common/os/exec.c при выполнении файла. OpenBSD имеет аналогичную логику. В руководстве OpenBSD говорится:
Если дочерний процесс выполняет новый исполняемый файл, будет определен новый статус issetugid. Этот статус основан на разрешениях uid, euid, gid и egid существующего процесса и в режимах исполняемого файла. Если в новых режимах исполняемого файла установлены setuid или setgid, или если существующий процесс выполняет новое изображение с помощью uid! = Euid или gid! = Egid, новый процесс будет считаться issetugid.
Solaris и OpenBSD сравнивают идентификаторы во время исполнения. Ваш код Linux задерживает сравнение до вызова issetugid(), поэтому он не эквивалентен.
3) Функции geteuid()
и getegid()
, похоже, работают одинаково везде; они просто возвращают эффективный идентификатор пользователя и эффективный идентификатор группы.
4) Сохраненные идентификаторы не имеют значения. Возможно, этот процесс изменил эти идентификаторы, не очищая переменные среды. Ни одна из реальных, эффективных или сохраненных идентификаторов не говорит нам, кто установил переменные среды для текущего процесса.
5) По крайней мере, на OpenBSD и Solaris процесс, который временно удаляет корень, не становится испорченным. На странице руководства OpenBSD указано:
Результат системного вызова issetugid() не вызван вызовами setuid(), setgid() или другими такими вызовами. В случае fork() дочерний процесс наследует один и тот же статус.
Статус issetugid() влияет только на execve().
Когда процесс временно удаляет корень с помощью setuid() или seteuid(), он не выполняет файл, поэтому его значение issetugid() не изменяется.
Но FreeBSD, DragonFly BSD и NetBSD более строго определяют issetugid(). руководство по FreeBSD для issetugid(2) говорит,
Процесс испорчен, если он был создан в результате execve (2) системный вызов, который был либо из Setuid или setgid битов (и дополнительные привилегии были даны в результате), или если он изменил любой из своих реальных, эффективных или сохраненных идентификаторов пользователей или групп с момента его запуска.
С помощью этих систем процесс, отбрасывающий корень, заставляет его значение issetugid() равным 1.
6) Нет, эффективный идентификатор, равный сохраненному идентификатору, не загрязняет процесс. Если это так, то каждый процесс будет испорчен, потому что каждый процесс имеет свой сохраненный идентификатор, установленный на его эффективный id во время выполнения.
Указанная основная причина вызова issetugid- гарантировать безопасное поведение при использовании в программах или программах setuid или setgid , которые работают с большим количеством привилегий после успешного выполнения. Вы можете сделать это более сложным, чем есть на самом деле. –
Спасибо Джим. Я в липкой ситуации - я проверяю код, который использует эту функцию. В Linux библиотека предоставляет API, потому что ядро этого не делает. Но я не уверен, что он должен делать (с его нестандартной точки зрения), или если он делает это эффективно ([Setuid Demystified] (http://www.cs.berkeley.edu/~daw/papers/setuid- usenix02.pdf)). – jww