Курс
20. Права на файлы
В теме "О файловых системах" мы познакомились с таким понятием, как инода – в ней хранится всякая информация о файле. С помощью утилиты stat мы можем увидеть часть этой информации и сейчас нас интересует 4 строка, где указаны стандартные UNIX права на этот файл:
1
mkdir temp
2
cd temp
3
touch file
4
stat file
Copied!
Доступы пользователей к файлам можно разделить на 3 категории: либо пользователь является владельцем этого файла и для него есть обозначение u - user; либо пользователь относится к группе, для которой выделены какие-то права на этот файл – обозначение для них – g - group; либо он относится к остальным – все остальные пользователи, которые не подходят под первую и вторую категорию – для них обозначение o - others. Конечно, есть ещё root – он может делать всё что угодно.
Что касается самих прав, то они делятся на три типа: право на чтение файла – обозначается как r — read; право на изменение файла – обозначается как w — write; право на запуск файла - обозначается как x – execute. Право на запуск обычно относится к программам и скриптам.
Теперь, указывая для владельца, группы и остальных права на файл, мы получаем такое значение:
1
rwxrwxrwx
Copied!
Первая тройка rwx это для владельца, вторая для группы, третья для остальных. Такое обозначение говорит, что мы разрешаем и владельцу, и группе и остальным читать файл, изменять его и запускать.
Если же мы хотим владельцу разрешить всё, группе разрешить только читать и запускать, а остальным ничего, получаем:
1
rwxr-x---
Copied!
где отсутствующие права заменены на дефисы.
Кроме stat, можно использовать ls -l или его алиас ll:
1
ll ~
Copied!
где в первом столбце также отображаются права на файлы, в 3 отображается владелец, а в четвёртом группа.
Теперь, как это всё менять. Начнём с владельца. Чтобы поменять владельца нужна команды chown – change owner. Но даже если мы владелец этого файла, без прав суперпользователя мы это сделать не сможем. Потому что если какой-то пользователь создаст файл, а потом укажет, что владельцем файла является другой пользователь, то он сможет подставить другого пользователя. Или, например, использовать выделенное для второго пользователя место в своих целях, когда каждому пользователю выделено сколько-то места на диске. Поэтому, чтобы поменять владельца, нужно использовать sudo:
1
ll file
2
sudo chown user4 file
3
ll file
Copied!
Если мы хотим это сделать для всех файлов в директории и во всех поддиректориях, вы уже знаете, для этого нужно делать рекурсивно:
1
mkdir dir
2
touch dir/file{1..10}
3
sudo chown -R user4 dir
4
ll dir
Copied!
Группу также можно поменять с помощью chown:
1
touch file{1..3}
2
chown -v :group1 file1
Copied!
Здесь ключ -v - verbose - только для вывода информации. Можно сменить разом владельца и группу:
1
sudo chown -v user:user file2
Copied!
А вообще, чтобы менять группу, есть отдельная команда:
1
chgrp group1 file3
Copied!
Как видите, чтобы менять группу, не нужны права root-а, конечно, если вы владелец файла.
Теперь касательно самих прав. Для начала вернём все файлы нашему пользователю, они нам пригодятся:
1
sudo chown -R user dir
2
cd dir
Copied!
Для смены прав используется команда chmod. Допустим, если мы хотим владельцу разрешить читать и изменять файл, пишем:
1
chmod -v u+rw file1
Copied!
Хотим группе запретить изменять файл, пишем:
1
chmod -v g-w file2
Copied!
Хотим всем разрешить запускать файл, пишем:
1
chmod +x file3
Copied!
Группе и остальным запретить читать файл:
1
chmod -v go-r file4
Copied!
+ добавляет, - убавляет. Также можно использовать =, чтобы выставить определённые права, допустим:
1
chmod -v ugo=r file5
Copied!
тогда останутся только права на чтение. chmod тоже работает рекурсивно с ключом -R. В целом по буквам понятно и это несложный способ, но он больше про изменение – кому-то что-то добавить, у кого-то что-то отнять. И если права для всех отличаются – придётся вводить две-три команды, чтобы выставить нужные права.
Часто легче использовать цифровой способ. У каждого права есть своя цифра – у read это 4, у write это 2, у execute это 1. И используя сумму этих чисел можно задать право разом. Допустим, rwx – это 4+2+1 – 7. rwxrwxrwx – это 777. rwxr-x--- - это 750. rwxrw-r-- - это 754. Так и пишем:
1
chmod 765 file6
Copied!
Если же говорить о директориях, вспомните, что директория как лист, в котором указаны имена файлов и их иноды – т.е. жёсткие ссылки:
1
mkdir dir{1..3}
2
touch dir{1..3}/file
3
chmod 400 dir1
4
chmod 600 dir2
5
chmod 700 dir3
6
ll dir*
Copied!
read позволяет видеть только имена файлов – список файлов и директорий — как в dir1.
write позволяет изменять её содержимое - добавлять, переименовывать или удалять файлы – опять же, на самом деле это даже не файлы, а жёсткие ссылки - т.е. «записи на листе». Это как добавлять какие-то записи в лист или стирать их, при этом, не важно, есть у вас права на сами эти файлы или нет:
1
touch dir2/file1
2
touch dir3/file1
Copied!
Как вы видите, несмотря на то, что write позволяет изменять содержимое директории, это не работает без execute. А execute позволяет заходить в эту директорию с помощью cd:
1
cd dir2
2
cd dir3
Copied!
и выполнять операции с содержимым директории. Т.е. без execute write бесполезен.
При этом без execute вы не сможете работать с файлами внутри этой директории, даже если у вас есть права на них:
1
nano dir2/file
Copied!
обратите внимание на ошибку, которая говорит, что данный путь недоступен.
Как я сказал, права write и execute позволяют изменять содержимое директории, допустим, удалять файлы, даже если у нас нет права на сами файлы. Допустим, создадим общую директорию для группы пользователей:
1
sudo mkdir /home/shared
Copied!
пусть у неё будет владелец root, а группа group1:
1
sudo chgrp group1 /home/shared
2
ll -d /home/shared
Copied!
в которую входят user и user4:
1
sudo lid -g group1
Copied!
И выставим права на директорию:
1
sudo chmod 770 /home/shared
Copied!
чтобы у рута и группы были все права, а у остальных никаких.
Значит, пользователь root, user и user4 могут создавать тут файлы:
1
cd /home/shared
2
sudo touch file1
3
sudo -u user4 touch file2
4
touch file3
5
ll
Copied!
Как видите, тут 3 файла и write права у меня есть только на файл user-а, а другие я изменять не могу:
1
touch file1
Copied!
При этом, я могу запросто удалить чужие файлы:
1
rm file2
Copied!
потому что у группы group1 есть права write на эту директорию:
1
ll -d
Copied!
Вы, возможно, подумали – это ж как-то неправильно, нехорошо. Кто-то может случайно или специально удалить чужие файлы. Поэтому есть специальный атрибут – дополнительное право, называемое sticky bit, которое защищает файлы внутри директории. Поставить его можно используя буквенное обозначение:
1
sudo chmod +t /home/shared
Copied!
либо используя цифровое обозначение – у стикибита цифра 1 и она ставится перед правами:
1
sudo chmod 1770 /home/shared
Copied!
После того, как вы поставите sticky bit на директорию, у неё появится буква T после прав:
1
ll -d /home/shared
Copied!
а также ls покажет эту директорию по другому. Так вот, теперь вернём файл пользователя user4:
1
sudo -u user4 touch file2
Copied!
и попытаемся удалить ещё раз:
1
rm file2
Copied!
Как видите, теперь у меня недостаточно прав. Но, как владелец, я могу удалять свои файлы:
1
rm file3
Copied!
А владелец директории, не важно, root он или нет, может удалять все файлы. В системе есть директория /tmp:
1
ll -d /tmp
Copied!
различные программы в процессе работы могут создавать здесь временные файлы. И чтобы другие процессы не удалили эти файлы здесь стоит sticky bit.
Есть ещё пара специальных атрибутов – setuid и setgid. Вкратце – они позволяют запускать файл от имени владельца или группы соответственно. Прекрасный пример – программа passwd:
1
ll /usr/bin/passwd
Copied!
Как видите, вместо x у владельца стоит s – это означает что здесь есть атрибут setuid, плюс ls ярким красным выделяет этот файл. Мы знаем, что passwd меняет пароль пользователя. Пользователь запускает программу passwd, вводит пароль, программа хэширует пароль и записывает в /etc/shadow. Но ведь у обычного пользователя нет прав редактировать файл /etc/shadow. И процесс passwd, запущенный от имени обычного пользователя, просто не смог бы редактировать этот файл – а значит пароль не поменялся бы. Поэтому здесь стоит setuid – когда мы запускаем программу passwd, процесс запускается не от имени нашего пользователя:
1
passwd
2
ps -ef | grep passwd
Copied!
а от имени владельца этого файла - root-а. А вот процесс, запущенный от рута, может редактировать всё что угодно. Если бы владельцем файла являлся user4, то программа запускалась бы от имени пользователя user4. Вот, собственно, для этого и есть setuid.
setgid делает примерно тоже самое, но уже от имени группы этого файла. Задаётся setuid, как и sticky bit – с помощью букв или чисел – u+s для setuid и g+s для setgid:
1
chmod u+s file
2
chmod g+s file
Copied!
Ну и цифрами setuid это 4, setgid это 2 – всё как в правах. Допустим, чтобы поставить setuid и setgid:
1
chmod 6770 file
Copied!
setuid, как и sudo, позволяет повысить привилегии пользователю, а значит это потенциальная брешь в безопасности. Используя программы, где стоит этот атрибут – можно попытаться стать рутом, как я показывал это с sudo. Поэтому использовать setuid вообще нежелательно и он используется только в крайних случаях, как например с passwd.
Также, у setgid есть одно особое применение. Если использовать setgid на директорию, то все файлы, создаваемые в этой директории, будут создаваться от имени группы, владеющей этой директорией. Обычно, когда вы создаёте какой-то файл, то владельцем являетесь вы, а группой – ваша основная группа. Это можно увидеть в той shared директории. Смотрите, user создал файл:
1
touch file4
2
ll file4
Copied!
и у него группа user, потому что это его user private group, о котором мы говорили в прошлый раз. Пользователь user4 не входит в группу и не является пользователем user, а значит он для этого файла относится к others. Я не хочу, чтобы все пользователи в системе видели этот файл, поэтому меняю права на 660:
1
chmod 660 file4
Copied!
но хочу, чтобы у пользователей в группе group1 был доступ к этому файлу:
1
chgrp group1 file4
2
ll file4
Copied!
А так как пользователь user4 тоже в этой группе, он сможет редактировать этот файл.
Но если я создам ещё один файл:
1
touch file5
2
ll file5
Copied!
мне придётся опять менять группу для нового файла. Учитывая, что это общая директория, она специально создана для того, чтобы тут несколько пользователей из одной группы работали с файлами, было бы легче, если б все новые файлы создавались с группой group1. И вот для этого можно использовать setguid:
1
sudo chmod g+s /home/shared
2
ll -d /home/shared
Copied!
Как видите, для группы теперь стоит setgid. И теперь, когда я создаю новый файл:
1
touch file6
2
ll file6
Copied!
он автоматом создаётся с этой группой, а не моей основной группой. Все новые файлы в этой директории, независимо от пользователя, будут принадлежать группе group1, благодаря чему пользователям не придётся постоянно менять группу файла, чтобы все могли работать с этими файлами.
Ещё один момент – как вы, возможно, заметили, все файлы, которые я создаю, имеют одни и те же стандартные права – 664. Дефолтные права на новые файлы задаются утилитой umask. Если просто запустить umask, можно увидеть 0002. Можно ещё запустить:
1
umask -S
Copied!
чтобы было понятнее. И так, первая цифра – для sticky bit, setuid и setgid, остальное для прав. Идея такая – берём максимальное значение – это 777 для директорий и 666 для файлов - и отнимаем те дефолтные права, которые мы хотели бы. Допустим, если мы хотим, чтобы у всех новых файлов были права 664, мы от 666 отнимает 664 – получаем 002. Вот у нас 002 и стоит. Ну и если от 777 отнять 002 получим 775.
Вы скажете – для файлов же максимальные права тоже 777. Но вот просто нельзя создавать новые файлы с правами execute, это большая угроза безопасности. Поэтому для файлов дефолтные максимальные права это 666. А с директориями без execute нормально не поработаешь, поэтому для них 777. Если я хочу, чтобы файлы создавались с правами 660, то я от 666 отнимаю 660 – получаю 006. Но если от 777 отнять 006 получится 771, 1 в конце выглядит бессмысленно, поэтому лучше использовать 007 – тогда права для директорий будут 770, а для файлов 660.
И так, как мне это применить? Я могу это сделать в текущей сессии – написать umask 007, и убедиться, создав новый файл и директорию:
1
touch file8
2
mkdir dir8
3
ll file8
4
ll -d dir8
Copied!
Как видите, теперь у новых файлов для остальных пользователей нет никаких прав. Если же мы хотим, чтобы этот umask действовал для нашего пользователя всегда, мы добавляем строчку:
1
umask 007
Copied!
в ~/.bash_profile или ~/.bashrc. Если помните, login shell у нас все равно считывает ~/.bashrc, а вот если задействуется non login shell, то он не прочтёт bash_profile, поэтому в некоторых случаях лучше писать в ~/.bashrc. Ну и если мы говорим про всех пользователей, то используйте файлы /etc/profile и /etc/bashrc.
Стандартные права делят пользователей на владельца, группу и остальных, что в большинстве случаев достаточно, но иногда всё же нет. Что, если мы хотим дать права на файл всем в группе, кроме двух её участников? Ради этого придётся создавать отдельную группу без этих двух участников. Или, допустим, нужно дать права на 3 группы, а не одну, при этом, дать какому-то пользователю больше прав, какому-то меньше. Для этого можно использовать список контроля доступа – acl. В общем-то речь про две команды:
1
getfacl
2
setfacl
Copied!
1
getfacl file8
Copied!
показывает текущие права на файл. Как видим, владельцу user и группе group1 можно читать и изменять этот файл. User4 тоже в группе group1, но я хочу запретить ему изменять этот файл – для этого я использую утилиту setfacl:
1
setfacl -m u:user4:r-- file8
Copied!
Команда говорит, что нужно модифицировать(-m) права для пользователя user4 и выставить их такими-то. Давайте ещё позволим группе wheel иметь полный доступ на файл:
1
setfacl -m g:wheel:rwx file8
Copied!
После выставления acl ls показывает рядом с правами значок +, а с помощью:
1
getfacl file8
Copied!
узнаем текущие права на файл. Теперь user4 не может редактировать этот файл:
1
sudo -u user4 nano file8
Copied!
Чтобы удалить дополнительные права используем ключ -b:
1
setfacl -b file8
2
getfacl file8
Copied!
Возможно, тему ACL я еще затрону отдельно, но вкратце этого достаточно.
Ну и напоследок, есть интересный пример с файлом /etc/shadow:
1
ll /etc/shadow
Copied!
Как вы видите, на этот файл никаких прав нет, даже у его владельца – root-а. Но при этом мы знаем, что при смене пароля с passwd новый пароль прописывается в этом файле, да и если открыть этот файл с nano – то мы можем читать и изменять этот файл.
Суть в том, что все позволения работы с файлом проверяет ядро операционной системы – оно проверяет, соответствует ли uid пользователя, обращающегося к файлу, с uid-ом владельца файла на файловой системе, есть ли пользователь в группе и т.п. И при некоторых условиях – когда к файлу обращается залогиненный root, в том числе при выполнении команды passwd, ядро просто пропускает проверку и сразу даёт доступ к файлу:
1
man capabilities
2
/DAC_OVERRIDE
Copied!
А вот для каких-нибудь сервисов, которые работают от имени рута, но запущены, допустим, при включении системы, а не вручную, этот файл недоступен для чтения. А при работе root может просто игнорировать все права на файлы.
Подводя итоги, мы с вами разобрали стандартные права – read, write и execute, команды chown, chgrp и chmod для смены прав и владельцев файлов, атрибуты sticky bit, setuid и setgid, права по умолчанию – umask, дополнительные права – acl. Администраторы всегда что-то делают с правами, тема хоть и простая, но может иметь много всяких нюансов, которые можно встреть при работе. Также для лучшего понимания советую почитать статью по ссылке.
Last modified 15d ago
Export as PDF
Copy link