【问题标题】:Creating a file with open() or creat() has fewer permission bits set than I asked for使用 open() 或 creat() 创建文件的权限位设置比我要求的要少
【发布时间】:2012-09-12 15:08:30
【问题描述】:

我正在编写一个程序来模拟 cp 实用程序。但是,我无法使文件权限正常工作。我知道它们存储在结构stat 中,并存储在st_mode 字段中stat

我的问题是我没有获得组或其他类别的写权限,即即使源文件是-rwxrwxrwx,我也获得了-rwxr-xr-x 作为文件的权限。我设置权限的语句如下。

if ( (dest_fd = open(dest_file, O_WRONLY|O_CREAT, (stats.st_mode & S_IRUSR)|(stats.st_mode & S_IWUSR)|(stats.st_mode & S_IXUSR)|(stats.st_mode & S_IRGRP)|(stats.st_mode & S_IWGRP)|(stats.st_mode & S_IXGRP)|(stats.st_mode & S_IROTH)|(stats.st_mode & S_IWOTH)| (stats.st_mode & S_IXOTH))) < 0)
    {
            printf("There was a problem opening the destination file.");
            exit(EXIT_FAILURE);
    }//ends the if statement opening the destination file.

【问题讨论】:

  • umask 惹你生气了吗?无论您在open 中设置什么权限,内核都会应用unmask 并(可能)删除一些权限。将umask设置为000后试一试。
  • "There was a problem opening the destination file." 是无用错误消息的典型示例。 man perror

标签: c unix file-io permissions umask


【解决方案1】:

到目前为止的答案是正确的,问题是umask,而不是清除umask(如果您的程序是多线程的或者您可能正在调用任何创建文件的库函数,这很危险)我会将umask 视为不允许修改的用户配置变量,而是在创建文件后调用fchmod 以赋予它们所需的最终权限。无论如何,这对于授予某些权限(例如 suid/sgid)可能是必要的,一些内核在文件被修改时会删除这些权限。我最初也会使用模式0600 创建文件,这样在打开它和更改权限之间没有竞争条件,在此期间另一个用户可以获得文件的打开句柄。

【讨论】:

  • 但是请注意,我的解决方案在理论上确实具有稍差的性能,因为它添加了额外的系统调用。我认为安全是值得的,至少在大多数情况下是这样。在不需要的情况下,您可以通过提前检查 umask 并保存它来优化它,然后仅在 umask 会影响传递给 open 的模式时调用 fchmod
  • 这是我的理解,我可能是错的,因为我只是在学习,如果你用 O_CREAT 打开一个带有“open”的文件,没有竞争条件,因为它是一个原子过程。他们取出 CREAT 函数来消除竞争条件并将其添加到公开调用中。
  • oldmask = umask(newmask);打开(..., ...); umask(旧掩码); -- 这应该会提高效率(特别是如果要创建多个文件)(并且我假设该进程没有运行可能会更改掩码的其他线程)
  • @mah:我的重点是这样做是不安全的。此外,两个 umask 系统调用的成本可能与一个 fchmod 系统调用一样多...
  • @tpar44:我所说的竞争条件是,如果你创建一个模式为0644 的文件,那么在你开始编写文件之前,立即将fchmod 转换为模式0600,还有一个在此窗口期间,另一个用户可以获得打开的文件描述符进行读取,并且即使在fchmod 之后,该文件描述符仍将继续可用,从而允许攻击者读取您的文件的内容。
【解决方案2】:

问题的原因是

创建文件的权限为(mode &amp; ~umask)

通常,umask022,因此禁止创建全局可写文件。

【讨论】:

    【解决方案3】:

    *nix 屏蔽掉您创建的文件中的模式位,但您可以使用umask() 函数更改屏蔽。 man umask(可能是man 2 umask)了解详情。

    【讨论】:

      【解决方案4】:

      您可以使用chmod(2) 系统调用来更改现有文件或目录的权限,或使用fchmod(2) 来设置给定打开文件描述符的权限。

      为了更安全并防止利用可能的竞争条件,您可以在创建文件时使用一组非常严格的权限,然后使用chmod(2) 恢复原始权限。这就是cp -a 所做的(除了它使用默认权限创建文件):

      $ strace cp -a file file1
      ...
      open("file1", O_WRONLY|O_TRUNC)       = 4
      ...
      fchmod(4, 0100640)                    = 0
      ...
      

      chmod(2)fchmod(2) 不受 umask 值的影响。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-08-21
        • 1970-01-01
        • 2011-01-15
        • 2017-08-02
        • 2015-10-24
        • 2019-11-13
        • 2013-08-25
        • 1970-01-01
        相关资源
        最近更新 更多