Перейти к содержанию

Права доступа и атрибуты файлов

Модель прав доступа

Права доступа в Linux определяют, кто может что делать с файлом. Каждый файл имеет три набора прав:

  • u (user/owner) — права владельца файла;
  • g (group) — права группы;
  • o (other) — права всех остальных.

Каждый набор состоит из трёх битов:

Бит Символ Восьмеричное Значение
r read 4 Чтение содержимого файла
w write 2 Запись / изменение файла
x execute 1 Выполнение файла (или вход в директорию)

Посмотреть права:

ls -l file.txt
# -rw-r--r-- 1 alice devs 1024 Jan 14 12:00 file.txt
#  ^^^ ^^^ ^^^
#  uuu ggg ooo

stat -c "%a %n" file.txt   # восьмеричный формат: 644 file.txt

Расшифровка rw-r--r-- (644): владелец — чтение+запись (6), группа — только чтение (4), остальные — только чтение (4).

Структура mode_t: биты прав и специальные биты

  mode_t (16 бит):

   15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
  ┌───┬───┬───┬───┬────┬────┬────┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
  │   тип файла   │SUID│SGID│Stky│ r │ w │ x │ r │ w │ x │ r │ w │ x │
  └───┴───┴───┴───┴────┴────┴────┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
        (S_IFMT)    │    │    │   └───────────┘ └───────────┘ └───────────┘
                    │    │    │      user(u)       group(g)     other(o)
                    │    │    │
                    │    │    └── Sticky   (01000) — /tmp: удаляет только владелец
                    │    └─────── SGID     (02000) — запуск от имени группы файла
                    └──────────── SUID     (04000) — запуск от имени владельца файла

  Пример: -rwsr-xr-x  (вывод ls -l)
  ┌──────────────────────────────────────────────────────────────┐
  │  -  r w s  r - x  r - x                                      │
  │  │  └─┬─┘  └─┬─┘  └─┬─┘                                      │
  │  │  u=rwx  g=rx   o=rx                                       │
  │  │  + SUID                                                   │
  │  │                                                           │
  │  └── тип: - = обычный файл                                   │
  │           d = директория                                     │
  │           l = символическая ссылка                           │
  │           b = блочное устройство                             │
  │           c = символьное устройство                          │
  └──────────────────────────────────────────────────────────────┘

  Восьмеричное представление:
  ┌──────┬──────┬──────┬──────┐
  │SUID/ │ user │group │other │
  │SGID/ │ rwx  │ rwx  │ rwx  │
  │Sticky│      │      │      │
  ├──────┼──────┼──────┼──────┤
  │  4   │  7   │  5   │  5   │  → 4755 = rwsr-xr-x
  │  1   │  7   │  7   │  7   │  → 1777 = rwxrwxrwt (/tmp)
  │  0   │  6   │  4   │  4   │  →  644 = rw-r--r--
  └──────┴──────┴──────┴──────┘

Буква s (строчная) в позиции x означает, что и x, и SUID/SGID установлены. Буква S (заглавная) — SUID/SGID установлен, но x нет. Аналогично t vs T для sticky.

Изменение прав: chmod

chmod принимает права в символьном или восьмеричном формате:

chmod u+x file.txt          # добавить execute для владельца
chmod g-w file.txt          # убрать write у группы
chmod u=rwx,g=rx,o= file.txt  # явно задать права каждой категории
chmod 644 file.txt          # восьмеричный формат
chmod -R 755 mydir/         # рекурсивно

Распространённые комбинации:

Число Символы Назначение
644 rw-r--r-- Обычный файл (читают все, пишет владелец)
755 rwxr-xr-x Исполняемый файл или директория
700 rwx------ Приватный файл, доступен только владельцу
600 rw------- Приватный файл без права выполнения
1777 rwxrwxrwt /tmp — все пишут, но удаляет только владелец

Права на директории

Для директорий биты r, w, x имеют другой смысл:

Бит Для файла Для директории
r Читать содержимое Просматривать список файлов (ls)
w Изменять файл Создавать и удалять файлы внутри
x Выполнить Входить в директорию (cd), обращаться к файлам

Чтобы получить доступ к файлу по пути, нужен бит x на каждой родительской директории. Бит r без x позволяет увидеть список имён, но не обратиться к самим файлам.

Изменение владельца и группы

chown alice file.txt              # сменить владельца
chown alice:developers file.txt   # сменить владельца и группу
chgrp developers file.txt         # сменить только группу
chown -R alice mydir/             # рекурсивно

Ограничения: только root может менять владельца (chown). Владелец файла может менять его группу только на группу, в которой сам состоит.

Системные вызовы chmod и chown

#include <sys/stat.h>

int chmod(const char *pathname, mode_t mode);
int fchmod(int fd, mode_t mode);
#include <unistd.h>

int chown(const char *pathname, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int lchown(const char *pathname, uid_t owner, gid_t group);  // не разыменовывает симлинки

Передача -1 в качестве owner или group означает «не изменять»:

chown("file.txt", 1001, -1);   // изменить только владельца
chown("file.txt", -1, 1002);   // изменить только группу

Константы прав доступа:

#include <sys/stat.h>

S_IRUSR  // 0400 — чтение для владельца
S_IWUSR  // 0200 — запись для владельца
S_IXUSR  // 0100 — выполнение для владельца
S_IRGRP  // 0040 — чтение для группы
S_IWGRP  // 0020 — запись для группы
S_IXGRP  // 0010 — выполнение для группы
S_IROTH  // 0004 — чтение для остальных
S_IWOTH  // 0002 — запись для остальных
S_IXOTH  // 0001 — выполнение для остальных

Специальные биты: SUID, SGID, Sticky

Помимо девяти обычных битов существуют три специальных:

Бит Восьмер. Символ На файле На директории
SUID 4xxx s / S Программа выполняется от имени владельца (не применяется)
SGID 2xxx s / S Программа выполняется от имени группы Новые файлы наследуют группу каталога
Sticky 1xxx t / T (нет эффекта) Удалять файлы может только их владелец

Строчная s или t означает, что соответствующий бит x тоже установлен; заглавная S или T — бит x не установлен.

SUID — классический пример /usr/bin/passwd: он принадлежит root и имеет SUID, поэтому обычный пользователь может менять свой пароль, хотя сам файл паролей доступен только root:

ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root ... /usr/bin/passwd

chmod u+s myprog      # символьный формат
chmod 4755 myprog     # восьмеричный формат

Sticky bit/tmp доступен для записи всем, но удалить чужой файл нельзя:

ls -ld /tmp
# drwxrwxrwt  (t в конце)

chmod o+t mydir/
chmod 1777 mydir/

SUID на скриптах не работает по соображениям безопасности — ядро игнорирует этот бит для интерпретируемых файлов.

Маска создания файлов: umask

При создании файла через open или mkdir запрошенные права маскируются через umask процесса:

итоговые_права = запрошенные_права & ~umask

Например, при umask 022 файл, созданный с mode=0666, получит права 0644, а директория с mode=07770755.

#include <sys/stat.h>

mode_t umask(mode_t mask);   // устанавливает umask, возвращает старое значение

Просмотр текущей umask в shell:

umask        # показать в восьмеричном виде (например 0022)
umask -S     # в символьном виде (u=rwx,g=rx,o=rx)

Атрибуты файлов (ext2/ext4)

Атрибуты — это дополнительные флаги inode, поддерживаемые рядом файловых систем (ext2, ext3, ext4). Они влияют на поведение ФС независимо от прав доступа.

Просмотр и изменение:

lsattr file.txt           # посмотреть атрибуты
chattr +i file.txt        # установить атрибут
chattr -i file.txt        # снять атрибут
chattr -R +A mydir/       # рекурсивно

Основные атрибуты:

Символ Название Описание
a append only Файл можно только дополнять (не перезаписать, не усечь)
i immutable Файл неизменяем: нельзя изменить, удалить, переименовать
A no atime update Время доступа не обновляется (экономит I/O)
s secure deletion При удалении блоки затираются нулями
S sync updates Все изменения записываются на диск синхронно
d no dump Файл пропускается утилитой dump при резервном копировании

Атрибут +i не может сломать даже root без предварительного chattr -i. Это полезно для защиты критических конфигов:

chattr +i /etc/myapp/config.conf
chattr +a /var/log/myapp.log      # лог только на добавление

Программный доступ к атрибутам через ioctl:

#include <sys/ioctl.h>
#include <linux/fs.h>
#include <fcntl.h>

int fd = open("file.txt", O_RDONLY);
int attrs;
ioctl(fd, FS_IOC_GETFLAGS, &attrs);

attrs |= FS_IMMUTABLE_FL;          // установить immutable
ioctl(fd, FS_IOC_SETFLAGS, &attrs);
close(fd);

Связанные темы

Источники

  • man 2 chmod — системный вызов chmod
  • man 2 chown — системный вызов chown
  • man 2 umask — маска создания файлов
  • man 1 chmod — команда chmod в оболочке
  • man 1 chattr — управление атрибутами файлов ext2/ext4
  • man 1 lsattr — просмотр атрибутов файлов
  • man 7 inode — поля inode, включая st_mode