2012-05-09 123 views
8

我知道copy_to_user/copy_from_user,get_user/put_user功能是爲了這個目的。如何從Linux內核訪問用戶空間內存?

我的問題是,給定一個用戶空間地址/指針,我怎樣才能訪問內核地址指向的數據?

我可以想象,首先我必須確保包含頁面應該在物理內存中(而不是在磁盤中)。

下一步是什麼?我能否使用*p,其中p是指向某些用戶空間數據的指針,直接引用數據?

或者我必須首先調用kmap來將包含物理頁面框架映射到內核虛擬地址空間嗎?爲什麼?

回答

4

指針本身還不夠!您需要知道指針「屬於」哪個進程。

當進程被搶佔時,指針指向另一個進程的地址空間。地址可能不再映射,yadda yadda,

如果該進程在您訪問數據時是當前進程,那麼您應該使用copy_to_user/copy_from_user函數。

如果可以調度進程,可以嘗試mlock()RAM中的頁面,找出頁面的物理RAM地址。每當你想訪問它時,你將該物理頁面映射到內核虛擬地址。

注:

  • 惡意進程可以次munlock()的頁面,誘騙您訪問一個錯誤的RAM頁。
  • 我不確定mlock()語義要求下劃線的RAM頁面不能改變。
  • 內核應該能夠將一個頁面鎖定到RAM中,我不熟悉mm子系統。
3

不同的用戶空間應用程序有不同的頁面表。 1)你需要獲得用戶空間程序pid。 2)在pid的頁表中搜索addree。

下面是將用戶空間虛擬地址轉換爲物理地址的示例代碼。 它適用於x86平臺。

taskpid = find_get_pid(curpid); 
task = pid_task(taskpid, PIDTYPE_PID); 
mm = get_task_mm(task); 
down_read(&mm->mmap_sem); 

start_vaddr = vaddr; 
end_vaddr = 0xC0000000; 

while(start_vaddr < end_vaddr){ 
    u32 end; 

    end = ((start_vaddr + PMD_SIZE) & PMD_MASK); 

    if(end < start_vaddr || end > end_vaddr) 
     end = end_vaddr; 

    ret = walk_pgd(start_vaddr, end, mm); 
    if(ret != 0){ 
     printk("ret: %08x \n", ret); 
     break; 
    } 

    start_vaddr = end; 

} 

up_read(&mm->mmap_sem); 

paddr = ret; 
kaddr = __va(paddr); 
mmput(mm); 
+0

好點,代碼邏輯很好。但我想有一些哈希表或類似的數據結構,給定一個虛擬地址,可以幫助您快速找到物理頁面。有一個缺陷:kaddr = __va(paddr);這條線只有在paddr駐留在低內存時纔有效,對吧? – Infinite

+0

paddr表示物理地址,所以始終存在於內存中。 kaddr表示內核地址。在Linux內核中,define是'#define __va(x)((void *)((unsigned long)(x)+ PAGE_OFFSET))'。內核地址內存映射並不複雜,只是一個PAGE_OFFSET。 (在x86模式下應該是0xC0000000)。 還有其他方法可以獲取地址。用戶空間應用程序可以通過/ proc//pagemap訪問內核地址來獲取頁面信息。如果能得到PFN,它也可以得到內核地址。 – richliu

0

你需要follow的地址就能獲取相應的page結構(見follow_page的例子)。接下來,獲取page結構,您需要通過kmapkmap_atomic將其映射到內核地址空間。

3

您可能會覺得這很有用。

讓我們重複的buff參數的讀取和寫入方法是 用戶空間指針。因此,它不能直接由 內核代碼解除引用。有此限制的幾個原因:

  • 根據其架構您的驅動器上運行,並 內核是如何配置的,而在內核模式下運行 用戶空間指針可能無效所有。該地址可能沒有映射,也可能指向其他一些隨機數據。

  • 即使指針確實意味着在內核空間同樣的事情, 用戶空間內存分頁,系統調用時有問題的內存可能不 駐留在RAM中。嘗試引用 用戶空間內存直接可能會產生頁面錯誤,這是內核代碼不允許執行的內容錯誤,即 。結果將是 「oops」,這將導致系統調用 的進程死亡。

  • 有問題的指針由用戶程序提供,其中 可能有問題或惡意。如果你的驅動永遠盲目取消引用 用戶提供的指針,它提供了一個開放的門道允許 用戶空間程序來訪問或 系統的任何地方覆蓋內存。如果您不希望對用戶系統的安全性產生影響,則不能直接取消引用 用戶空間指針。

來源:http://www.makelinux.net/ldd3/chp-3-sect-7

這麼說,我是我自己很想知道,如果用戶空間地址確實是有效的,並沒有上述報考條件會發生什麼......

相關問題