Learning Platform
Глоссарий Troubleshooting
Урок 12.02 · 22 мин
Начальный
PermissionsrwxchmodsetuidsetgidstickyLinux

rwx-права — девять битов, которые управляют доступом к каждому файлу

Когда вы делаете ls -l и видите -rw-r--r-- — это девять битов в inode файла, которые kernel читает миллиарды раз в день. На каждом open(), на каждом read(), на каждом cd — kernel смотрит эти биты и решает «можно или нельзя». Понимание этой системы — абсолютная база Unix-мира, и одновременно одна из самых частых причин «у меня permission denied», на которые тратятся часы.

В этом уроке разберём: как kernel принимает решение, что значат rwx для разных типов файлов, как chmod конвертирует число в биты, и что делают волшебные setuid/setgid/sticky.


Девять битов и кому они соответствуют

Каждый файл в Linux имеет:

  • Владельца (user, owner) — один UID.
  • Группу — один GID.
  • Девять битов доступа — три набора по три (r, w, x).

Девять битов делятся на три категории:

-rwxr-xr-x
 ^^^^^^^^^
 u  g  o
  • u (user, owner) — права владельца.
  • g (group) — права группы файла.
  • o (other) — права всех остальных.

Когда процесс пытается открыть файл, kernel выполняет проверку:

  1. Если EUID процесса == UID владельца файла — проверяет биты u.
  2. Иначе, если GID файла есть среди групп процесса (primary или supplementary) — проверяет биты g.
  3. Иначе — проверяет биты o.

Важно: только ОДНА проверка. Если вы владелец и u-r не стоит, вы НЕ читаете файл, даже если o-r стоит. Это часто непонимают: «но other может читать, почему я не могу?» Потому что для kernel ваш категория — owner, и эта категория должна разрешить.

Какая из трёх категорий применяется к процессу
EUID == owner UID?Первый чек: процесс работает от имени владельца файла?
yes
Используем биты uПрименяются только биты u (первая тройка rwx). Биты g и o игнорируются
GID есть в моих группах?Если нет совпадения по UID -- проверяем GID. EGID процесса или supplementary groups
yes
Используем биты gПрименяются только биты g (вторая тройка). Биты u и o игнорируются
ИначеЕсли не owner и не group -- остаются only biты o
Используем биты oПрименяются биты o (третья тройка). Биты u и g игнорируются

Root (UID=0) — исключение. Он игнорирует обычные проверки прав (кроме особых случаев типа immutable bit и capabilities).


Что значат r, w, x для файлов

Для обычного файла:

  • r (read) — можно читать содержимое (cat, less, cp).
  • w (write) — можно изменять содержимое (echo > file, редактор сохраняет).
  • x (execute) — можно запускать как программу (./script.sh, ./binary).

Несколько неочевидных моментов:

  • w без r — редко полезно. Можно затереть, но не прочитать. Используется в логах, куда сервис должен только append’ить.
  • x на скрипте. Нужны и r, и x. Чтобы выполнить bash-скрипт, shell должен его прочитать.
  • x на бинарнике. Достаточно только x (kernel сам читает бинарник через специальный канал, не через права).
  • Удалить файл — это W на ДИРЕКТОРИИ, не на файле. См. ниже.
# Создать файл и поиграть с правами:
echo "secret" > /tmp/secret.txt
ls -l /tmp/secret.txt
# -rw-r--r-- 1 levoely levoely 7 May 18 12:00 /tmp/secret.txt

# Убрать чтение для других:
chmod o-r /tmp/secret.txt
ls -l /tmp/secret.txt
# -rw-r----- 1 levoely levoely 7 May 18 12:00 /tmp/secret.txt
# Группа всё ещё читает, others -- нет

# Полностью приватный (только мне):
chmod 600 /tmp/secret.txt
ls -l /tmp/secret.txt
# -rw------- 1 levoely levoely 7 May 18 12:00 /tmp/secret.txt

Что значат r, w, x для директорий

Для директорий значение битов меняется:

  • r (read) — можно ПОЛУЧИТЬ СПИСОК файлов (ls dir/). Без r вы не увидите, какие файлы там есть.
  • w (write) — можно СОЗДАВАТЬ и УДАЛЯТЬ файлы в этой директории (даже не свои!).
  • x (execute) — можно ВОЙТИ в директорию (cd) и обращаться к файлам по имени.

Это контр-интуитивно: чтобы удалить файл secret.txt, не нужны права на сам файл — нужны w на директории, в которой он лежит. Потому что «удалить» — это убрать запись из директории, не из файла.

mkdir /tmp/test
cd /tmp/test
touch myfile
chmod 000 myfile        # никаких прав на файл!
ls -l myfile
# ---------- 1 levoely levoely 0 May 18 12:00 myfile

cat myfile              # cannot open: permission denied (нет r)
echo "x" > myfile       # permission denied (нет w)

rm myfile               # СРАБОТАЕТ! Потому что у вас w на /tmp/test

Сочетание x без r на директории — интересный кейс. Вы можете обращаться к файлу по имени (если знаете), но ls запрещён. Иногда используется для shared-директорий, где никто не должен видеть, какие там файлы, но конкретные адреса работают:

chmod 711 /tmp/private   # x для всех, r только владельцу
touch /tmp/private/known_file
# Из другого аккаунта:
ls /tmp/private              # permission denied
cat /tmp/private/known_file  # works! если файл доступен сам

Восьмеричная запись chmod

Девять битов — это число от 0 до 0777 в восьмеричной. Каждая тройка rwx — одна восьмеричная цифра:

БитыВосьмеричноеЧто значит
---0ничего
--x1только execute
-w-2только write
-wx3write + execute
r--4только read
r-x5read + execute
rw-6read + write
rwx7всё

Часто встречающиеся комбинации:

ModeСмысл
644rw-r—r— — обычный файл, владелец редактирует, все читают
600rw------- — приватный файл (SSH ключи, токены)
755rwxr-xr-x — исполняемая программа или директория
700rwx------ — приватная директория (например, ~/.ssh)
777rwxrwxrwx — НИКОГДА в production
666rw-rw-rw- — почти всегда плохая идея
chmod на практике: octal, symbolic notation и umask
# Восьмеричной записью:
chmod 644 file.txt
chmod 755 script.sh

# Символьной (mnemonic):
chmod u+x script.sh      # добавить execute владельцу
chmod g-w file.txt       # убрать write у группы
chmod o=r file.txt       # set: only read у others
chmod a+r file.txt       # all (u+g+o): добавить read
WARNING

‘chmod 777’ встречается в туториалах в стиле «помогло, теперь работает». Это маскировка проблемы. Любой пользователь в системе сможет переписать файл — катастрофа в production. Правильный путь: понять, какой UID/GID должен иметь доступ, и дать минимальные нужные права.


Setuid: программа выполняется от имени владельца

Бывают ситуации, когда обычному пользователю нужно временно получить root-права для конкретной операции. Классический пример — passwd: пользователь должен изменить свой пароль, который хранится в /etc/shadow (доступен только root для записи). Как это работает?

/usr/bin/passwd имеет специальный бит setuid (SUID). При запуске такой программы effective UID процесса становится UID владельца файла, а не запустившего:

ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root 68208 May 18 12:00 /usr/bin/passwd
#    ^ маленькая s вместо x в позиции u-x = setuid bit

s в позиции execute владельца — это SUID. Файл принадлежит root, и при запуске EUID процесса становится 0 (root), хотя RUID остаётся вашим. Поэтому passwd может модифицировать /etc/shadow.

Это мощный механизм, но опасный. Каждая setuid-программа — потенциальная дыра в безопасности. Если в ней есть buffer overflow или command injection, атакующий получает права владельца (часто root).

# Найти все setuid-программы в системе:
find / -perm -4000 -type f 2>/dev/null
# Список обычно небольшой: passwd, sudo, ping, mount, su, ...

# Установить SUID:
chmod u+s /path/to/program  # или
chmod 4755 /path/to/program  # 4 = setuid

# Снять:
chmod u-s /path/to/program

В современном Linux setuid постепенно заменяют capabilities (следующий урок). Например, ping исторически был setuid root (чтобы открывать raw socket), теперь чаще имеет capability CAP_NET_RAW — более точечное право.


Setgid: программа выполняется от имени группы файла

Аналогично, но для группы. SGID-бит на исполняемом файле делает EGID = GID файла при запуске.

s в позиции execute группы:

ls -l /usr/bin/wall
# -rwxr-sr-x 1 root tty 36320 May 18 12:00 /usr/bin/wall
#         ^ s вместо x на g

Wall (write-to-all-users) имеет EGID=tty при запуске — получает право писать в терминалы всех пользователей.

Setgid на ДИРЕКТОРИИ имеет другой смысл: новые файлы в этой директории получают её GID, а не primary GID создателя. Это удобно для shared-папок проекта:

mkdir /shared
sudo chown :developers /shared
chmod 2775 /shared        # 2 = setgid в начале
# Теперь любой файл, созданный в /shared, имеет GID=developers,
# даже если создавший пользователь имеет primary group 'levoely'

Sticky bit: только владелец удалит свой файл

Помните: чтобы удалить файл, нужно w на ДИРЕКТОРИИ, а не на файле. Это значит, что в shared-директории с правами 777 кто угодно может удалить чужие файлы. Решение — sticky bit.

С sticky bit на директории файл может удалить только владелец файла (или владелец директории, или root). Видно как t в позиции execute для others:

ls -ld /tmp
# drwxrwxrwt 28 root root 4096 May 18 12:00 /tmp
#          ^ t = sticky bit

/tmp — классический пример. Любой может создавать файлы, но удалять только свои. Без sticky любой пользователь смог бы удалить чужой /tmp/foo.

# Установить sticky:
chmod +t /shared/dir   # или
chmod 1777 /shared/dir
# 1 = sticky в первой позиции

# Проверить:
ls -ld /shared/dir

Все 12 бит вместе

Полный набор: 9 базовых rwx + setuid + setgid + sticky. Кодируется четырёхзначным восьмеричным числом:

  • Первая цифра — setuid (4) + setgid (2) + sticky (1).
  • Остальные — стандартные u, g, o.
chmod 4755 /usr/bin/passwd   # setuid + 755
chmod 2775 /shared/projects  # setgid + 775
chmod 1777 /tmp              # sticky + 777
chmod 0644 /etc/hosts        # обычный (можно и просто 644)
Полная запись прав файла: 12 бит
setuidЗапустить как владельца файла. 4 в восьмеричной первой цифре
setgidЗапустить как группа файла. На директории -- inherit GID. 2 в восьмеричной
stickyТолько владелец удаляет (на директориях). 1 в восьмеричной
u: rwxПрава владельца (UID файла)
g: rwxПрава группы файла (GID файла)
o: rwxПрава всех остальных

Реальный пример отладки permission denied

# Что делать, если 'cat file.txt' даёт permission denied:

# 1. Что за файл -- права и владелец:
ls -l file.txt
# -rw-r----- 1 alice developers 245 May 18 12:00 file.txt

# 2. Какой у меня UID и группы:
id
# uid=1000(levoely) gid=1000(levoely) groups=1000(levoely),27(sudo)

# 3. Проверка:
#    - я owner? Нет (1000 != UID alice)
#    - я в группе developers? Нет (developers не среди моих групп)
#    - other rwx? --- (нет read для others)
# Результат: permission denied -- правильно.

# 4. Что я могу сделать:
# (a) Попросить alice сделать chmod o+r file.txt
# (b) Попросить admin'а добавить меня в группу developers
# (c) Если есть sudo -- 'sudo cat file.txt' (как root, видит всё)

# 5. Если файл должен быть доступен:
sudo chown alice:developers file.txt   # установить владельца
sudo chmod 640 file.txt                # u=rw, g=r, o=
sudo usermod -aG developers levoely    # добавить меня в группу
# Перелогиниться, чтобы новая группа применилась к shell

Попробуй сам

# 1. Создать файл и посмотреть права:
touch /tmp/exp.txt
ls -l /tmp/exp.txt
# Какой umask определил начальные права?
umask                # обычно 022 -> файлы по умолчанию 644

# 2. Поиграть с chmod:
chmod 600 /tmp/exp.txt
ls -l /tmp/exp.txt
chmod 644 /tmp/exp.txt
chmod a+x /tmp/exp.txt   # хотя это не скрипт, можно дать execute

# 3. Тест удаления через директорию:
mkdir /tmp/td
echo "important" > /tmp/td/file
chmod 000 /tmp/td/file
cat /tmp/td/file        # permission denied
rm /tmp/td/file         # сработает, у вас w на /tmp/td
ls /tmp/td              # пусто

# 4. Найти setuid-программы:
find /usr/bin /usr/sbin -perm -4000 -type f 2>/dev/null

# 5. Посмотреть права /tmp:
ls -ld /tmp
# Обратите внимание на 't' в конце

# 6. Эксперимент с sticky:
mkdir /tmp/shared
chmod 1777 /tmp/shared
ls -ld /tmp/shared       # drwxrwxrwt
# Создайте файл, попросите другого пользователя его удалить -- не получится

# 7. Найти все доступные для записи файлы в /etc (потенциальные риски):
find /etc -type f -perm -o=w 2>/dev/null
# Хорошо настроенная система покажет пустой результат

Проверка знанийKnowledge check
Сервер с веб-приложением на Python (бежит под uid=999 'webapp'). Пользователь 'levoely' (uid=1000) разместил конфиг в /opt/app/config.yaml, права '-rw-r----- 1 levoely staff'. Приложение падает при чтении файла. Какие 3 способа починить и какой 'правильный'?
ОтветAnswer
Проблема: webapp (uid=999) не владелец, не в группе staff, others не имеют r. Результат: permission denied. 3 способа починить: 1) chmod o+r /opt/app/config.yaml -- дать read всем. Быстро, но плохо: любой пользователь на сервере сможет прочитать config (там могут быть пароли, токены). Хуже всего, если это что-то вроде /etc/app/secrets.yaml. 2) chown levoely:webapp /opt/app/config.yaml + chmod 640 -- сменить group на webapp (если такая группа существует), дать g+r. Webapp читает через свою primary group. Минус: нужна группа webapp, и только webapp может читать. Если другие сервисы тоже должны -- усложняется. 3) usermod -aG staff webapp -- добавить webapp в группу staff. Webapp получает доступ через supplementary group. Минус: webapp получает доступ ко ВСЕМ файлам группы staff, не только к config -- может быть слишком широко. 4) Правильный путь -- разделить ответственности и принцип least privilege: - Создать выделенную группу config-readers (или app-config). - Положить config с правами 0640, владелец levoely, группа config-readers (chown levoely:config-readers). - Добавить webapp в config-readers (usermod -aG config-readers webapp). - При необходимости добавлять других читателей в эту группу, не меняя файл. Тогда у webapp точечное разрешение читать именно конфиги, без лишнего доступа. levoely может редактировать через u-bits. Other (root через sudo всё равно может) -- closed. Бонус: для secrets в production правильнее не файл на диске, а secret manager (Vault, AWS Secrets Manager, Kubernetes Secret) -- но это другая история. Если используем файл -- chmod 640 + dedicated group самый чистый вариант. Что точно НЕ делать: chmod 777 (раздать всем write -- катастрофа), chown root (тогда webapp не сможет даже как root прочитать, потому что бежит под webapp).

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 6. Файл с правами '-rwxr-xr-x' принадлежит alice:staff. Bob -- в группе staff, но не owner. Какие операции ему разрешены?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4