2015-04-27 51 views
3

我讀過Linux內核中的__user說明符,用於標記函數參數Sparse以檢查函數參數。我可以傳遞一個指向linux內核空間的指針給__user參數嗎?

特別是,鑑於

int foo1(char * buf); 

一個不能將指針傳遞給用戶空間buf

其他方式如何?在

int foo2(char __user * buf); 

可以必須我通過用戶提供的指針?我猜測前者是因爲用戶提供的指針可能真的是任何東西,但我還沒有在任何地方找到正式的__user規範。

回答

3

請記住,__user從根本上意味着指針指向用戶地址空間。它不一定是由用戶提供的,但它確實意味着它不能成爲內核內存的指針。在某些體系結構(如x86和x86_64)上,內核和用戶內存位於相同的地址空間,並且僅通過邊界(即x86中的3G以上的內核)區分。在這些體系結構中,__user主要用作註釋以提醒開發人員應小心處理。然而,這並非總是如此!一些體系結構(如PowerPC)實際上完全爲內核使用單獨的地址空間;在這些體系結構中,__user具有新的重要性,因爲它表示使用特殊功能(如copy_from_user必須來訪問指針。正常的內存訪問根本不起作用,因爲它會試圖取消引用內核地址空間中的指針,在那裏它可能無效。

+0

很好的回答;我的探索更加簡潔。事實上,在例如x86-64用戶空間是一種*模擬*獨立的地址空間。正如我的回答所見,您可以*從內核代碼訪問用戶空間指針。 –

2

A __user指針可能會傳遞到copy_from_user,copy_to_user或類似的東西。

在x86-64的,這些在copy_user_64.S實現:

/* Standard copy_to_user with segment limit checking */ 
ENTRY(_copy_to_user) 
     CFI_STARTPROC 
     GET_THREAD_INFO(%rax) 
     movq %rdi,%rcx 
     addq %rdx,%rcx 
     jc bad_to_user 
     cmpq TI_addr_limit(%rax),%rcx 
     ja bad_to_user 
     ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,X86_FEATURE_ERMS, \ 
       copy_user_generic_unrolled,copy_user_generic_string, \ 
       copy_user_enhanced_fast_string 
     CFI_ENDPROC 
ENDPROC(_copy_to_user) 

/* Standard copy_from_user with segment limit checking */ 
ENTRY(_copy_from_user) 
     CFI_STARTPROC 
     GET_THREAD_INFO(%rax) 
     movq %rsi,%rcx 
     addq %rdx,%rcx 
     jc bad_from_user 
     cmpq TI_addr_limit(%rax),%rcx 
     ja bad_from_user 
     ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,X86_FEATURE_ERMS, \ 
       copy_user_generic_unrolled,copy_user_generic_string, \ 
       copy_user_enhanced_fast_string 
     CFI_ENDPROC 
ENDPROC(_copy_from_user) 

cmpq TI_addr_limit(%rax),%rcx這將確保您的指針是小於或等於current_thread_info()->addr_limit

此限制由set_fs()宏設置,該宏在許多地方被調用。特別地,它可以與USER_DS被稱爲其是定義爲:

#define USER_DS   MAKE_MM_SEG(TASK_SIZE_MAX) 

TASK_SIZE_MAX定義爲:

/* 
* User space process size. 47bits minus one guard page. 
* ... 
*/ 
#define TASK_SIZE_MAX ((1UL << 47) - PAGE_SIZE) 

在X86-64,內核在高(或負)虛擬映射地址空間。所以內核指針會失敗檢查。


總之,我覺得__user指針不能是實際用戶提供,但保證是一個有效的用戶空間地址。我認爲唯一的限制是你必須確保你在當前的上下文中傳遞的指針是有效的(這取決於我們在說什麼,可能隨時改變)。

相關問題