Файл stat () vs access () для проверки прав доступа к каталогу - PullRequest
8 голосов
/ 17 августа 2011

Я успешно использовал оба параметра stat() & access() по отдельности, чтобы определить, имеет ли пользователь права на чтение или чтение / запись в каталоге.

Мой вопрос: - Есть ли предпочтительный метод?Я вижу много примеров использования stat, но для моей цели доступ кажется более легким и служит цели.
- Есть ли какие-либо проблемы (например, - безопасность) с одним или другим?- Есть проблемы с моим подходом?

Вот некоторый псевдокод (воссоздание из памяти без компиляции):

       // Using access():
    bool readAccessPermission = false; 
    bool writeAccessPermission = false;

    if (mode == 'r'){
            if (access(directory, R_OK) == 0)
                    readAccessPermission = true;                        
    }
    else{
            if (access(directory, R_OK && W_OK) == 0)
                    readAccessPermission = true;
                    writeAccessPermission = true;
    }


    // vs. using stat function
    // assume I already called stat(directory) and have the object


    bool readAccessPermission = false; 
    bool writeAccessPermission = false;

    var retmode = ((stats.mode) & (0777));

    if (modeString == 'r'){ 
        if ((retmode) & (consts.S_IRUSR)){
            readAccessPermission = false; 
        }    
    } 
    else{ 
        if ((retmode) & (consts.S_IRUSR)){
            readAccessPermission = true; 

            if ((retmode) & consts.S_IWUSR)){               
                writeAccessPermission = true; 
            }
        }
    }

Ответы [ 3 ]

8 голосов
/ 17 августа 2011

Любой эквивалент для ваших нужд. access() - более чистая оболочка, если вы не собираетесь ничего делать с заполненной структурой статистики.

Просто помните, что вы создаете расу, когда делаете это. Разрешения могут меняться между вызовом stat()/access() и тем, когда вы на самом деле пытаетесь использовать каталог. Черт, каталог мог даже быть удален и воссоздан в то время.

Лучше просто попытаться открыть то, что вам нужно, и проверить на EPERM. Проверка stat() или access() не гарантирует, что последующая операция не вернет EPERM.

4 голосов
/ 17 августа 2011

В простом случае оба являются функционально эквивалентными для нашего вопроса. Кроме того, access() не будет намного быстрее или так же, как одна и та же структура данных (индекс) будет очень извлечена.

Однако, если в системе используются списки контроля доступа ( ACL ), они будут обрабатываться, пока у вас нет возможности проверить ACL с данными stat.

1 голос
/ 11 ноября 2016

Эти два фрагмента кода не идентичны и дают существенно разные результаты.

Во-первых, ваш статистический вызов проверяет только биты разрешения владельца. Если пользователь, выполняющий этот код, не владеет рассматриваемым файлом, это неправильный набор битов для проверки.

Во-вторых, даже если мы предполагаем, что вызывающий пользователь является владельцем, нам также необходимо выяснить, что мы подразумеваем под «вызывающим пользователем». Что касается open(2) и его друзей, то вызывающим пользователем является номер, возвращаемый geteuid(2), то есть эффективный идентификатор пользователя . Это то, что open использует, чтобы определить, разрешить ли открытие файла. Что касается access(2), то вызывающим пользователем является номер, возвращаемый getuid(2), то есть реальный идентификатор пользователя . Это то, что использует доступ, чтобы определить, следует ли сообщать об успехе. Действительные и эффективные идентификаторы UID могут различаться, особенно при запуске двоичного файла с включенным битом setuid или когда программист делает что-то особенно умное (и, вероятно, ИМХО опрометчивое).

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

Наконец, как было указано в нескольких ответах, оба фрагмента кода могут быть уязвимы для ошибок TOCTTOU , в зависимости от того, что вы делаете с результатами. В общем, самый безопасный способ определить, разрешено ли действие, - это попытаться выполнить это действие и проверить, не выполнено ли оно.

...