我想安全地模拟 openO_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);

但是后来我引入了种族条件,可能是安全问题。

我考虑过可能创建一个虚拟文件,只有用户才能写作,有点像 touching filename, ,做 lstat 检查,然后使用 chmod 完成写作后(纠正文件模式位),但是我可以忽略一些主要的东西(例如,如果文件处于 filename 存在,不是常规文件,也不是符号链接)。

你怎么看?

有帮助吗?

解决方案

您的建议仍然有种族条件:

  • 马洛里(Mallory)创建了他希望您遵循的链接;
  • open() 链接与 O_CREAT;
  • Mallory用常规文件代替链接;
  • 你做你的 lstat() 测试,通过(不是链接);
  • Mallory再次用链接替换了常规文件。

您可以为非 -O_TRUNC 通过打电话 fstat() 在您的打开文件描述符上以及 lstat() 在道路上,并确保 .st_dev.st_ino 成员是一样的。

但是,如果您使用的话,这无效 O_TRUNC - 当您发现欺骗时,为时已晚 - 马洛里已经诱使您截断了一个重要的文件之一。

我相信消除没有漏洞的传统方式 O_NOFOLLOW 支持是:

  • 使用模式创建一个临时目录 700. 。错误(或重试)如果 mkdir() 由于现有目录而失败;
  • 在临时目录中创建新文件;
  • 采用 rename() 原子上将临时文件移至目标名称;
  • 删除临时目录。
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top