Введение в POSIX'ивизм

       

Право на файл


В начале этого параграфа были вскользь упомянуты прочие атрибуты файла - принадлежности, доступа и режима. Это - очень важные понятия любой Unix-системы (как, впрочем, и любой иной системы, претендующей на звание всамделишней). И - одно из тех понятий, которые (знаю по собственному опыту) психологически трудны для понимания пользователя, пришедшего из мира DOS/Windows 3.X/9X/ME.

Впрочем, смысл атрибутов принадлежности интуитивно понятен: каждый файл в системе, а) имеет своего хозяина, б) приписан к какой-либо группе пользователей, и в) находится в неких отношениях со всеми прочими. В качестве хозяина файла обычно выступает его создатель. Точнее, хозяин процесса, этот файл создавшего. А еще точнее - пользователь, идентификатор которого был унаследован процессом, создавшим файл, в качестве эффективного UID. То есть если процесс этот по каким-либо причинам получил привилегии root-оператора, то и созданный им файл будет иметь своим хозяином его, а не пользователя, на самом деле процесс запустившего.

Далее, каждый файл приписывается по умолчанию к основной группе пользователя - хозяина файла, однако такое положение не является непременным. И именно отнесение файла к некоей группе широко используется для разграничения доступа, организации коллективной работы и прочих задач администрирования. Ну и все "прочие" также имеют некие права на файл - и не обязательно более узкие, чем члены его группы (или даже хозяин).

С атрибутами доступа дело несколько сложнее. Основных из них также три: атрибут чтения, изменения, исполнения, причем смысл их различается для каталогов и всех прочих файлов. Начнем со вторых.

Право на чтение (read) файла - это возможность просмотреть его командой less (естественно, только для обычного файла, файлы устройств, сокеты или каналы просмотреть таким образом нельзя, а попытка просмотра символической ссылки вызовет ее файл-источник), открыть в текстовом редакторе или какой-либо прикладной программе. Атрибут изменения (write) также понятен - он дает право изменить содержимое файла, вплоть до полного удаления (содержимого, но не файла! - никакие атрибуты файла не имеют отношения к возможности его удаления).
А атрибут исполнения (execute) означает возможность запустить откомпилированный бинарник или скрипт: именно присвоение этого атрибута волшебным образом превращает набранную в текстовом редакторе последовательность команд в сценарий оболочки.

Для каталога же атрибут чтения позволяет просмотреть командой ls (или каким бы то ни было иным способом) его содержимое. А по предыдущему параграфу мы помним, что все содержимое каталога - это просто список имен входящих в него файлов. И потому право на изменение каталога - это возможность этот самый список модифицировать. Например, удалить из него какое-либо имя, или создать новое (путем перемещения ли, копирования файла, или записи некоторых данных из программы). А поскольку больше имя файла нигде не фигурирует, лишившись его, файл становится недоступным для системы - то есть удаленным. При этом прошу обратить внимание: никаких особенных прав на сам файл не требуется, в общем случае можно удалить файл, не имея на него прав не только изменения, но даже чтения, достаточно обладать правом на изменение каталога. При этом, зная точно имя удаляемого файла и полный путь к нему, можно не иметь и права на чтение каталога, к которому файл приписан.

Наконец, атрибут исполнения для каталога дает право входить в него командой cd. Всего-то навсего, но без этого права какие-либо операции внутри каталога становятся затруднительными. Хотя и не невозможными: по аналогии с правом чтения легко догадаться, что файл из каталога можно удалить, не входя в него - достаточно знать имя файла и путь к нему.

Атрибуты доступа сцеплены с атрибутами принадлежности. То есть для каждой категории обладателей файла (даже прочих - они тоже в определенной мере обладатели файла) может быть установлено свое (и теоретически любое) сочетание прав на доступ к нему. Так, юзер может иметь право на чтение, изменение и (если это оправдано по смыслу) исполнение файла или каталога (очевидно, что право исполнения TIFF-файла ни малейшего смысла не имеет), группа и прочие - иметь права чтения и, если нужно, исполнения: это схема, по которой обычно по умолчанию распределяются атрибуты вновь создаваемого файла.



Можно запретить любой доступ к своим файлам для прочих, оставив их только для группы особо избранных товарищей. А можно, напротив, запретить право чтения и исполнения для группы, сохранив их для прочих: в этом случае группа товарищей превращается в группу, скажем так, не-товарищей. Ведь права доступа проверяются при обращении к нему в строгом порядке: юзер -> группа -> прочие. И потому, если чтение файла запрещено для членов группы, к которой файл приписан, их попытки ознакомиться с ним будут отвергнуты, тогда как все прочие прочтут файл беспрепятственно...

Кроме атрибутов принадлежности и доступа, которые присваиваются файлу (или, напротив, отнимаются у него) в обязательном порядке, он может иметь и три дополнительных атрибута, называемых иногда атрибутами режима. Для названия их удобочитаемого русского перевода не существует. А на вражьей мове это атрибут SUID (Set User IDentificator), иногда именуемый битом "суидности" (не путать с суицидом), SGID (Set Group IDentificator) и sticky (что можно трактовать как атрибут "липкости" или "сохранности"). Первые два имеют смысл только для исполняемых обычных файлов, последний - в основном для каталогов.



Атрибут "суидности" обеспечивает механизм, благодаря которому пользователю удается изменить свой пароль без помощи администратора. А именно: файл, которому он присвоен, при запуске на выполнение (именно потому он имеет смысл только для файлов с атрибутом исполнения) порождает процесс, наследующий эффективный UID не юзера, его запустившего, а хозяина файла, правами доступа которого и определяются привилегии процесса. А поскольку хозяином подавляющего большинства файлов за пределами домашних каталогов является root, именно его-то права процессу обычно и достаются. Смысл атрибута SGID аналогичен, только тут процессом наследуется не эффективный UID пользователя, а эффективный GID группы, к которой приписан помеченный файл.

Атрибут sticky присваивается обычно каталогам, и влечет за собой невозможность удаления из него файла кем бы то ни было, за исключением владельца файла - ведь в обычном случае для этого достаточно иметь права доступа не к файлу, а к каталогу.


Установка его целесообразна для каталогов, хранящих всякого рода временные данные (типа /tmp и некоторых подкаталогов ветви /var), права доступа к которым по умолчанию (и по смыслу) допускают их модификацию всеми пользователями. Однако, если право на запись временных файлов юзер вряд ли сможет использовать во вред, то удаление из таких каталогов чужих файлов вряд ли будет приветствоваться их хозяином. И именно для предотвращения такой ситуации предназначен атрибут sticky.

Сведения обо всех атрибутах файла можно получить посредством команды ls в "длинном" формате (с опцией -l). Или - от какого-либо файлового менеджера. Хотя, на мой взгляд, команда ls ничуть не менее информативна и выразительна. Что я и попытаюсь продемонстрировать в ближайшей интермедии.

В обычном выводе команды ls -l имена пользователя и группы находятся в третьем и четвертом полях, а атрибуты доступа объединены в первом. Он имеет вид

-rwxrwxrwx

что расшифровывается следующим образом. Первая позиция последовательности - тип файла (символ дефиса, -, в примере означает, что мы имеем дело с обычным файлом, для каталога там был бы символ d - от directory, для символьного устройства - символ c, для блочного - символ b). Следующие три символа определяют атрибуты доступа для хозяина файла: r - чтение, w - изменение, x - исполнение. Две последние тройки символов - суть то же самое, но для группы и прочих, соответственно. То есть в данном примере фигурирует исполняемый файл, открытый на чтение, запись и запуск для всех. Если же у кого-либо какое-то право отнято - в соответствующей позиции мы увидим символ дефиса. Так, атрибуты нового текстового файла по описанной выше умолчальной схеме будут выглядеть как

-rw-r--r--

Если файлу приписан атрибут суидности, в тройке владельца место символа x займет символ s, а при наличии атрибута SGID то же s окажется на месте x в тройке группы. Атрибут "липкости" маркируется символом t в последней позиции (вместо x для "прочих"). То есть вывод команды



ls -l /usr/bin/passwd

будет выглядеть так:

-rwsr-xr-x

а прочие варианты предлагается домыслить самостоятельно.

Выше при описании прав доступа использована т.н. символьная нотация, простая и мнемонически понятная (r - от read, o - от other, и т.д.). Однако наряду с ней существует (и активно используется) нотация цифровая, где права доступа обозначаются числами типа 644. Поначалу она кажется загадочной. Однако при ближайшем рассмотрении - ничего подобного. Первая цифра соответствует правам хозяина файла, вторая - правам членов группы, третья - правам разных там прочих, как и при символьной нотации. А сама цифра представляет собой простую арифметическую сумму прав, также выраженных численно - только в двоичной системе счисления, трансформированной в восьмеричную для компактности. А именно: наличию любого права соответствует двоичная единица, отсутствию - двоичный ноль. То есть символьной форме rwxrwxrwx будет соответствовать двоичная 111 111 111, что в восьмеричном пересчете и даст "число юзверя" - 777 (полный доступ для всех атрибутов принадлежности). Образуется она из суммы прав чтения (восьмеричное 4), изменения (восьмеричное 2) и исполнения (восьмеричная 1) в трех позициях. Из чего можно догадаться, что число 000, напротив, означает отсутствие прав на любые действия у кого бы то ни было.

Арифметические вычисления того, какие числа соответствуют каким соотношениям прав, я предоставляю читателю (слаб стал в устном счете с тех пор, как бросил преферанс). Скажу только, что "умолчальная" атрибутика новорожденного файла rw-r--r-- в численной нотации будет выглядеть как 644.

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

Догадались, почему в первой позиции стандартной совокупности прав фигурирует 6, хотя в аргументе команды umask видим 0? Правильно, потому, что ни один создаваемый непосредственно пользователем файл не рождается как исполняемый: этот атрибут должен быть присвоен ему принудительно.А от рождения право на исполнение обретают только двоичные файлы, создаваемые компилятором (например, gcc).


Содержание раздела