2013-05-18 1 views
1

Согласно страницам руководства для issetugid, вызов должен либо (1) оповестить об изменениях uid/gid; или (2) предупреждение о возможной испорченной среде. Название функции предполагает третью цель.Назначение issetugid?

Первый вопрос: какая цель?

Когда я смотрю на реализации имеющихся (например, в системе Linux в качестве библиотеки, так как ядро ​​Linux не обеспечивает API), я нахожу следующее:

if (getuid() != geteuid()) return 1; 
if (getgid() != getegid()) return 1; 
return 0; 

В Solaris, это выглядит следующим образом :

return ((curproc->p_flag & SUGID) != 0); 

Я немного подозрительным, но это отчасти потому, что его трудно понять, какие функции, как geteuid и getegid возвращение на всех платформах - например, BSD, Linux, Unix и Solaris.

Второй вопрос: код Linux семантически эквивалентен коду Solaris?

Третий вопрос: geteuid и getegid реализованы одинаково на всех платформах? Как насчет систем, у которых есть игра с тремя идентификаторами - реальная, эффективная и сохраненная?

Четвертый вопрос: эффективный идентификатор единственного идентификатора, который имеет здесь значение?

Если процесс начинается с UID = 0 и временно снижает привилегии, то вступает в игру saved. Процесс, который временно отбрасывает корень, не нуждается в exec и не должен быть испорчен.

ПЯТЫЙ вопрос: это процесс, который временно разрушает корень?

Шестой вопрос: должен ли процесс, действительный id которого является сохраненным идентификатором, считаться испорченным?

+0

Указанная основная причина вызова issetugid- гарантировать безопасное поведение при использовании в программах или программах setuid или setgid , которые работают с большим количеством привилегий после успешного выполнения. Вы можете сделать это более сложным, чем есть на самом деле. –

+0

Спасибо Джим. Я в липкой ситуации - я проверяю код, который использует эту функцию. В Linux библиотека предоставляет API, потому что ядро ​​этого не делает. Но я не уверен, что он должен делать (с его нестандартной точки зрения), или если он делает это эффективно ([Setuid Demystified] (http://www.cs.berkeley.edu/~daw/papers/setuid- usenix02.pdf)). – jww

ответ

4

Шесть вопросы многовато ответить в системе, предназначенной для один вопроса, чтобы ответить, особенно если ни один человек не знает ответы на все шесть, но я буду стараться ...

1) Цель из issetugid(), позволяет библиотекам знать, используются ли они в программе, которая была запущена с повышенными привилегиями, поэтому они могут избежать рискованного поведения, например, доверять переменным среды LD_LIBRARY_PATH, NLSPATH и т. д., которые позволят загружать модули вызывающего абонента, которые могут злоупотреблять повышенные привилегии. Вы можете увидеть некоторые исторические дискуссии по этому поводу ncurses 4.1 security bug thread.

2) Этот код выглядит менее безопасным, чем версии BSD & Solaris, поскольку он не учитывает сохраненные биты setid.

3) У них, вероятно, разные реализации на разных ядрах - посмотрите на исходный код платформы, чтобы узнать.

4, 5 & 6) Нет, да, да - процесс, который может изменить его euid или egid на более высокие уровни, все равно не должен доверять переменным окружения, которые заставляют его загружать предоставленный пользователем код, чтобы использовать их.

+0

~ alanc - «Шесть вопросов - это немного, чтобы ответить в системе, разработанной для одного вопроса ...» Да, согласился. Это был компромисс между одной почтой с несколькими вопросами или несколькими сообщениями (с большим количеством копий/папок) с одним вопросом. – jww

+0

спасибо, что ответили на вопрос 2 и 4. У меня были такие же чувства. Кроме того, вы видите гонку как проблему (это был еще один, менее важный вопрос, так как Linux (и другие ОС) полон гонок). – jww

+0

Если код многопоточный, то да, проверяя текущие результаты getuid/geteuid/etc. как показано в # 2, может участвовать в гонке против setuid/seteuid/etc. звонит и возвращает разные ответы в зависимости от того, кто победит в гонке. – alanc

2

Я не знаю 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 во время выполнения.

 Смежные вопросы

  • Нет связанных вопросов^_^