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

Dan*_*ien 1 c security symlink race-condition posix-api

我希望能够安全地在不支持的系统上open进行模拟。我可以通过以下方式在某种程度上实现我的要求:O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOWO_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOWO_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);
Run Code Online (Sandbox Code Playgroud)

但随后我引入了竞争条件和可能的安全问题。

我想过也许创建一个虚拟文件,只有用户能够写入,有点像touching filename,进行lstat检查,然后chmod在完成写入后使用(以更正文件模式位),但我可能会忽略一些主要的东西(例如,如果文件filename存在,不是常规文件,或者已经是符号链接)。

你怎么认为?

caf*_*caf 5

你的提案仍然存在竞争条件:

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

O_TRUNC您可以通过调用fstat()打开的文件描述符以及lstat()路径并确保.st_dev和.st_ino成员相同来修复此问题。

然而,如果您使用的是马洛里(Mallory)O_TRUNC,那么当您发现欺骗时,为时已晚,这将不起作用 - 马洛里(Mallory)已经诱导您截断了您的重要文件之一。

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

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