使用 noexec 選項在文件系統上執行 bash 腳本或 ac 二進製文件
任何人都可以詳細解釋以下內容。假設我正在安裝一個帶有
noexec
以下選項的目錄:mount -o noexec /dev/mapper/fedora-data /data
所以為了驗證這一點,我跑了
mount | grep data
:/dev/mapper/fedora-data on /data type ext4 (rw,noexec,relatime,seclabel,data=ordered)
現在
/data
我正在創建一個簡單的腳本hello_world
,如下所示:#!/bin/bash echo "Hello World" whoami
所以我使腳本可執行
chmod u+x hello_world
(但這對帶有noexec
選項的文件系統沒有影響),我嘗試執行它:# ./hello_world -bash: ./hello_world: Permission denied
但是,準備
bash
文件會產生:# bash hello_world Hello World root
所以我創建了一個簡單
hello_world.c
的內容如下:#include <stdio.h> int main() { printf("Hello World\n"); return 0; }
編譯它使用
cc -o hello_world hello_world.c
現在執行:
# ./hello_world -bash: ./hello_world: Permission denied
所以我嘗試使用
/lib64/ld-linux-x86-64.so.2 hello_world
錯誤:
./hello_world: error while loading shared libraries: ./hello_world: failed to map segment from shared object: Operation not permitted
所以這當然是正確的,因為
ldd
返回以下內容:ldd hello_world ldd: warning: you do not have execution permission for `./hello_world' not a dynamic executable
在另一個
noexec
安裝選項不適用的系統上,我看到:ldd hello_world linux-vdso.so.1 (0x00007ffc1c127000) libc.so.6 => /lib64/libc.so.6 (0x00007facd9d5a000) /lib64/ld-linux-x86-64.so.2 (0x00007facd9f3e000)
現在我的問題是:為什麼在帶有
noexec
選項的文件系統上執行 bash 腳本而不是c
編譯程序?引擎蓋下發生了什麼?
兩種情況的情況是一樣的:直接執行文件,需要設置執行位,文件系統不能掛載noexec。但是這些東西並不能阻止任何東西讀取這些文件。
當 bash 腳本以 as 執行
./hello_world
並且文件不可執行(沒有 exec 權限位或文件系統上的 noexec )時,甚至不會檢查#!
該行,因為系統甚至不會載入文件。該腳本永遠不會在相關意義上“執行”。在這種情況下
bash ./hello_world
,noexec 文件系統選項只是普通的並不像您希望的那樣聰明。執行的bash
命令是/bin/bash
,並且/bin
不在帶有noexec
. 所以,它執行沒有問題。系統並不關心 bash(或 python 或 perl 或其他)是解釋器。它只是執行您給出的命令 (/bin/bash
) 並帶有恰好是一個文件的參數。對於 bash 或其他 shell,該文件包含要執行的命令列表,但現在我們“過去”了任何要檢查文件執行位的內容。該檢查不對以後發生的事情負責。考慮這種情況:
$ cat hello_world | /bin/bash
……或者對於那些不喜歡毫無意義地使用貓的人:
$ /bin/bash < hello_world
#!
當您嘗試將文件作為命令執行時,文件開頭的“shbang”序列只是一個很好的魔法,可以有效地做同樣的事情。您可能會發現這篇 LWN.net 文章很有幫助:程序如何執行。