英語

No New Privileges Flag

execve 系統呼叫可以授予新啟動的程式其父程序沒有的特權。最明顯的例子是 setuid/setgid 程式和檔案 capabilities。為了防止父程式也獲得這些特權,核心和使用者程式碼必須小心,防止父程式做任何可能破壞子程式的事情。例如

  • 如果程式是 setuid,動態載入器會以不同的方式處理 LD_* 環境變數。

  • chroot 不允許非特權程序使用,因為它允許從繼承 chroot 的程序的角度替換 /etc/passwd

  • exec 程式碼對 ptrace 有特殊的處理。

這些都是臨時的修復。no_new_privs 位 (自 Linux 3.5 起) 是一種新的通用機制,使程序可以安全地修改其執行環境,使其在 execve 中保持不變。任何任務都可以設定 no_new_privs。一旦設定了該位,它將在 fork、clone 和 execve 中繼承,並且無法取消設定。設定 no_new_privs 後,execve() 承諾不會授予執行 execve 呼叫無法完成的任何操作的許可權。例如,setuid 和 setgid 位將不再更改 uid 或 gid;檔案 capabilities 不會新增到允許的集合中,並且 LSM 不會在 execve 之後放寬約束。

要設定 no_new_privs,請使用

prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);

但請注意:LSM 也可能不會在 no_new_privs 模式下加強對 exec 的約束。(這意味著設定一個通用的服務啟動器在執行守護程序之前設定 no_new_privs 可能會干擾基於 LSM 的沙箱。)

請注意,no_new_privs 不會阻止不涉及 execve() 的特權更改。具有適當特權的任務仍然可以呼叫 setuid(2) 並接收 SCM_RIGHTS 資料報。

到目前為止,no_new_privs 有兩個主要用例

  • 為 seccomp 模式 2 沙箱安裝的過濾器在 execve 中保持不變,並且可以更改新執行的程式的行為。因此,如果設定了 no_new_privs,則只允許非特權使用者安裝此類過濾器。

  • 就其本身而言,no_new_privs 可用於減少非特權使用者可用的攻擊面。如果使用給定 uid 執行的所有內容都設定了 no_new_privs,則該 uid 將無法透過直接攻擊 setuid、setgid 和使用 fcap 的二進位制檔案來提升其特權;它首先需要破壞一些未設定 no_new_privs 位的程式碼。

將來,如果設定了 no_new_privs,則其他潛在的危險核心功能可能會提供給非特權任務。原則上,當設定了 no_new_privs 時,unshare(2)clone(2) 的幾個選項將是安全的,並且 no_new_privs + chroot 比 chroot 本身危險性小得多。