15.4.7. Изменение прав доступа к файлу: системные вызовы chmod() и fchmod()
Системные вызовы chmod() и fchmod() изменяют права доступа к файлу.
#include
int chmod(const char *
#define _XOPEN_SOURCE 500 /* Или #define _BSD_SOURCE */
#include
int fchmod(int
Оба вызова возвращают 0 при успешном завершении и –1 при ошибке
Системный вызов chmod() изменяет права доступа к файлу, указанному в аргументе pathname. Если данный аргумент является символической ссылкой, то системный вызов chmod() изменяет права доступа к файлу, на который она указывает, а не права доступа к самой ссылке. (Символическая ссылка всегда создается с правами доступа на чтение, запись и выполнение, предоставленными всем пользователям, и эти права нельзя изменить. Они игнорируются при разыменовании ссылки.)
Системный вызов fchmod() изменяет права доступа к файлу, указанному с помощью открытого файлового дескриптора fd.
Аргумент mode задает новые права доступа к файлу как число (восьмеричное) либо в виде маски, сформированной с помощью операции ИЛИ (|) из битов прав доступа, приведенных в табл. 15.4. Для изменения прав доступа к файлу необходимо, чтобы процесс был привилегированным (CAP_FOWNER) либо чтобы его действующий UID совпадал с владельцем (UID) для файла. (Если абсолютно точно, то в Linux в случае непривилегированного процесса с идентификатором пользователя файла должен совпадать пользовательский идентификатор в файловой системе процесса, а не его действующий UID, как описано в разделе 9.5.)
Чтобы предоставить всем пользователям только право доступа на чтение файла, можно использовать следующий системный вызов:
if (chmod("myfile", S_IRUSR | S_IRGRP | S_IROTH) == -1)
errExit("chmod");
/* Или эквивалент — chmod("myfile", 0444); */
Порядок изменения избранных битов прав доступа к файлу таков: сначала следует извлечь существующие значения, применив системный вызов stat(), изменить необходимые биты, а затем выполнить системный вызов chmod(), чтобы обновить права доступа:
struct stat sb;
mode_t mode;
if (stat("myfile", &sb) == -1)
errExit("stat");
mode = (sb.st_mode | S_IWUSR) & ~S_IROTH;
/* Разрешить владельцу запись, другим пользователям запретить чтение,
остальные биты не менять */
if (chmod("myfile", mode) == -1)
errExit("chmod");
Приведенный выше код эквивалентен следующей команде оболочки:
$ chmod u+w,o-r myfile
В подразделе 15.3.1 мы отметили: если каталог размещен в файловой системе ext2, смонтированной с параметром — o bsdgroups, или в какой-либо файловой системе, смонтированной с параметром — o sysvgroups, и для этого каталога установлен бит прав доступа set-group-ID, то создаваемые в данном каталоге новые файлы наследуют свою принадлежность от родительского каталога, а не от действующего GID создающего процесса. Но может случиться так, что идентификатор группы для такого файла не совпадает ни с одним из GID создающего процесса. По этой причине, когда непривилегированный процесс (то есть не обладающий возможностью CAP_FSETID) совершает системный вызов chmod() (или fchmod()) для файла, идентификатор группы которого не совпадает с действующим GID или идентификатором добавочной группы для процесса, ядро всегда очищает бит прав доступа set-group-ID. Это мера безопасности, призванная запретить пользователю создание программы с правами доступа set-group-ID для группы, к которой он не принадлежит. Следующие команды оболочки демонстрируют попытку взлома, которая пресекается данной мерой:
$ mount | grep test
/dev/sda9 on /test type ext3 (rw,bsdgroups)
$ ls — ld /test
drwxrwxrwx 3 root root 4096 Jun 30 20:11 /test
$ id
uid=1000(mtk) gid=100(users) groups=100(users),101(staff),104(teach)
$ cd /test
$ cp ~/myprog.
$ ls — l myprog
— rwxr-xr-x 1 mtk root 19684 Jun 30 20:43 myprog
$ chmod g+s myprog
$ ls — l myprog
— rwxr-xr-x 1 mtk root 19684 Jun 30 20:43 myprog
Ряд файловых систем Linux допускают устанавливать для файлов и каталогов различные