儘管處於非特權模式,但 mmap'ing /dev/mem 如何運作?

儘管處於非特權模式,但 mmap'ing /dev/mem 如何運作?

據我了解,用戶空間程式運行在非特權模式下,因此無法直接存取記憶體或 I/O。

那麼當我們在用戶空間程式中mmap /dev/mem 時,究竟該如何直接存取記憶體或I/O 位置呢?

例如:

int fd = 0;
u8 leds = 0;
fd = open("/dev/mem", O_RDWR|O_SYNC);
leds = (u8 *)mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x80840000);

這是嵌入式設備中非常常用的技巧。

現在該變數leds可以即時使用來存取可能存在於 0x80840000 處的任何裝置。

我們將不再使用任何系統呼叫來存取該位址。

甚至像

leds[0x20] = val;

會工作。

但是特權操作,例如直接從 I/O 位址讀取/寫入,只能透過系統呼叫將處理器置於特權模式來實現。

來源

答案1

允許非特權進程存取/dev/mem確實是安全問題,不應該被允許。

在我的系統上,ls -l /dev/mem看起來像這樣:

crw-r----- 1 root kmem 1, 1 Sep  8 10:12 /dev/mem

所以root可以讀寫它,該kmem組的成員(恰好沒有)可以讀它但不能寫它,其他人根本無法打開它。所以這應該是安全的。

如果你的/dev/mem和我的一樣,你的非特權進程根本不應該能夠打開該文件,更不用說mmap它了。

檢查您系統上的權限/dev/mem以確保它們是安全的!

答案2

使用者程序(無論是以 root 使用者或非特權使用者執行)可見的位址都是虛擬位址,它們由 MMU 透過頁表對應到實體位址。設定頁表是特權操作,只能由核心程式碼執行;然而,一旦設定了頁表,就允許在使用者模式下存取記憶體。

具體來說,您的程式碼用於mmap請求核心設定頁表以允許存取給定範圍的實體記憶體。核心檢查進程的權限(它具有讀取/寫入存取權限/dev/mem)並設定頁表以允許其存取實體記憶體。

答案3

的值leds是一個虛擬位址。只要它在目前進程的使用者空間中,進程就可以直接透過指令存取它,leds[0] = val而不必處於特權模式,無論這個虛擬位址對應到 RAM 中的哪個位置

相關內容