Ubuntu

dd if=/dev/urandom of=/dev/mem 安全嗎?

  • November 30, 2019

這究竟是做什麼的?我不明白你怎麼能用這個來訪問基本記憶體……似乎有點奇怪。安全嗎?

dd if=/dev/urandom of=/dev/mem

不要在家裡嘗試這個!它可能會使您的系統崩潰,如果您真的不走運,它可能會損壞外圍設備或使您的電腦無法啟動。

實際上,在大多數平台上,它只是因錯誤而失敗,但這取決於硬體架構。除非您以非特權使用者身份執行該命令,否則絕對不能保證這是無害的。對於非特權使用者,該命令完全無害,因為您無法打開/dev/mem.

當您以 root 身份執行命令時,您應該知道自己在做什麼。核心有時會阻止您做一些危險的事情,但並非總是如此。/dev/mem是那些你真正應該知道你在做什麼的潛在危險的事情之一。

我將介紹如何/dev/mem在 Linux 上進行寫入操作。一般原則在其他 Unices 上是相同的,但核心選項之類的東西完全不同。

當程序讀取或寫入設備文件時會發生什麼取決於核心。對設備文件的訪問會在處理該設備文件的驅動程序中執行一些程式碼。例如,寫入/dev/mem呼叫write_mem. drivers/char/mem.c此函式有 4 個參數:表示打開文件的資料結構、指向要寫入的數據的指針、要寫入的字節數以及文件中的目前位置。

請注意,如果呼叫者首先有權打開文件,那麼您只能做到這一點。設備文件通常服從文件權限。的正常權限由/dev/mem擁有crw-r-----root:kmem因此如果您嘗試以非 root 身份打開它進行寫入,您只會得到“權限被拒絕”(EACCESS)。但是,如果您是 root(或者如果 root 更改了此文件的權限),則打開會通過,然後您可以嘗試寫入。

函式中的程式碼進行了write_mem一些健全性檢查,但這些檢查不足以防止一切不良。它所做的第一件事是將目前文件位置轉換*ppos為物理地址。如果失敗(實際上,因為您在具有 32 位物理地址但文件偏移量為 64 位且文件偏移量大於 2^32 的平台上),則寫入失敗並顯示 EFBIG(文件太大)。下一個檢查是要寫入的物理地址範圍在這個特定的處理器架構上是否有效,並且失敗會導致 EFAULT(錯誤地址)。

接下來,在 Sparc 和 m68k 上,第一個物理頁面中寫入的任何部分都被靜默跳過。

我們現在已經到達了主循環,它以塊的形式迭代數據,這些塊可以容納在一個MMU頁面中。 /dev/mem訪問物理記憶體,而不是虛擬記憶體,但是在記憶體中載入和儲存數據的處理器指令使用虛擬地址,因此程式碼需要安排將物理記憶體映射到某個虛擬地址。在 Linux 上,根據處理器架構和核心配置,這種映射要麼永久存在,要麼必須即時生成;這就是xlate_dev_mem_ptr(並且unxlate_dev_mem_ptr撤消所做的任何事情xlate_dev_mem_ptr)的工作。然後函式copy_from_user從傳遞給write系統呼叫,只寫入目前映射物理記憶體的虛擬地址。程式碼發出正常的記憶體儲存指令,這意味著什麼取決於硬體。

在討論對物理地址的寫入之前,我將討論在此寫入之前發生的檢查。在循環內部,如果啟用了核心配置選項(預設情況下是這種情況) ,函式page_is_allowed會阻止對某些地址的訪問:只有允許的地址才能通過 訪問,對於其他地址,寫入失敗並出現 EPERM(不允許操作)。此選項的描述指出:CONFIG_STRICT_DEVMEMdevmem_is_allowed/dev/mem

如果打開此選項,並且 IO_STRICT_DEVMEM=n,/dev/mem 文件只允許使用者空間訪問 PCI 空間以及 BIOS 程式碼和數據區域。這對於dosemu 和X 以及/dev/mem 的所有普通使用者來說已經足夠了。

這是非常以 x86 為中心的描述。事實上,更一般地說,CONFIG_STRICT_DEVMEM阻止訪問映射到 RAM 的物理記憶體地址,但允許訪問不映射到 RAM 的地址。允許的物理地址範圍的細節取決於處理器架構,但所有這些都不包括儲存核心和使用者態程序數據的 RAM。附加選項CONFIG_IO_STRICT_DEVMEM(自 Ubuntu 18.04 起禁用)阻止對驅動程序聲明的物理地址的訪問。

映射到 RAM 的物理記憶體地址。那麼有沒有映射到 RAM 的物理記憶體地址?是的。這就是我在上面承諾的關於寫信給地址的意義的討論。

記憶體儲存指令不一定寫入 RAM。處理器分解地址並決定將儲存分派到哪個外圍設備。(當我說“處理器”時,我包括可能不是來自同一製造商的外圍控制器。)RAM 只是這些外圍設備之一。調度如何完成很大程度上取決於處理器架構,但所有架構的基本原理或多或少都是相同的。處理器基本上分解地址的高位並在一些表中查找它們,這些表基於硬編碼資訊、通過探測某些匯流排獲得的資訊以及軟體配置的資訊來填充。可能會涉及到大量的記憶體和緩衝,但簡而言之,經過這個分解,匯流排,然後由外圍設備處理它。(或者查表的結果可能是這個地址沒有外圍設備,在這種情況下,處理器進入一個陷阱狀態,它在核心中執行一些程式碼,這通常會導致呼叫程序的SIGBUS。)

儲存到映射到 RAM 的地址除了覆蓋之前儲存在該地址的值外,不會“做”任何事情,並承諾稍後在同一地址載入將返回最後儲存的值。但即使是 RAM 也有一些地址不是這樣的:它有一些寄存器可以控制刷新率和電壓等內容。

通常,對硬體寄存器的讀取或寫入操作會執行硬體被程式執行的任何操作。大多數對硬體的訪問都是這樣工作的:軟體(通常是核心程式碼)訪問某個物理地址,該地址到達連接處理器和外圍設備的匯流排,外圍設備完成它的工作。一些處理器(特別是 x86)也有單獨的 CPU 指令,這些指令導致對與記憶體載入和儲存不同的外圍設備的讀/寫,但即使在 x86 上,許多外圍設備也是通過載入/儲存到達的。

該命令dd if=/dev/urandom of=/dev/mem將隨機數據寫入地址 0(以及後續地址,只要寫入成功)映射的任何外設。在實踐中,我希望在許多架構上,物理地址 0 沒有任何外圍設備映射到它,或者有 RAM,因此第一次寫入嘗試失敗。但是,如果在地址 0 處映射了一個外設,或者如果您將命令更改為寫入不同的地址,您將在外設中觸發一些不可預知的事情。隨著地址增加的隨機數據,它不太可能做一些有趣的事情,但原則上它可能會關閉電腦(實際上可能有一個地址這樣做),覆蓋一些導致無法啟動的 BIOS 設置,甚至擊中一些以某種方式損壞它的越野車外圍設備。

alias Russian_roulette='dd if=/dev/urandom of=/dev/mem seek=$((4096*RANDOM+4096*32768*RANDOM))'

引用自:https://unix.stackexchange.com/questions/532381