在没有此标志的系统上模拟O_NOFOLLOW的好方法是什么?

时间:2010-05-26 22:48:03

标签: c security race-condition symlink posix-api

我希望能够安全地在不支持open的系统上使用O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOWO_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW模拟O_NOFOLLOW。我可以在某种程度上实现我的要求:

struct stat lst;
if (lstat(filename, &lst) != -1 && S_ISLNK(lst.st_mode)) {
    errno = ELOOP;
    return -1;
}

mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, mode);

然后我介绍了竞争条件,可能还有安全问题。

我想过可能只创建一个只有用户能够编写的虚拟文件,有点像touch ing filename,进行lstat检查,然后使用{{1我写完之后(纠正文件模式位),但我可能会忽略一些主要的东西(例如,如果chmod处的文件存在,不是常规文件,或者已经是符号链接)。< / p>

您怎么看?

1 个答案:

答案 0 :(得分:4)

您的提案仍有竞争条件:

  • Mallory创建了他希望您关注的链接;
  • open()O_CREAT;
  • 的链接
  • Mallory用常规文件替换链接;
  • 您进行lstat()测试,该测试通过(不是链接);
  • Mallory将链接替换为常规文件。

您可以通过在打开的文件描述符上调用O_TRUNC以及路径上的fstat()来解决非lstat()案例的问题,并确保.st_dev.st_ino成员是一样的。

然而,如果您使用O_TRUNC,这不起作用 - 当您发现欺骗时,为时已晚--Mallory已经诱使您截断您的一个重要文件。

我认为在没有O_NOFOLLOW支持的情况下消除漏洞的传统方法是:

  • 使用模式700创建临时目录。如果mkdir()由于现有目录而失败,则出错(或重试);
  • 在临时目录中创建新文件;
  • 使用rename()以原子方式将临时文件移动到目标名称;
  • 删除临时目录。