簡體   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