2010-09-01 2 views
3

Я ищу способ определения прав доступа к файлу для текущего пользователя (т. Е. UID процесса) в системах, совместимых с POSIX. Я не хочу пытаться открыть файл - это может стать беспорядочным с каталогами и всеми специальными файлами.определить права доступа к файлам для текущего пользователя

Я составляю список каталогов указанного каталога и для каждого файла, сообщающий о множестве вещей: имя файла, размер, тип (файл/каталог/другое), разрешения (вы можете читать, вы можете писать). Для размера и типа у меня уже есть результаты вызова stat.

Вот что я придумал:

if ((dirent->st_uid == getuid() && dirent->st_mode & S_IRUSR) 
|| (dirent->st_gid == getgid() && dirent->st_mode & S_IRGRP) 
|| (dirent->st_mode && S_IROTH)) entry->perm |= PERM_READ; 
if ((dirent->st_uid == getuid() && dirent->st_mode & S_IWUSR) 
|| (dirent->st_gid == getgid() && dirent->st_mode & S_IWGRP) 
|| (dirent->st_mode && S_IWOTH)) entry->perm |= PERM_WRITE; 

Должен ли я сделать так, или есть простой вызов/макрос, который будет сделать то же самое? Бонусные баллы за поддержку ACL, хотя на данный момент это не является абсолютно необходимым.

ответ

8

access(2) выполнит полный набор разрешений тестов для вас, в ядре:

#include <unistd.h> 
#include <stdio.h> 

int main(int argc, char* argv[]) { 
    int i; 

    for (i=0;i<argc;i++) { 
      if(access(argv[i], R_OK)) { 
        printf("%s\n", argv[i]); 
        perror("R_OK"); 
      } 
      if(access(argv[i], W_OK)) { 
        printf("%s\n", argv[i]); 
        perror("W_OK"); 
      } 
    } 

    return 0; 
} 

Некоторый Пример вывод:

$ ./foo ./foo /etc/passwd /etc/shadow 
/etc/passwd 
W_OK: Permission denied 
/etc/shadow 
R_OK: Permission denied 
/etc/shadow 
W_OK: Permission denied 

EDIT

Обратите внимание, что access(2) уязвим до TOCTTOU Время гонки на время использования. Вы не должны использовать access(2), чтобы предоставить или запретить доступ к файлам пользователю из привилегированного процесса, ваша программа будет уязвима к условиям гонки, которые могут быть использованы. Если это то, что вы хотите проверить, используйте setfsuid(2) перед выполнением любых звонков open(2) или exec*().

Смежные вопросы