惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
Recent Commits to openclaw:main
Recent Commits to openclaw:main
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
罗磊的独立博客
V
Visual Studio Blog
爱范儿
爱范儿
H
Help Net Security
J
Java Code Geeks
I
InfoQ
Recent Announcements
Recent Announcements
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Recorded Future
Recorded Future
Jina AI
Jina AI
Microsoft Security Blog
Microsoft Security Blog
WordPress大学
WordPress大学
GbyAI
GbyAI
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Y
Y Combinator Blog
Google DeepMind News
Google DeepMind News
Scott Helme
Scott Helme
S
SegmentFault 最新的问题
S
Securelist
L
LINUX DO - 热门话题
Cyberwarzone
Cyberwarzone
C
Cisco Blogs
Simon Willison's Weblog
Simon Willison's Weblog
G
Google Developers Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 叶小钗
T
The Blog of Author Tim Ferriss
博客园_首页
B
Blog
F
Fortinet All Blogs
AWS News Blog
AWS News Blog
V
Vulnerabilities – Threatpost
S
Secure Thoughts
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Forbes - Security
Forbes - Security
S
Security @ Cisco Blogs
T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
Schneier on Security
Project Zero
Project Zero
Martin Fowler
Martin Fowler
C
Cybersecurity and Infrastructure Security Agency CISA
N
Netflix TechBlog - Medium
N
News and Events Feed by Topic

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Linux: Права доступа
opensophy · 2026-05-13 · via Все публикации подряд на Хабре

Средний

12 мин

14K

Введение

Продолжаем серию рубрики Linux. В прошлой серии разобрали пользователей и группы – UID, GID, /etc/passwd. Теперь разберём что ядро делает с этими числами когда процесс пытается открыть файл или войти в директорию. Про права доступа легко выучить команды – chmod 755, chown user file – но не понимать что происходит под капотом. Тогда начинаются странные ситуации: «я же владелец, почему Permission denied?». Цель этой статьи – кратко но в достаточной форме рассказать про права доступа.

Вся статья построена на практике: каждый раздел можно пройти руками. Для большинства примеров достаточно обычного пользователя, для части нужен sudo. Где нужен – отмечено явно. Серия в основном под Ubuntu/Debian.

В конце статьи будет бонус который даст вам возможность изучить права доступа в Linux ещё доступнее и возможно проще.

Обновление статьи: 2026-05-14

1. Что такое права доступа и зачем они нужны

Linux – многопользовательская система. На одной машине одновременно работают процессы от разных пользователей: nginx читает файлы сайта, postgres работает со своими данными, разработчик ivan пишет код в своём каталоге. Без изоляции любой мог бы читать чужие ключи SSH, удалять чужие файлы, подменять конфиги сервисов.

Права доступа – механизм изоляции. Каждый файловый объект несёт метаданные: кто владелец, какая группа, кто что может делать. Метаданные хранятся в inode – структуре файловой системы которая описывает файл. Важно понимать: содержимое файла и его метаданные (включая права) хранятся раздельно. Когда вы делаете ls -la – вы читаете именно inode, а не сам файл.

Посмотрим на конкретный пример. Файл /etc/shadow хранит хеши паролей всех пользователей:

ls -la /etc/shadow
-rw-r----- 1 root shadow 1478 апр 16 12:03 /etc/shadow

Права гарантируют что читать его может только root и члены группы shadow. Обычный пользователь – нет. Разберём эту строку полностью, слева направо.

Часть

Что означает

-rw-r-----

тип файла и биты прав (разберём ниже)

1

количество жёстких ссылок на файл

root

владелец файла

shadow

группа-владелец файла

1478

размер в байтах

апр 16 12:03

дата последнего изменения

/etc/shadow

путь к файлу

2. Модель UGO – три класса доступа

Стандартная модель Linux делит всех на три класса относительно конкретного файла.

U – User (владелец). Один конкретный пользователь. Когда создаёте файл – автоматически становитесь его владельцем. G – Group (группа). Одна конкретная группа. По умолчанию – primary group пользователя который создал файл. O – Others (остальные). Все кто не попал в первые два класса.

Для каждого из трёх классов устанавливается свой набор прав. Вот как это выглядит в выводе ls -la:

veil@veilos:~$ ls -la
drwxr-x---+ 19 veil veil 4096 апр 24 13:14 .

Первый символ – тип файла:

Символ

Тип

-

обычный файл

d

директория

l

символическая ссылка

b

блочное устройство

c

символьное устройство

p

именованный канал (pipe)

s

сокет

Следующие 9 символов – три блока по три бита для U, G и O. Вернёмся к /etc/shadow:

-  rw-  r--  ---
   U      G    O

U=rw- → владелец (root) читает и пишет
G=r-- → группа (shadow) только читает
O=--- → все остальные – никаких прав

Каждый файл имеет ровно одного владельца и ровно одну группу – не двух, не список. Это ограничение стандартной модели UGO. Для более гибкого управления существуют ACL – разберём их в разделе 9.

3. Биты rwx – что они означают

Три бита в каждом блоке: r – read, w – write, x – execute. Установлен бит – операция разрешена. Сброшен (дефис) – запрещена. Смысл битов различается для файлов и директорий.

Для файлов

Бит

Что разрешает

r

читать содержимое (cat, less, cp)

w

изменять содержимое (редакторы, echo >>)

x

запускать как программу

Для директорий

Здесь важно не путать – директория это тоже файл, просто специального типа. Биты работают иначе.

Бит

Что разрешает

r

читать список файлов внутри (ls)

w

создавать и удалять файлы внутри

x

входить (cd) и обращаться к файлам по имени

На директориях бит х (проход) нужен, чтобы в дальнейшем войти через cd или обратиться к файлу по пути. r без x будет парадоксом, где список файлов через ls будет видно а открыть нельзя, поэтому r и x на директориях почти во многих случаях ставятся вместе.

4. Числовое и символьное представление

Существует два способа записывать права, и оба используются в реальной работе. Разберём оба.

Числовое (восьмеричное)

Каждый бит имеет числовое значение:

r = 4
w = 2
x = 1
- = 0

Чтобы получить число для класса – складываем биты:

rwx = 4+2+1 = 7
rw- = 4+2+0 = 6
r-x = 4+0+1 = 5
r-- = 4+0+0 = 4
--- = 0+0+0 = 0

Итоговые права – три цифры, по одной для U, G, O:

755 → rwx r-x r-x
644 → rw- r-- r--
700 → rwx --- ---
600 → rw- --- ---

777 означает что любой пользователь на системе может читать, изменять и запускать файл. На сервере где работают несколько пользователей – это дыра. Особенно опасно если это скрипт который запускается по cron от root – любой сможет подменить его содержимое. Используйте с осторожностью.

Шпаргалка по типовым комбинациям:

Права

Символьно

Когда применять

644

rw-r--r--

Обычные файлы, конфиги

755

rwxr-xr-x

Исполняемые файлы, директории

600

rw-------

Приватные ключи SSH, секреты

640

rw-r-----

Конфиги с паролями – группа читает, others нет

700

rwx------

Домашняя директория сервисного пользователя

750

rwxr-x---

Директории сервисов

777

rwxrwxrwx

Почти никогда – проблема безопасности

Символьное

Удобно когда нужно добавить или убрать один бит не трогая остальные – не надо держать в голове итоговое число. Синтаксис: [кто][операция][что].

Кто: u – владелец, g – группа, o – остальные, a – все сразу (u+g+o).

Операция: + – добавить, - – убрать, = – установить точно (остальные биты сбросятся).

chmod u+x script.sh        # добавить x владельцу
chmod g-w file.txt         # убрать w у группы
chmod o=r file.txt         # ровно r для others, остальное сбрасывается
chmod a+x file.sh          # добавить x всем
chmod u+x,g-w file.txt     # несколько операций через запятую
chmod go-rwx secret.txt    # убрать всё у группы и others

Когда что удобнее: числовой – когда знаешь точное итоговое состояние. Символьный – когда хочешь изменить один бит не затрагивая остальные.

Особый случай: +X (заглавная)

+x (строчная) ставит бит execute на всё подряд – и на файлы, и на директории. +X (заглавная) её можно назвать умнее: она ставит execute только там, где это имеет смысл – на директории всегда, на файлы только если у кого-то из классов уже стоит x.

chmod -R +x dir/     # x поставится на ВСЕ файлы внутри, включая .txt, .jpg
chmod -R +X dir/     # x поставится только на директории и уже исполняемые файлы

Пример где можно применить: для рекурсивной установки прав.(Это безопаснее и правильнее чем потом чистить лишние биты через find.)

5. chmod – изменение прав

chmod (от change mode) – команда для изменения прав доступа.

# Числовым способом
chmod 644 file.txt
chmod 755 /var/www/html
chmod 600 ~/.ssh/id_rsa

# Символьным способом
chmod u+x script.sh
chmod g+w shared/
chmod o-rwx secret.txt

# Рекурсивно для всего дерева каталогов
chmod -R 750 /var/lib/app

Здесь есть типичная ловушка при настройке веб-серверов. Многие делают так:

chmod -R 755 /var/www/html

Эта команда поставит 755 на абсолютно все объекты – и директории, и файлы. Для директорий 755 нормально, им нужен x чтобы в них можно было входить. Но для файлов это означает что .html, .css, .jpg становятся исполняемыми – а этого не должно быть. Правильный способ – разделить файлы и директории:

# Директориям нужен x чтобы в них можно было входить
find /var/www/html -type d -exec chmod 755 {} \;

# Файлам x не нужен
find /var/www/html -type f -exec chmod 644 {} \;

После этого права будут корректные: директории – 755, файлы – 644, без лишнего x. Главное: не ставить права «на глаз» – всегда думайте кому реально нужен доступ.

6. chown и chgrp – смена владельца и группы

chown (от change owner) меняет владельца файла, группу, или оба сразу. chgrp (от change group) меняет только группу – по сути то же что chown :group, просто отдельная команда.

# Сменить только владельца
chown ivan file.txt

# Сменить только группу
chgrp developers file.txt

# Сменить и владельца и группу сразу
chown ivan:developers file.txt

# Рекурсивно
chown -R www-data:www-data /var/www/html

Обычный пользователь может поменять группу файла только на одну из своих собственных групп. Поменять владельца на другого пользователя – только root. Без этого ограничения можно было бы «подарить» вредоносный файл с SUID другому пользователю – и это стало бы простым способом эскалации привилегий.

7. Как ядро принимает решение о доступе

Это самый важный раздел статьи. Команды можно выучить, но без понимания алгоритма поведение системы будет казаться непредсказуемым. Особенно когда видишь Permission denied там где не ожидаешь.

7.1 Real vs Effective UID

Когда пользователь запускает программу, у процесса есть несколько идентификаторов. RUID (Real UID) – кто фактически запустил процесс. Не меняется в течение жизни процесса. EUID (Effective UID) – от чьего имени процесс работает прямо сейчас. Именно его проверяет ядро при обращении к файлу.

В большинстве случаев RUID == EUID. Но это различие становится важным при SUID – разберём в следующем разделе.

cat /proc/self/status | grep Uid
Uid:    1000    1000    1000    1000

Четыре числа в строке: Real UID, Effective UID, Saved UID (нужен для временного переключения прав), Filesystem UID (используется при проверке доступа к файлам – в большинстве случаев совпадает с EUID). Для понимания прав доступа ключевой – второй, EUID.

7.2 Алгоритм проверки прав

Когда процесс обращается к файлу, ядро проверяет права строго по порядку и останавливается на первом совпадении:

  1. Если EUID = 0 (root) → доступ почти всегда разрешён

  2. Если EUID совпадает с владельцем файла → используются права владельца

  3. Если группа процесса (EGID или дополнительные группы) совпадает с группой файла → используются права группы

  4. Во всех остальных случаях → используются права для остальных (others)

Система не комбинирует права – она берёт только один подходящий вариант и на этом заканчивает проверку.

7.3 Права не суммируются

Частая ловушка с которой сталкиваются многие. Допустим есть файл:

ls -la secret.txt
# ----rwx--- 1 ivan developers secret.txt
#  U: ---    G: rwx    O: ---

Пользователь ivan является владельцем и одновременно входит в группу developers:

id ivan
# uid=1001(ivan) gid=1001(ivan) groups=1001(ivan),1005(developers)

Но если ivan попробует прочитать файл – получит Permission denied. Почему? Ядро проверило: EUID процесса совпадает с UID файла – совпадение на шаге 2. Применило биты owner – ---. Остановилось. Биты group rwx даже не рассматривались. ivan является владельцем, но у владельца нет прав. Группа имеет полный доступ – но до неё проверка не дошла.

Решение – дать владельцу права явно:

chmod u+r secret.txt
# или явно задать нужные права
chmod 740 secret.txt    # u=rwx, g=r--, o=---

Уточнение: пример выше демонстрирует механику проверки прав ядром, а не реальную схему работы с группами. Ситуация ----rwx--- на файле, где владелец намеренно без прав, надуманная и в реальной практике почти не встречается.

Зачем тогда нужны группы?

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

Примерный сценарий: команда разработчиков работает с общим проектом.

# Создать группу и добавить пользователей
groupadd developers
usermod -aG developers maria
usermod -aG developers sergei
 
# Назначить группу на директорию проекта
chown -R ivan:developers /project
chmod -R 750 /project

Теперь ivan – владелец (rwx), все члены группы developers – читают и входят (r-x), остальные – ничего. Когда нужно добавить нового разработчика – просто usermod -aG developers newuser, и он сразу получает нужный доступ. Группы становятся особенно полезными в связке с SGID на директории (раздел 8): новые файлы автоматически наследуют группу директории, и всем членам группы не нужно думать о правах при создании файлов.

7.4 root и права

root (EUID=0) обходит проверку UGO для большинства операций – может читать любой файл, писать в любой файл независимо от прав. Но есть одно исключение: бит execute. Даже root не может запустить файл если ни у кого не установлен x:

chmod 644 script.sh
sudo ./script.sh
# ./script.sh: Permission denied – даже для root

Чтобы запустить – сначала chmod +x script.sh, потом sudo ./script.sh. Это защита от случайного запуска: если x не установлен, файл не является исполняемым ни для кого, включая root.

8. Специальные биты – SUID, SGID, Sticky bit

Помимо стандартных rwx существуют три специальных бита. Каждый работает по-разному в зависимости от того – установлен он на файл или на директорию.

SUID (Set User ID)

При запуске файла с SUID процесс получает EUID = UID владельца файла, а не UID пользователя который его запустил. Пример – команда passwd. Обычный пользователь должен иметь возможность сменить свой пароль, а значит записать новый хеш в /etc/shadow. Но /etc/shadow доступен только root. SUID решает эту проблему: /usr/bin/passwd принадлежит root и имеет SUID – при запуске процесс временно получает EUID=0 и может писать в shadow.

ls -la /usr/bin/passwd
# -rwsr-xr-x 1 root root 64152 Feb 6 /usr/bin/passwd

s вместо x в блоке владельца – SUID установлен. Заглавная S (без x) означает что SUID установлен но бит execute при этом не установлен – это подозрительная ситуация которой обычно не должно быть.

# Установить SUID
chmod u+s file
chmod 4755 file    # 4 – это SUID в числовом виде

# Найти все файлы с SUID в системе
find / -perm -4000 -type f 2>/dev/null

SUID-бинарники – популярная цель при атаках на повышение привилегий. Если на стандартной утилите вроде vim, find или bash внезапно появился SUID – это серьёзный повод для расследования. Регулярно проверяйте список SUID-файлов и сравнивайте с эталоном.

Эталон – это список SUID-файлов, снятый в заведомо чистом состоянии системы (сразу после установки или после проверенного аудита). При следующих проверках вы сравниваете текущий список с ним и видите, что появилось нового.

SGID (Set Group ID)

SGID работает по-разному для файлов и директорий. На файл: процесс получает EGID = GID группы файла – аналог SUID но для группы. Используется редко. На директорию: все файлы и поддиректории созданные внутри автоматически наследуют группу этой директории, а не primary group создателя. Это ключевой механизм для совместной работы. В качестве примера возьмём несколько разработчиков которые работают с одной директорией. Без SGID каждый создаёт файлы со своей primary group – другие не могут их редактировать даже если входят в нужную группу. С SGID все файлы автоматически получают группу директории и все члены группы могут работать с ними без лишних телодвижений.

# Установить SGID на директорию
chmod g+s /project
chmod 2755 /project    # 2 – это SGID в числовом виде

# Проверить – в выводе ls будет s вместо x в блоке группы
ls -la /project
# drwxr-sr-x 2 ivan developers 4096 апр 29 /project

Sticky bit

Sticky bit решает конкретную проблему: если у пользователя есть право w на директорию – он может удалить из неё любой файл, даже чужой. На директорию: пользователь может удалить файл только если он является владельцем файла или владельцем директории. Просто иметь w на директорию – недостаточно. Пример – /tmp, где директория доступна на запись всем, но никто не должен удалять чужие файлы:

ls -la /
# drwxrwxrwt  22 root root 4096 апр 29 19:07 tmp

t вместо x в блоке others – sticky bit установлен.

# Установить sticky bit
chmod +t /shared
chmod 1777 /shared    # 1 – это sticky bit в числовом виде

Сводная таблица

Бит

Числовой

Символьный

На файл

На директорию

SUID

4000

u+s

EUID = UID владельца файла

Нет эффекта

SGID

2000

g+s

EGID = GID группы файла

Новые файлы наследуют группу директории

Sticky

1000

+t

Нет эффекта

Удалить файл может только его владелец

Специальные биты идут первой цифрой в четырёхзначной записи:

chmod 4755 file    # SUID + rwxr-xr-x
chmod 2755 dir     # SGID + rwxr-xr-x
chmod 1777 dir     # Sticky + rwxrwxrwx
chmod 3755 dir     # SGID + Sticky + rwxr-xr-x

9. ACL – когда стандартных прав недостаточно

Стандартная модель UGO имеет фундаментальное ограничение: один владелец и одна группа. Что если нужно дать доступ двум разным пользователям с разными правами? Например, пользователь maria должна читать и писать файл, пользователь sergei – только читать, а все остальные – ничего. В UGO это не реализовать. ACL (Access Control Lists) решают эту задачу – они позволяют прописать права для произвольного количества пользователей и групп на один объект.

Для начала проверим что пакет установлен:

apt list --installed 2>/dev/null | grep acl
# Если пакета нет:
sudo apt install acl

9.1 Просмотр ACL

getfacl file.txt
# file: file.txt
# owner: veil
# group: veil
user::rw-          ← права владельца (стандартные)
group::r--         ← права группы (стандартные)
other::r--         ← права остальных (стандартные)

Пока ACL не установлены – вывод совпадает с обычными правами. Как только добавляем ACL-запись, в выводе ls -la появляется символ + в конце строки прав:

ls -la file.txt
# -rw-r--r--+ 1 veil veil 34045 апр 29 15:18 file.txt
#           ↑ этот плюс означает что на файле есть ACL

9.2 Установка ACL

# Дать конкретному пользователю права на файл
setfacl -m u:maria:rw file.txt

# Дать группе права на директорию
setfacl -m g:backend:rx /var/www/api

# Несколько записей сразу
setfacl -m u:maria:rw,g:backend:r file.txt

# Удалить конкретную ACL-запись
setfacl -x u:maria file.txt

# Удалить все ACL с файла
setfacl -b file.txt

После добавления ACL для maria – getfacl покажет дополнительные строки:

getfacl file.txt
# file: file.txt
# owner: veil
# group: veil
user::rw-
user:maria:rw-     ← ACL-запись для конкретного пользователя
group::r--
mask::rw-          ← маска появилась автоматически
other::r--

9.3 Маска

Маска – это максимально возможные эффективные права для всех ACL-записей, кроме владельца и others. Если маска r-x, то даже ACL с rwx реально даст только r-x. Маска появляется автоматически при добавлении первой ACL-записи и расширяется когда вы добавляете записи с большими правами. Можно задать явно:

# Посмотреть маску
getfacl file.txt | grep mask

# Явно задать маску
setfacl -m mask::rx file.txt

9.4 ACL по умолчанию – важный момент

Без флага -d ACL применяется только к уже существующим файлам. Новые файлы созданные в директории его не наследуют. Это частая ошибка – настроил ACL на директорию, а файлы которые потом создаются внутри его не получают.

Правильный паттерн – всегда два вызова:

# 1. Применить к существующим файлам и поддиректориям
setfacl -R -m g:developers:rwx /project

# 2. Установить ACL по умолчанию – для всех новых файлов
setfacl -d -m g:developers:rwx /project

# Проверить – в выводе появятся строки default:
getfacl /project
# file: project
# owner: ivan
# group: ivan
user::rwx
group::r-x
other::r-x
default:group:developers:rwx    ← будет применяться к новым файлам

10. umask – права по умолчанию при создании файлов

Когда создаётся новый файл или директория – система не даёт максимально возможные права, а вычитает из них маску. Это и есть umask. Максимальные права при создании: файл – 666 (execute никогда не ставится автоматически), директория – 777.

# Посмотреть текущую маску
umask
# 0022

# Расчёт:
# файл:       666 - 022 = 644 (rw-r--r--)
# директория: 777 - 022 = 755 (rwxr-xr-x)

Строго говоря umask работает как побитовая операция исключения, а не простое вычитание. Разница проявляется если у вас нестандартные значения: например, 666 минус 033 математически даст 633, но побитовое исключение даст 644. Для стандартных значений (022, 027, 077) простое вычитание даёт верный результат и удобнее для понимания.

# Проверить на практике
umask 022
touch newfile.txt && ls -la newfile.txt
# -rw-r--r-- 1 ivan ivan 0 Mar 26 newfile.txt   ← 644

mkdir newdir && ls -la | grep newdir
# drwxr-xr-x 2 ivan ivan 4096 Mar 26 newdir     ← 755

Типичные значения

umask

Файлы

Директории

Когда применять

022

644

755

Стандарт – публичный доступ на чтение

027

640

750

Усиленный – others вообще без доступа

077

600

700

Параноидальный – только владелец

Где настраивается

# Для текущей сессии
umask 027

# Глобально для всех пользователей
grep UMASK /etc/login.defs
# UMASK 022

# Для конкретного пользователя
echo "umask 027" >> ~/.bashrc

# Для сервиса через systemd unit-файл
# [Service]
# UMask=0027

Бонус и Заключение

Мы рассмотрели всё начиная от базовой модели UGO и битов rwx до алгоритма принятия решений ядром, специальных битов и ACL. Отдельно хочу поделиться полезным материалом на YouTube от Дмитрия с заданиями для самостоятельной отработки навыков, очень полезно тем, кто только начинает учить Linux.

Увидимся в следующей части серии!

Статья доступна на сайте opensophy. Статьи, блоги и документации в первую очередь выходят и обновляются на сайте с указанием автора и соавторов.