【问题标题】:File stat() vs access() to check permissions on a directory文件 stat() 与 access() 检查目录的权限
【发布时间】:2011-10-28 14:43:14
【问题描述】:

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

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

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

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

【问题讨论】:

  • 你的代码有点问题...access(directory, R_OK && W_OK) 应该是access(directory, R_OK|W_OK)。也没有理由计算(stats.mode) & (0777);你可以直接使用stats.mode。也就是说,这些方法之间在功能上没有区别。
  • 如果您想要可移植代码的另一个问题:在 POSIX 下,您需要验证当前用户是否特别具有这些权限;您的测试仅检查目标的权限,而不检查它是否适用于当前用户。

标签: c++ file-io stat


【解决方案1】:

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

请注意,您这样做是在制造一场比赛。在调用stat()/access() 和实际尝试使用该目录时,权限可能会发生变化。该死的,那个时候甚至可以删除并重新创建目录。

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

【讨论】:

  • 来自手册页:“使用 access() 来检查用户是否被授权在使用 open(2) 实际打开文件之前打开文件,因为用户可能会利用短检查和打开文件以对其进行操作之间的时间间隔。"
  • 或者如果你需要文件的统计信息,那么open文件并使用fstat就可以了。至少那时您知道统计信息与您正在处理的文件相同。
  • @Zan:除了检查读取和/或写入权限之外...如果open 成功,显然您至少已经拥有其中一个:-)。 (编辑:好的,所以我想您可以使用O_SEARCH 打开一个目录。但是权限检查的结果将如何处理?接受 Adam 的建议并简单地尝试所需的操作本身更有意义。)
  • @Nemo:好点。我在考虑其他事情,比如大小或所有权,但对于读/写访问来说,这并不重要。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    这两个代码sn-ps不相同,会产生本质上不同的结果。

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2019-12-02
      • 1970-01-01
      • 1970-01-01
      • 2012-11-15
      • 1970-01-01
      • 2010-11-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多