Права доступа к файлам

Материал из LORWiki
Перейти к навигацииПерейти к поиску

Операционная система Linux является наследником UNIX, которая изначально создавалась как многопользовательская операционная система. В связи с этим ОС UNIX обладала простой, но гибкой системой ограничения доступа к файлам, которую унаследовала и ОС Linux. Каждому пользователю Linux стоит иметь представление о правах доступа: проверять или изменять их нередко приходится даже тем, у кого Линукс стоит только на домашнем компьютере, на котором никто, кроме хозяина, не работает, так как для некоторых технических целей, в том числе для защиты от взлома и ошибок, на машине почти всегда будет больше одного и даже больше двух аккаунтов, чтобы можно было запускать разные программы с разными правами.

Как узнать права доступа[править]

В командной строке их можно узнать при помощи команды ls

с параметром -l. Для директорий надо указать параметр -d, иначе ls выведет вместо данных о директории данные о всех файлах в ней. Вот пример:
$ ls -dl Музыка
drwxr-xr-x 14 vasya adm 4096 2011-12-07 23:16 Музыка

Как это читать, написано ниже, в секции «Символьное обозначение».

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

Владелец и группа[править]

Каждому файлу и каталогу в Linux приписан определенный пользователь (который называется владельцем файла) и определенная группа пользователей. При создании файла это чаще всего пользователь, создавший файл, и его первичная группа, но владельца и группу можно поменять. Более того, не обязательно, чтобы владелец файла входил в группу, которой «принадлежит» файл.

Владелец файла имеет право изменить права доступа к нему. Кроме владельца (и суперпользователя) никто не может этого сделать.

У группы файла[1] никаких прав автоматически не появляется, но владелец может присвоить группе права, отличающиеся от прав всех остальных пользователей.

Владельца файла можно сменить с помощью команды chown , а группу — с помощью chgrp

(одновременно сменить группу и владельца можно тоже с помощью chown). Сменить владельца файла обычно может только суперпользователь. Сменить группу с помощью chgrp может и суперпользователь, и обычный пользователь, но только если этот пользователь является владельцем файла и меняет группу на одну из тех, в которые сам входит. Если меняется владелец/группа каталога, изменение не коснется вложенных файлов и каталогов, кроме как если chown/chgrp запущена с параметром -R (recursive).

Права доступа к файлам[править]

Для каждого файла существует три полностью разделенных права на доступ:

  • Право на чтение (read) — право прочитать данные из файла.
  • Право на запись (write) — право изменить данные в файле. Не дает возможности удалить файл (об этом см. ниже), но дает возможность сделать файл пустым.
  • Право на исполнение (execute) — право выполнить файл как программу. Не требует права на чтение, так как файл будет читать только ядро системы, от имени пользователя чтение производиться не будет.

Для каждого файла в файловой системе сохраняется запись, какие из этих прав есть у владельца файла, у группы файла и у всех остальных пользователей (т.е. у каждого, кто не является владельцем и не входит в группу). Конечно, владельца файла нельзя ограничить в правах, так как он может сам их поменять, но сделать это он должен будет эксплицитно, так что владелец может использовать ограничения для защиты от собственных ошибок. Что касается группы файла, то она обычно обладает либо большими правами, чем остальные пользователи, либо равными, хотя технически возможно дать ей меньшие права, чем всем остальным.

Сменить права можно с помощью команды chmod . Для этого нужно быть владельцем файла или суперпользователем.

Исполнение интерпретируемых программ[править]

Право на исполнение работает так, как описано выше, только в том случае если программа нативная[2] и запускается запросом к ядру систему на выполнение файла. Если у пользователя есть право на выполнение, ядро загрузит и выполнит программу, пользователю не требуется право на чтение, хотя программа будет исполняться от его имени.

Если программа является скриптом для интерпретатора и запускается запросом на выполнение файла (например, ./my_program.perl или aclocal — aclocal написана на Perl), то ядро откажется запускать программу без права на исполнение. Если право есть, то ядро проверит первую строчку файла. Если она начинается с символов #! (называется shebang, иногда hashbang), то содержимое этой строчки будет воспринято как команда для запуска интерпретатора, после которой через пробел нужно вставить путь к файлу. Пример:

В начале my_program.perl стоит:
#!/usr/bin/perl -w

Запускаем:
./my_program.perl
Получается:
#!/usr/bin/perl -w ./my_program.perl

Запускаем:
/home/vasya/programs/my_program.perl
Получается:
/usr/bin/perl -w /home/vasya/programs/my_program.perl

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

Если пользователь напрямую вызовет интерпретатор, например, так:

perl ./my_program.perl

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

Права доступа к каталогам[править]

Для каталогов действуют те же самые три права, что и для файлов, только они имеют немного другой смысл:

  • Право на чтение понимается как право получить список имен всех файлов и подкаталогов в каталоге (например, с помощью команды ls

.

  • Право на запись понимается как право создавать и удалять файлы в каталоге.
  • Право на исполнение понимается как право открыть файл или подкаталог в данном каталоге и право сделать каталог текущим (например, с помощью команды cd

). Чтобы открыть файл /a/b/c, нужно иметь право на исполнение корневого каталога (/), каталога /a и каталога /a/b. Но если для какой-нибудь программы каталог /a/b является текущим, и она открывает файл по относительному пути ./c, то ей не требуется право на исполнение каталога /a и корневого каталога. Таким образом, если у пользователя есть право на исполнение каталога, но нет права на его чтение, он может открывать файлы и подкаталоги в нём, если знает их имена.

У каталогов точно так же есть владелец и группа, и у владельца есть те же особые права, что и в случае с файлами.

Удаление файлов и sticky bit[править]

Мы отметили выше, что для создания и удаления файлов в каталоге необходимо иметь разрешение на запись в этот каталог. И все. Для удаления файла никаких прав на доступ к самому файлу не нужно.[3]

Но это не всегда хорошо. Допустим, для директории /tmp, где хранятся временные файлы, часто выставляют разрешение на запись для всех пользователей: все могут создавать там файлы, они все равно временные. Но можно ли на многопользовательской машине разрешить всем пользователям удалять чужие временные файлы? Нельзя, иначе они смогут нарушить работу чужих программ.

Решением является так называемый sticky bit, иногда называемый флагом ограниченного удаления.[4] Если для директории выставлен sticky bit, то файл в ней сможет удалить исключительно владелец этого файла, а не любой, у кого есть разрешение на запись. Выставляется этот флаг тоже с помощью chmod.

Права доступа и суперпользователь[править]

Для суперпользователя (root) права доступа не проверяются. Он может прочитать, изменить и удалить любой файл или каталог, а также сменить владельца, группу или права доступа любого файла или каталога. Единственное ограничение: суперпользователь не может выполнить файл как программу, не имея права на исполнение файла, но он в любом случае может себе это право присвоить тем или иным образом.

Обозначения для прав доступа[править]

Существует два способа представить права доступа для файла в виде, подходящем для чтения людьми: символьный (латинскими буквами и знаком "-") и числовой. Команда ls

выдает права в символьном обозначении. Команда chmod
принимает запись либо в числовом обозначении, либо в своем собственном символьном (в нем указывается, как меняются права, а не какими они должны стать — см. справку по chmod).

Символьное обозначение[править]

Чтобы записать права в символьном обозначении, действуйте по следующему алгоритму:

  1. Если у владельца файла есть право на чтение, запишите "r", иначе "-".
  2. Если у владельца есть право на запись, запишите "w", иначе "-".
  3. Если у владельца есть право на исполнение, запишите "x", иначе "-".
  4. Повторите предыдущие шаги для группы и для всех остальных.
  5. Дальше записываются дополнительные символы, в частности, sticky bit (t).
  6. В результате получится запись из 9 и более символов, которые и обозначают права доступа.

Примеры:

$ ls -l /etc/mtab
-rw-r--r-- 1 root root 704 2011-12-19 21:46 /etc/mtab

Здесь минус в начале обозначает, что /etc/mtab — обычный файл, а не каталог или особый файл. Он принадлежит пользователю root и группе root. У владельца есть право на чтение и запись, у группы и у остальных есть право только на чтение.

$ ls -dl Музыка
drwxr-xr-x 14 vasya adm 4096 2011-12-07 23:16 Музыка

Первый символ d обозначает, что "Музыка" является директорией. Ею владеет пользователь vasya и группа adm. У владельца есть право на чтение, исполнение (так сказать) и запись в каталог, у группы и у остальных есть право на чтение и исполнение.

$ ls -l /dev/tty6
crw------- 1 root root 4, 6 2011-12-19 21:46 /dev/tty6

Символ c обозначает, что файл /dev/tty6 является особым файлом — ссылкой на character device. Он принадлежит пользователю root и группе root, у владельца есть право на чтение и запись, у группы и остальных пользователей вообще нет прав на доступ к файлу.

$ ls -dl /tmp
drwxrwxrwt 21 root root 12288 2011-12-26 17:17 /tmp

Директория /tmp, владелец root, группа root, у владельца, группы и остальных есть права на чтение, запись и исполнение каталога. Установлен sticky bit.

Числовое обозначение[править]

Числовое обозначение прав доступа представляет собой число из четырех восьмеричных цифр. Первая цифра - suid/guid/sticky, вторая цифра - права владельца, третья цифра - права группы, четвертая цифра - права остальных. Описания значений первой цифры ниже в статье, здесь будем считать ее равным 0.

Каждую из второй, третьей и четвертой цифр можно получить по следующему алгоритму:

  1. Возьмите число 0.
  2. Если у субъекта есть право на чтение, прибавьте 4.
  3. Если есть право на запись, прибавьте 2.
  4. Если есть право на исполнение, прибавьте 1.
  5. Получившееся число от 0 до 7 и есть нужная цифра.

Примеры:

  • 0777 = rwxrwxrwx (у всех есть права на запись, чтение и исполнение)
  • 0640 = rw-r----- (у владельца есть права на чтение и запись, у группы — только на чтение, у остальных нет доступа)
  • 0755 = rwxr-xr-x (у владельца есть все права, у группы и остальных — только на чтение и исполнение)

Вот примеры вызова chmod с числовой записью прав:

#Выставить права rwxr-xr-x на файл /usr/local/myprogram
chmod 0755 /usr/local/myprogram
#Выставить права rwxr-xr-x на каталог /usr/local/somedir и все вложенные каталоги и файлы
chmod -R 0755 /usr/local/somedir
#(Но это, обычно, не то, что требуется. См. следующий пример)

Обычно требуется выставить 0755 для каталогов и 0644 для файлов. В символьном виде это делается одной командой

chmod -R u=rwX,go=rX  /usr/local/somedir

(обратите внимение на большую Х, см. man 1 chmod), а в числовом двумя командами:

find /usr/local/somedir -type d -print0 | xargs -0 chmod 0755
find /usr/local/somedir -type f -print0 | xargs -0 chmod 0644

Не будем говорить здесь, как записать sticky bit, SUID/SGID и прочее. Если хотите, прочитайте раздел ниже.

На самом деле[править]

На самом деле числовая запись представляет собой число из 12 бит, записанное в восьмеричной системе счисления. Последние девять бит числа делятся на три группы по три бита, обозначающие, соответственно, права владельца, группы и остальных. Первый бит в каждой группе — чтение, второй — запись, третий — выполнение. Если право есть, соответствующий бит равен единице, если права нет, то нулю.

Первые три бита обозначают дополнительные флаги: SUID, SGID, Sticky bit

Примеры:

  • rwxr-xr-x = 000.111.101.101 (двоичн., точки просто для читаемости) = 0755 (восьм.)
  • r-------- = 000.100.000.000 = 0400
  • rwxrwxrwt = 001.111.111.111 = 1777
  • rwxr-sr-t = 011.111.101.101 = 3755

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

Как хранятся права доступа[править]

Права доступа и даные о владельце и группе не являются частью содержимого файла, а являются особой записью в файловой системе. Итак, права доступа действуют только для тех файлов, которые находятся на разделах с совместимой ФС, например, ext, ext2, ext3 или ext4, ReiserFS, ZFS и других системах, которые создавались для UNIX/Linux. Файловая система FAT (в т.ч. FAT32), например, прав доступа не поддерживает. NTFS тоже (там своя, несовместимая с UNIX система прав доступа). Ну, конечно, драйвер файловой системы может как-либо сымитировать поддержку прав.

Данные о владельце и группе хранятся в виде их числовых идентификаторов (UID — user id и GID — group id). Поэтому если на компьютере несколько инсталляций Линукса с разными конфигурациями или речь идет о переносном жестком диске или флешке, то может получиться, что на разных конфигурациях один UID/GID соответствует разным пользователя. Только UID суперпользователя всегда 0.

Копирование, перемещение и переименование файлов[править]

При копировании или перемещении файла происходят следующие операции:[5]

  1. Создается новый файл, владельцем которого становится пользователь, производящий копирование, а группой, скорее всего, его первичная группа. Нужно право на запись в каталог, в котором будет создан файл.
  2. Считывается содержимое исходного файла и переписывается в новый. Нужно право на чтение исходного файла.
  3. Если производится перемещение, а не копирование, то исходный файл удаляется. Нужно иметь право на запись в каталог, где он находится, и быть владельцем файла, если на каталоге стоит sticky bit.

Переименование файла можно рассматривать как частный случай перемещения.

Права доступа будут выставлены по умолчанию.

Чтобы скопировать файл с сохранением прав, нужно, чтобы копирующая программа этим озаботилась. Команду cp , например, для этого нужно запустить с параметром '--preserve=mode', а чтобы сохранить данные о владельце и группе — '--preserve=ownership' (чтобы сохранить и то, и другое, запустить с параметром '--preserve=mode,ownership' или с параметром '-p', который аналогичен '--preserve=mode,ownership,timestamps'). Права на файл поменять можно без, так как вы будете владельцем нового файла, а вот чтобы сохранить данные о группе и владельце, нужно иметь право поменять группу и владельца.

Передача файлов по сети[править]

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

Единственный популярный формат архивов на сегодняшний день, сохраняющий права доступа UNIX, — это архив tar . Он является чисто архивным форматом, т.е. никак не сжимает файлы. Поэтому архивы tar часто запаковывают еще в один архив, который сжимает данные, например, bz2 или gzip. Итак, для передачи по сети с сохранением прав или, если нужно, для упаковки бэкапов пользуйтесь tar'ом.

Существуют специальные протоколы передачи данных с сохранением данных о владельце и правах, например, rsync.

Важное замечание о применимости материала статьи[править]

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

SUID/SGID[править]

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

Примером может служить программа passwd, служащая для изменения паролей пользователей. В большинстве сетей со многими пользователями администраторы хотели бы, чтобы каждый пользователь мог самостоятельно поменять собственный пароль. Но пароли хранятся в файлах, которые может отредактировать (или даже прочитать) только root, а дать всем пользователям пароль от root'а, конечно, нельзя. Поэтому пользователям дается разрешение запускать программу passwd с теми же правами, что есть у суперпользователя, но passwd сама может определить, запустил ее настоящий root или нет. Если нет, то она воспользуется правами root для редактирования файлов с паролями, но не позволит менять никакого пароля, кроме пароля запустившего ее пользователя.

Такое специальное разрешение выражается в виде права SUID (set user id) или SGID (set group id). Если файлу приписано разрешение SUID, то при запуске его как программы он будет запускаться с правами своего владельца, а не запускающего пользователя (но у запускающего пользователя должно быть право на исполнение). Если файлу приписано разрешение SGID, то он будет запускаться с правами своей группы.

Выражение SUID/SGID в выдаче ls таково. Если у файла есть SUID, то вместо "x" в перечислении прав его владельца будет стоять "S" (если у владельца нет прав на исполнение) или "s" (если есть). Пример:

$ ls -l $ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 37140 2011-02-14 23:11 /usr/bin/passwd

Здесь у владельца есть право на чтение, запись и исполнение, а у остальных — на чтение и исполнение. Но на файл распространяется право SUID, так что при запуске файла программа в нем автоматически получит права своего владельца — пользователя root.

Если на файл распространяется право SGID, то той же самой замене подвергнется "x" в правах группы. Пример:

$ ls -l testfile
-rwsr-Sr-- 1 vasya adm 0 2011-12-16 18:06 testfile

При запуске файла testfile он получит права пользователя vasya и группы adm. Однако никто, кроме владельца, не может его запустить. SUID (в отличие от SGID) здесь большого смысла не имеет, пример чисто гипотетический.

Если файл вообще не является программой или если никто не имеет права выполнить файл как программу, то исключая особые ситуации право SUID/SGID большого смысла не имеет. Права SUID/SGID могут распространяться и на директории, но тогда они имеют другой смысл.

Еще раз уточним, чтобы все читатели точно поняли: право SUID указывается в числе прав владельца, а право SGID — в числе прав группы, но это только обозначение. Права эти срабатывают, когда программа запускается, кто бы ее ни запустил. Запускающему пользователю нужно только право на исполнение.

Больше мы в этой статье ничего о SUID/SGID говорить не будем, это тема для отдельной статьи. Здесь мы упоминаем эти права только для того, чтобы читатели о них знали и не пугались, если вдруг в выдаче ls увидят "s" или "S" вместо "x".

Access Control Lists[править]

Хотя стандартная система прав доступа является достаточно гибкой, иногда и ее бывает недостаточно. В некоторых конфигурациях бывает трудно распределить права доступа, не имея возможности указать различные права для нескольких пользователей или групп пользователей, а не только для одного владельца и одной группы. В этом случае можно использовать механизм, называемый Access Control Lists (списки контроля доступа). Механизм ACL входит в стандарт POSIX и используется не только в Linux. Отметим, что подобный механизм используется по умолчанию в системе Windows, но он не полностью соответствует POSIX ACL

Мы не будем подробно говорить об этом механизме, так как он используется далеко не везде, и это тема для отдельной статьи. Мы упоминаем его только для того, чтобы читатели знали о существовании этой расширенной системы прав. Если интересно, можно почитать man 5 acl (должен быть установлен соотв. пакет, обычно называется acl).

На всякий случай отметим также, что если доступ к файлу контролируется ACL, то после стандартных прав доступа ls выведет знак "+" (например, "drwxr-x---+"). Стандартные права выводятся потому, что ACL не полностью их отменяет. Сам же список контроля доступа можно получить и изменить только с помощью отдельных утилит (обычно getfacl и setfacl).

Опция acl команды mount - про этот механизм.

Extended attributes[править]

Это расширенные атрибуты, которые представляют собой строковую пару name:value, ассоциированную с файлом или директорией. (Слегка похоже на окружение (environment), ассоциированный с процессом). Подробнее: man 5 attr .

Опция user_xattr команды mount - про эти аттрибуты.

Attributes on linux file system[править]

Кроме того, на файл могут влиять специальные атрибуты Linux. В отличии от ACL, входящих в стандарт POSIX, это специфичный для Linux механизм. Аттрибутов достаточно много, самые интересные: 'a' - append-only: в файл можно только дописывать данные, в каталоге можно создавать файлы, но не удалять уже созданные; 'i' - immutable - файл нельзя изменять/удалять. Расширенные атрибуты устанавливаются коммандой chattr, посмотреть их можно с помощью команды lsattr.

Примечания[править]

  1. Словосочетание «группа файла» звучит коряво, но употребляется.
  2. Нативной (от англ. native) называется программа, которая полностью скомпилирована в машинный код, то есть набор инструкций для процессора, и работает непосредственно под управлением операционной системы. Не все программы, работающие под Linux, нативные. Например, программы на Perl, Python или Java являются интерпретируемыми: они представляют собой набор инструкций для программы-интерпретатора, а она уже формирует инструкции для процессора по ходу выполнения программы. Программы для Windows, запускаемые через Wine, тоже не являются нативными для Linux: они запускаются не под управлением системы, а под управлением Wine. Ненативная программа не может запуститься без помощи какой-либо нативной программы.
  3. Почему? Потому что создавая или удаляя файл, вы делаете запись в каталоге, что в нем теперь находится (или больше не находится) такой-то файл. В Linux при помощи т.н. "жестких ссылок" (см. команду ln ) можно вообще сделать так, что один и тот же файл будет занесен в разные каталоги под разными именами. Физическое удаление файла происходит после того, как в файловой системе не останется ни одной ссылки на этот файл.
  4. На некоторых других UNIX-подобных системах этот флаг имел другое значение, но в Линуксе только это: ограничение на удаление файлов в директории. Почему bit? См. раздел о том, как на самом деле представлены права доступа.
  5. Список приведен только для понимания того, какие права нужны, и не описывает точно, какие именно операции происходят на самом деле.