在没有此标志的系统上模拟 O_NOFOLLOW 的好方法是什么?
我希望能够安全地使用 O_CREAT | 模拟
和 open
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
检查,然后在我完成写入后使用 chmod (以更正文件模式位),但我可能会忽略一些主要内容(例如,如果 filename
处的文件存在,则不是常规文件,或者已经是符号链接)。
你怎么认为?
I would like to safely be able to simulate open
with O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW
and O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW
on systems that do not support O_NOFOLLOW
. I can somewhat achieve what I am asking for with:
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);
but then I introduce a race condition and possibly a security problem.
I thought about maybe creating a dummy file with only the user being able to write, kind of like touch
ing filename
, doing the lstat
check, and then using chmod
after I finish writing (to correct the file mode bits), but I could be overlooking something major (e.g. if the file at filename
exists, is not a regular file, or is already a symbolic link).
What do you think?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你的提案仍然存在竞争条件:
O_CREAT
open()
链接;lstat()
测试,该测试通过(不是链接);对于非
O_TRUNC
情况,您可以通过在打开的文件描述符上调用fstat()
以及在路径上调用lstat()
来修复此问题,并确保.st_dev
和.st_ino
成员相同。但是,如果您使用
O_TRUNC
,则此方法不起作用 - 当您发现欺骗时,为时已晚 - Mallory 已经诱导您截断您的一个重要文件。我相信在没有
O_NOFOLLOW
支持的情况下消除漏洞的传统方法是:700
创建一个临时目录。如果mkdir()
由于现有目录而失败,则出错(或重试);rename()
自动将临时文件移动到目标名称;Your proposal still has a race condition:
open()
the link withO_CREAT
;lstat()
test, which passes (not a link);You can fix this for the non-
O_TRUNC
case by callingfstat()
on your open file descriptor as well aslstat()
on the path, and ensuring that the.st_dev
and.st_ino
members are the same.However, this doesn't work if you're using
O_TRUNC
- by the time you've discovered the deception, it's too late - Mallory has already induced you to truncate one of your important files.I believe the traditional way to eliminate the hole without
O_NOFOLLOW
support is:700
. Error (or retry) ifmkdir()
fails due to existing directory;rename()
to atomically move the temporary file to the target name;