gcc linux 下的 mkdir()/chmod() TOCTOU 竞争条件

问题描述 投票:0回答:1

我在 RHEL 8.x / 9.x 中运行 gcc 'C' 代码,该代码已被标记为具有 'TOCTOU 竞争条件'。

它先执行 mkdir(),然后执行 chmod(),SonarQube 指向 chmod()。

我认为它是在抱怨有人可能在 mkdir() 和 chmod() 之间做坏事,导致替换文件或符号链接被“chmod()”编辑,而不是我创建的新目录。

我执行后续 chmod() 的原因是因为 umask 值将更改我在 mkdir() 上指定的权限,因此 chmod() 可以将文件权限“修复”为我最初要求的内容。

由于我的代码是更大系统的一部分,并且被各种程序作为共享对象中的条目调用,因此我无法修改 umask,因为它会更改整个进程和任何其他线程的 umask同时运行可能会改变其文件创建行为。 (我无法控制可能从同一进程运行的任何其他线程,或用于启动给定进程的 umask)。

我的印象是我无法使用 open() 创建目录(这将允许我在打开的句柄上使用 fchmod() 并可能避免竞争条件)。

是否有一些“标准”方法可以避免这场 TOCTOU 比赛?

仅当尝试在所述子目录中创建文件失败并显示“ENOENT”时,才会真正调用“创建子目录”代码(假设失败原因是子目录不存在)。

(我试图在“/tmp”类型目录中创建这个子目录,该目录在每次系统重新启动时都会被删除。我想要创建的文件将进入我的新子目录,并且该子目录预计在重新启动后第一次调用我的代码时需要创建)。

类似:

strcpy(temp_dir_path, "/tmp/new-dir");
strcpy(f_name, "/tmp/new-dir/xyzzy");

fd = open( f_name,
           O_CREAT | O_RDWR | O_TRUNC,             
           S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 

if (fd == -1)
{
   if (errno == ENOENT)
   {  /***************************************************************/
      /* Presume this is because the sub-directory under /tmp        */
      /* doesn't yet exist. Try to create it.                        */
      /***************************************************************/

      rc = create_subdir(temp_dir_path);

...
c linux gcc sonarqube race-condition
1个回答
0
投票

我执行后续 chmod() 的原因是因为 umask 值将更改我在 mkdir() 上指定的权限,因此 chmod() 可以将文件权限“修复”为我最初要求的内容。

如果您使用

0000
作为
mkdir
的权限参数,那么在新目录创建到 chmod 发生之间,每个人都将
完全无法访问该目录(root 可能除外,但 root 无论如何都是受信任的) ,因此您无需担心任何人利用不正确的权限
在新创建的目录上

据我所知,这里没有系统调用(甚至在

*at

 系列中也没有)创建目录并返回该目录的打开 
O_PATH
/
O_SEARCH
 fd。因此,如果您使用 
0000,那么
 仍然是一场竞赛:有人可能会突然介入并修改 
mkdirchmod
 之间的 
parent
 目录,导致您 
chmod
 做错事。我认为没有任何办法可以避免这场比赛。然而,有两种
应该无懈可击的解决方法:

    如果可以使父目录仅由
  • root
     拥有和写入,则让 
    root
     创建您需要的目录并将其 
    chown
     授予适当的用户。
  • 如果父目录必须是全局可写的,那么请确保它也是“粘性”的(模式1777);那么以其他用户身份运行的进程就无法重命名或删除您的目录。
© www.soinside.com 2019 - 2024. All rights reserved.