繁体   English   中英

root 无法打开 NamedTemporaryFile 创建的文件

[英]root can't open file created by NamedTemporaryFile

我有一个在 Linux 上运行的 Python 脚本,它执行类似的操作

with tempfile.NamedTemporaryFile() as output:
    permissions = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH
    os.chmod(output.name, permissions)
    subprocess.run(f'sudo ./some_executable -f {output.name}', shell=True)

其中some_executable是一个 C 程序,其中包含

fd = open(output_file, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if ( fd < 0 ) {
    perror("open");
    // bail
}

some_executable打印

open: Permission denied

如果我不以root身份运行或不将O_CREAT添加到open ,它就可以工作。

我错过了一些明显的东西吗?

该错误与“C 程序正在尝试打开()已被另一个进程打开的文件”无关。 该问题完全是由/tmp对临时文件的默认使用、该目录的特殊语义以及 Linux 中内置的一些保护措施引起的(我将在此答案的末尾解释)。

您可以通过修改代码以在本地目录中创建一个临时文件来验证这一点:

with tempfile.NamedTemporaryFile(dir=".") as output:
    permissions = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH
    os.chmod(output.name, permissions)
    subprocess.run(f'sudo ./some_executable -f {output.name}', shell=True)

此代码将无错误地运行。


您看到的错误是由三件事共同引起的:

  1. 您正在/tmp中创建一个文件,该文件是世界可写的,并且设置了“粘性”位。

  2. 您正在使用O_CREAT打开文件

  3. 由于 kernel 4.19,Linux 具有protected_regular sysctl:

    这种保护类似于protected_fifos,但它避免了写入攻击者控制的常规文件,程序预计会在其中创建一个文件。

    当设置为“0”时,写入常规文件不受限制。

    当设置为“1”时,不允许O_CREAT在世界可写粘性目录中我们不拥有的常规文件上打开,除非它们归目录所有者所有。

    当设置为“2”时,它也适用于组可写粘性目录。

阅读上述文档时,您会遇到“不允许 O_CREAT 打开我们在世界可写粘性目录中不拥有的常规文件”。 我敢肯定,如果您检查fs.protected_regular sysctl 的值,您会发现它是12

解决方案是:

  • /tmp以外的地方创建临时文件。
  • fs.protected_regular sysctl 设置为0

我会用上面演示的第一个解决方案 go 。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM