Traditional Unix permissions и Access Control Lists

Описание Traditional Unix permissions and ACL с выдержками из мануалов по Multics и Unix первых редакций.

2019-09-04

“The term user is used in two different ways. We often speak of a logged-in person as a user, and, sometimes, use the term to refer to the process which the user is controlling from his terminal. Especially in the context of user control, however, we apply the term user to any member of the set of users (in the first sense) who could log in. In other words, we speak of a user as a registered identity.”
Multics System Administrators Manual January 9, 1973 This manual was written by Thomas H. Van Vleck of the Programming Development Office of the Massachusetts Institute of Technology.

Введение

Насколько я понял из чтения Multics Features, а также и другого материала по системам Multics/Unix, именно в Multics, предшественнике Unix, уже присутствовала древовидная иерархическая файловая система в виде каталогов с файлами (называемыми в Multics сегментами), а также использовались развитые ACLs и режимы доступа в виде rwx-записей для чтения, записи и выполнения. Так что не удивительно, что один из разработчиков Multics, Кен Томпсон (Ken Thompson), перенёс эти идеи в свою новую однопользовательскую операционную систему Unics (в дальнейшем Unix), упростив их до приемлемого уровня. Необходимо вспомнить, что ОС Multics изначально разрабатывалась для работы на серьёзных многопользовательских составных сложных (MULTiplex Information and Computing Service) системах, тогда как Unics писалась в виде баловства для работы на слабом устаревшем компьютере PDP-7, пылившемся в углу.

Впоследствии еще один исследователь лаборатории Bell Labs, Брайан Керниган (Brian Kernighan), как-то в шутку назвал эту систему UNICS (UNiplexed Information and Computing Service — примитивная информационная и вычислительная служба).
Танненбаум. Современные Операционные Системы. 4-е издание.

В мире Unix всё является файлом

Всё в Unix/Linux/POSIX-системе является файлом. Процесс, любое устройство, жёсткий диск, раздел на жёстком диске, etc. Даже каталог, содержащий в себе файлы, является не более чем файлом, в котором перечислены имена жёстких ссылок на другие файлы. Файл определяется номером в inode и не имеет имени. Именем файла является, по минимуму, одна жёсткая ссылка на файл, указанная в файле-каталоге.

Все файлы представлены в файловой системе Операционной Системы (ОС) в виде древовидной структуры, называемой Деревом Каталогов.

  • Одни ветви-каталоги этого дерева представляют собой отображение реальных файлов на внутренних и внешних накопителях. Здесь можно найти файлы, обеспечивающие работу самой ОС; временные файлы, появляющиеся и пропадающие во время работы ОС; файлы созданные пользователями на этом компьютере или принесённые на флэшке.
  • Другие ветви-каталоги отображают подключенные к системе устройства. Вставленная в USB-порт флэшка появится в этом каталоге в виде файла и, через чтение/запись в этот файл, с флэшкой можно производить низкоуровневые операции, например, чтобы восстановить случайно удалённые файлы.
  • Третьи ветви-каталоги являются динамическим представлением оперативной памяти ОС и процессов, работающих в ней, где каждый файл представляет отдельную работающую программу-процесс в ОЗУ. Здесь также можно найти массу информации по работающим процессам и операционной системе; читать и даже менять какие-либо параметры, оперативно влияя на работу процессов и ОС.

UID, GID

Каждый файл в Дереве Каталогов принадлежит определённому пользователю и определённой группе пользователей. Эта информация записывается в область метаданных файла и представлена там полями UID и GID, с числовым значением от 0 до 32767 в ранних Unix, от 0 до 65535 в Linux. Аббревиатура UID и GID означает User ID и Group ID. Подавляющее большинство файлов, созданных на момент установки ОС, имеют UID=0 и GID=0, то есть принадлежат пользователю root и группе root. Видимо по причине того, что установка новой системы происходит из-под рута.

Назначение файлу UID и GID происходит на этапе создания файла. Работающая программа-процесс, принадлежащая какому-либо пользователю и группе, создаёт в файловой системе новый файл и этому файлу, если не указаны иные значения, автоматически назначаются UID и GID создавшего файл процесса. И в соответствии с установками umask, для UID, GID и Other устанавливаются флаги прав доступа (чтение, запись, исполнение).

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

Получение пользователем UID и GID

Системный администратор первых Unix добавлял в систему новых пользователей ручным редактирование файла /etc/passwd (Из седьмой редакции UNIX PROGRAMMER’S MANUAL, январь 1979):

Install new users by editing the password file /etc/passwd (passwd(5)). This procedure should be done once multi-user mode is entered (see init(8)). You’ll have to make a current directory for each new user and change its owner to the newly installed name. Login as each user to make sure the password file is correctly edited. For example:

ed /etc/passwd
$a
joe::10:1::/usr/joe:
w
q
mkdir /usr/joe
chown joe /usr/joe
login joe
ls -la
login root

This will make a new login entry for joe, who should be encouraged to use passwd(1) to give himself a password. His default current directory is /usr/joe which has been created. The delivered password file has the user bin in it to be used as a prototype.

Видно, что пользователю joe назначен UID = 10 и GID = 1. Далее видно, что системному администратору предписывалось создать домашнюю папку нового пользователя и проверить корректность введённых сведений простым входом под логином нового пользователя.

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

После установления связи с Unix, начиналась процедура входа в систему:

  1. Пользователь видит приглашение login:, вводит свой логин и нажимает enter.
  2. getty вызывает login с аргументом — введённым ранее именем пользователя.
  3. login сверяет введённое имя пользователя с информацией из файла /etc/passwd.
  4. Запрашивает пароль, если таковой был установлен.
  5. Меняет текущую директорию на пользовательскую, меняет свой UID и GID на пользовательский и запускает оболочку, обычно, /bin/sh или другую, указанную в /etc/passwd.

Естественно, с этого момента все процессы, запускаемые из оболочки пользователя, наследовали UID и GID пользователя. Отсюда следует, что все файлы, созданные этим пользователем в рамках своего сеанса, наследовали его UID и GID.

Интересно, что “The easiest way to log out is” было “to hang up the phone.” Мы уже давно не вешаем трубку для разрыва соединения и посылки соответствующего сигнала процессам. Трубка, которую можно повесить, исчезла, а сигнал остался.

Сейчас кое-что изменилось. Для добавления нового пользователя в систему используется специальные команды adduser или useradd. Пароли, после червя Морриса, переместились в файл /etc/shadow. Но, в принципе, мало что поменялось.

Флаги прав доступа к файлу

Судя по первой редакции UNIX PROGRAMMER’S MANUAL. K. Thompson, D. M. Ritchie. November 3, 1971, в частности File formats, изначально в Unix для файла предусматривались только следующие флаги доступа:

  • executable (то есть “исполняемый”)
  • set user ID on execution (SETUID)
  • read, write (owner) (“чтение”, “запись” для владельца файла)
  • read, write (non-owner) (“чтение”, “запись” для остальных)

В четвёртой редакции от ноября 1973 года UNIX PROGRAMMER’S MANUAL, Fourth Edition, появились группы пользователей и биты прав доступа к файлу стали более привычными:

  • setuser-ID on execution (SETUID)
  • setgroup-ID on execution (SETGID)
  • read, write, execute (owner)
  • read, write, execute (group)
  • read, write, execute (others)

В шестой редакции упомянут Sticky бит. А в седьмой редакции от января 1979 года UNIX PROGRAMMER’S MANUAL. Seventh Edition, Volume 1. January, 1979 команда chmod стала такой, какой мы знаем её сейчас.

CHMOD(1)    UNIX Programmer’s Manual

Где хранятся UID, GID файла и биты прав доступа

При создании файловой системы, кроме места хранения файлов с данными, выделяется место для хранения метаданных о файлах. Метаданные файла представлены структурой, которая называется inode (индексный узел). В inode хранится информация о файле, например:

  • число жёстких ссылок на файл (имя файла здесь не хранится, так как на этот inode может ссылаться произвольное количество ссылок с различными именами, поэтому если количество ссылок уменьшится до нуля, тогда inode удаляется и блоки файла помечаются свободными);
  • тип файла;
  • время создания файла;
  • время последнего изменения файла;
  • UID — идентификатор владельца файла;
  • GID — идентификатор группы;
  • режим доступа к файлу:
    • ownerModes -- rwx------ (для владельца)
    • groupModes -- ---rwx--- (для группы)
    • otherModes -- ------rwx (для остальных, в случае несовпадения UID/GID вызывающего процесса с UID/GID вызываемого файла)

ACL

В 2002 году в ядро Linux была добавлена поддержка Access Control Lists, которая добавила больше гибкости к управлению доступа к файлам, что приблизило Linux 2000-x к Multics 1960-x. Если ранее доступ к файлу назначался только одному пользователю и одной группе пользователей, то теперь появилась возможность назначать доступ к файлу нескольким пользователям и группам.

Сравнение Traditional Unix Permissions vs ACL

Традиционные права доступа Unix, в отличии от ACL, доступны в ФС любой *nix-системы по умолчанию. Несмотря на то, что Traditional Unix Permissions, по сравнению с ACL, довольно примитивны, их достаточно для работы подавляющего большинства систем. Лично я применял ACL на тех серверах, точнее, на тех томах, к информации на которых необходимо было обеспечить доступ некоторого количества пользователей, объединённых в несколько групп с различными правами доступа. Вдобавок к этому могу вспомнить ещё несколько случаев, где мне понадобилась поддержка ACL. На тысяче других систем, мне ACL не понадобилась.

Для некоторых файловых систем (ext3, ext4), при монтировании необходимо вручную включать поддержку ACL. В других (xfs, btrfs), поддержка ACL включена по умолчанию, но её можно отключить при монтировании.

Для обработки ACL требуются ресурсы системы, поэтому включать поддержку ACL без необходимости не рационально. С другой стороны, не помню, чтобы на томах xfs или btrfs я намеренно применял опцию noacl.

При использовании ACL надо держать в уме, что при некоторых файловых операциях можно потерять эти настройки. Например:

  • Копировать файл с ACL необходимо с опцией cp -p file.txt ~/, но mv file.txt ~/ и без дополнительных опций сохранит ACL.
  • При копировании файла с тома, смонтированного с опцией acl, на том noacl, установленные ACL потеряются.
  • Потерять ACL можно при бэкапировании средствами, не умеющими работать с ACL. Для обхода этих ограничений можно сохранять настройки ACL в отдельный файл с помощью getfacl, с последующим setfacl из файла при операции восстановления их архива.
  • не все утилиты командной строки поддерживают ACL.

Совместная работа Traditional Unix Permissions & ACL

ACL дополняет обычные права доступа, а не замещает их. В дополнении к традиционным правам доступа для владельца, группы и остальные, появляется возможность добавить произвольное число пользователей и групп, которым необходимо добавить права на файл. Также можно установить права по умолчанию на каталог, для автоматической установки некоторого набора прав на копируемые или создаваемые в этом каталоге файлы/папки. Это удобней стандартного umask.

Алгоритм проверки прав пользователя при обращении к файлу

(Перепроверить) Попробую описать алгоритм проверки прав пользователя при обращении к файлу. Процесс, например, bash, в котором я ввожу команду $ cat filename.txt, выполнит системный вызов open() к ядру с целью вывода данных из файла на экран.

При системном вызове будут произведены проверки:

  1. Сравнивается UID процесса с UID файла. При совпадении используются права доступа владельца. Иначе \
  2. GID процесса сравнивается с GID файла. При совпадении используются права доступа группы. Иначе \
  3. Используются права доступа для Остальных.

После определения принадлежности, соответствующие биты режима доступа разрешают, что может сделать процесс с файлом, то есть чтение, запись, выполнение.

Алгоритм проверки доступа к файлу, защищённого ACL описан в man 5 acl и отличается от вышеприведённого только проверкой маски, которая определяет максимальный уровень прав для всех, кроме владельца.

Команды для работы с традиционными правами доступа Unix

ls -al — команда позволяет увидеть установленные права на файлы и каталоги.

chown — команда для изменения владельца:группы файла. Можно изменять отдельно владельца или группу. Интересно, что в Unix, до седьмой редакции включительно, chown предназначалась только для смены владельца. Для смены группы использовалась команда chgrp.

chgrp — редко используемая мной команда для изменения только группы файла.

chmod — изменение прав доступа для владельца, группы файла, а также для остальных. Кроме того, chmod используется для установки SETUID, SETGID И STICKY атрибутов на файлы и каталоги.

umask — команда для установки прав по умолчанию при создании новых файлов и каталогов.

Команды для работы с ACL

getfacl — команда для вывода текущих настроек ACL.

setfacl — команда для установки ACL.