C++ 文件 stat() 与 access() 以检查目录的权限

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7087958/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 16:27:31  来源:igfitidea点击:

File stat() vs access() to check permissions on a directory

c++file-iostat

提问by Bamerza

I have successfully used both stat()& access()separately to determine if a user has either read or read/write access to a directory.

我已经成功地同时使用stat()&access()来确定用户是否具有对目录的读或读/写访问权限。

My question is: - Is there a preferred method ? I see a lot of examples using stat, but for my purpose, access seems to be more lightweight and serves purpose.
- Are there any issues (e.g. - security) w/ one or the other ? - Any issues w/ my approach ?

我的问题是: - 是否有首选方法?我看到很多使用 的示例stat,但就我的目的而言,访问似乎更轻量级并且服务于目的。
- 是否存在任何问题(例如 - 安全性)?- 我的方法有什么问题吗?

Here is some pseudo code (re-creating from memory w/o compiling) :

这是一些伪代码(从内存中重新创建,无需编译):

       // 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; 
            }
        }
    }

回答by Adam Hawes

Either is equivalent for your needs. access()is a cleaner wrapper if you're not going to do anything with the stat structure that you populate.

两者都满足您的需求。access()如果您不打算对填充的 stat 结构做任何事情,那么它是一个更干净的包装器。

Just be mindful that you are creating a race when doing this. The permissions can change between calling stat()/access()and when you actually try and use the directory. Hell, the directory could even be deleted and recreated in that time.

请注意,这样做时您正在创造一场比赛。权限可以在调用stat()/access()和实际尝试使用目录之间更改。地狱,那个时候甚至可以删除和重新创建目录。

It's better to just try and open what you need and check for EPERM. Checking stat()or access()will not guarantee that a subsequent operation won't return EPERM.

最好只是尝试打开您需要的内容并检查EPERM. 检查stat()access()不保证后续操作不会返回 EPERM。

回答by dmeister

In the simple case, both are functionally equivalent for our matter. Also, access()would not be much faster or so as the same data structure (the inode) much be fetched.

在简单的情况下,对于我们的问题,两者在功能上是等效的。此外,access()不会快得多,因为相同的数据结构(inode)会被提取很多。

However, if access control lists (ACL) are used on the system, access will process these while you have no way to check ACLs with the statdata.

但是,如果系统上使用了访问控制列表 ( ACL),访问将处理这些列表,而您无法使用stat数据检查 ACL 。

回答by Kevin

These two code snippets are not identical and will produce materially different results.

这两个代码片段并不相同,会产生截然不同的结果。

Firstly, your stat call only checks the owner's permission bits. If the user running this code does not own the file in question, this is not the right set of bits to check.

首先,您的 stat 调用仅检查所有者的权限位。如果运行此代码的用户不拥有相关文件,则这不是要检查的正确位集。

Secondly, even if we assume the calling user is the owner, we also need to figure out what we mean by "calling user." As far as open(2)and its friends are concerned, the calling user is the number returned by geteuid(2), that is, the effective user ID. This is what open uses to determine whether to allow opening a file. As far as access(2)is concerned, the calling user is the number returned by getuid(2), that is, the real user ID. This is what access uses to determine whether to report success. The real and effective UIDs can differ, particularly when running a binary with the setuid bit enabled or when the programmer is doing something particularly clever (and probably ill-advised IMHO).

其次,即使我们假设呼叫用户是所有者,我们也需要弄清楚我们所说的“呼叫用户”是什么意思。就open(2)其朋友而言,主叫用户是 返回的号码geteuid(2),即有效用户ID。这是 open 用于确定是否允许打开文件的内容。就其access(2)而言,主叫用户是 返回的号码getuid(2),即真实用户 ID。这是 access 用来确定是否报告成功的内容。实际和有效的 UID 可能不同,特别是在运行启用了 setuid 位的二进制文件时,或者当程序员正在做一些特别聪明的事情时(恕我直言,可能是不明智的)。

(Meanwhile, stat()doesn't care about the calling user one way or the other, except insofar as it needs execute permission on the containing directory to do its job. For that purpose it checks the EUID).

(同时,stat()不关心调用用户的一种或另一种方式,除非它需要对包含目录的执行权限才能完成其工作。为此,它会检查 EUID)。

Finally, as has been pointed out in multiple answers, both code snippets may be vulnerable to TOCTTOUbugs, depending on what you do with the results. All in all, the safest way to determine whether an action is permitted is to attempt that actionand check whether it failed.

最后,正如在多个答案中指出的那样,这两个代码片段都可能容易受到TOCTTOU错误的影响,具体取决于您对结果的处理方式。总而言之,确定某个操作是否被允许的最安全方法是尝试该操作并检查它是否失败。