Выбрать главу

1. Если у исполняемого файла установлен бит полномочий set-user-ID (set-group-ID), то действующий пользовательский (групповой) ID процесса становится таким же, что и у владельца исполняемого файла. Если у исполняемого файла не установлен бит полномочий set-user-ID (set-group-ID), то действующий пользовательский (групповой) ID процесса не изменяется.

2. Значения для сохраненного set-user-ID и сохраненного set-group-ID копируются из соответствующих действующих идентификаторов. Это копирование осуществляется независимо от того, был ли у выполняемого на данный момент файла установлен бит set-user-ID или бит set-group-ID.

Рассмотрим пример того, что происходит в ходе вышеизложенных действий. Предположим, что процесс, чьи пользовательские идентификаторы — реальный, действительный и сохраненный set-user-ID — равны 1000, выполняет set-user-ID-программу, владельцем которой является root (UID равен 0). После выполнения пользовательские идентификаторы процесса будут изменены следующим образом:

real=1000 effective=0 saved=0 (реальный=1000 действующий=0 сохраненный=0)

Различные системные вызовы позволяют set-user-ID-программе переключать ее действующий пользовательский идентификатор между значениями реального UID и сохраненного set-user-ID. Аналогичные системные вызовы позволяют программе с полномочиями setgid изменять ее действующий GID. Таким образом, программа может временно сбросить и восстановить любые полномочия, связанные с пользовательским (групповым) идентификатором исполняемого файла. (Иными словами, она может перемещаться между состояниями потенциальной привилегированности и фактической работы с полномочиями.) При более подробном рассмотрении вопроса в разделе 38.2 выяснится, что требования безопасного программирования гласят: программа должна работать под непривилегированным (реальным) ID до тех пор, пока ей на самом деле не понадобятся права привилегированного (то есть сохраненного установленного) ID.

Иногда в качестве синонимов сохраненного установленного идентификатора пользователя и сохраненного установленного идентификатора группы употребляются выражения «сохраненный идентификатор пользователя» и «сохраненный идентификатор группы».

Сохраненные установленные идентификаторы являются нововведениями, появившимися в System V и принятыми в POSIX. В выпусках BSD, предшествующих 4.4, они не предоставлялись. В исходном стандарте POSIX.1 поддержка этих идентификаторов была необязательной, но в более поздних стандартах (начиная с FIPS 151-1 в 1988 году) стала обязательной.

9.5. Пользовательские и групповые ID файловой системы

В Linux для определения полномочий при выполнении операций, связанных с файловой системой (открытие файла, изменение его собственника и модификация полномочий), применяются не действующие пользовательские и групповые ID, а пользовательские и групповые ID файловой системы. Они используются в этом качестве наряду с дополнительными групповыми идентификаторами. (Действующие идентификаторы по-прежнему, как и в других реализациях UNIX, используются для других, ранее рассмотренных целей.)

Обычно пользовательские и групповые идентификаторы файловой системы имеют те же значения, что и соответствующие действующие идентификаторы (и, таким образом, нередко совпадают с соответствующими реальными идентификаторами). Более того, когда изменяется действующий пользовательский или групповой ID (либо посредством системного вызова, либо из-за выполнения программы с полномочиями setuid или setgid), изменяется, получая такое же значение, и соответствующий идентификатор файловой системы. Поскольку идентификаторы файловой системы следуют таким образом за действующими идентификаторами, это означает, что Linux при проверке привилегий и полномочий фактически ведет себя точно так же, как любая другая реализация UNIX. Лишь когда используются два характерных для Linux системных вызова — setfsuid() и setfsgid(), поведение Linux отличается от поведения других реализаций UNIX, и ID файловой системы отличаются от соответствующих действующих идентификаторов.

Зачем в Linux предоставляются идентификаторы файловой системы и при каких обстоятельствах нам понадобятся разные значения для действующих идентификаторов и идентификаторов файловой системы? Причины главным образом имеют исторические корни. Идентификаторы файловой системы впервые появились в Linux 1.2. В этой версии ядра один процесс мог отправлять сигнал другому, лишь если действующий идентификатор пользователя отправителя совпадал с реальным или действующим идентификатором пользователя целевого процесса. Это повлияло на некоторые программы, например на программу сервера Linux NFS (Network File System — сетевая файловая система), которой нужна была возможность доступа к файлам, как будто у нее есть действующие идентификаторы соответствующих клиентских процессов. Но, если бы NFS-сервер изменял свой действующий идентификатор пользователя, он стал бы уязвим от сигналов непривилегированных пользовательских процессов. Для предотвращения этой возможности были придуманы отдельные пользовательские и групповые ID файловой системы. Оставляя неизмененными свои действующие идентификаторы, но изменяя идентификаторы файловой системы, NFS-сервер может выдавать себя за другого пользователя с целью обращения к файлам без уязвимости от сигналов пользовательских процессов.