2012-01-25 87 views
3

x86_64體系結構上Linux 3.0上的進程具有64位虛擬地址空間。x86_64 Linux 3.0:無效的內存地址

很明顯0被保證是一個無效的內存地址[見下面的定義]在這個地址空間,因爲這是用來表示一個NULL指針。

還有什麼其他的64位數字(如果有的話)永遠不會是有效的內存地址,爲什麼?

例如,1可以是有效的地址嗎?那麼2^64-1

定義:你是什麼意思「保證是無效的內存地址」?

void deref_and_assign(uint64_t i) 
{ 
    char* p = (char*) i; 
    *p = 42; 
} 

對於這個問題的目的,保證無效的內存引用意味着函數deref_and_assign總會提高一個SIGSEGV

+0

出於好奇,爲什麼這是你要找的信息嗎?這可能不是您應該基於代碼編寫的信息。當然,對於研究,任何事情都會發生。;) –

+0

好奇心不錯。我正在實現一個不可移植的動態類型(對於Linux/x86_64目標),並且我正在考慮我的選項,只要將超前的64位值「代碼單元」過載即可。一種方法是將代碼單元劃分爲(a)即時值和(b)指向更多信息的指針。作爲一個簡單的例子,你可以表示一個動態數字/字符串類型,如下所示:(0-4095)它是一個數字,表示爲整數0,1,2 ... 4095; (4096-2^64)這是一個指向空終止字符串的指針。對於一個更真實世界的例子來看看rubys VALUE類型是如何工作的。 ruby.tgz中的ruby.h –

回答

4

如果啓用了頁面轉換並且虛擬地址0處的內存不可訪問(由於物理內存映射到虛擬地址空間的方式),在x86/64上,1 ... 4095將不可訪問因爲所有這些4096個地址都對應一頁內存,並且它只能作爲一個整體可用或不可用。永遠不要在虛擬地址0映射內存是一個好主意。不映射它將有助於捕獲許多空指針解引用。這裏的CPU會在未映射的位置或要求比當前正在執行的代碼更高權限的位置上生成頁面錯誤(aka #PF)。

在64位模式下,CPU可能實現的虛擬地址位數少於(48+),而64位地址必須包含未實現的位中的全零或全1(值爲0或1,必須與最重要的實現地址位的值相同,所有這些都可以解釋爲地址符號擴展)。這些地址稱爲規範。如果您嘗試使用非規範地址讀取或寫入內存,則會出現一般性保護錯誤(AKA #GP)。

因此,根據操作系統(有效地,在其內存佈局上)和實際的CPU,您可能會提出一系列「無效」內存地址。如果您嘗試從用戶模式應用程序讀取/寫入內核內存,您將獲得#PF。如果您嘗試讀取/寫入未映射的內存(例如,在地址0到4095),您將獲得#PF。如果您嘗試讀取/寫入非規範地址,您將獲得#GP。

這是你要找的那種東西嗎?

+0

是的,0..4095很清楚第一頁不能存在,謝謝。關於48位模式尚不清楚。你能舉一個x86_64/Linux CPU的例子嗎?在我的機器上,我在/ proc/*/maps中看到vsyscall被映射到ffffffffff600000-ffffffffff601000,例如幾乎是vm的頂部。另外:你如何「嘗試」並從用戶空間的內核內存中讀取?所有在用戶空間中用作內存地址的單詞解引用到vm。 –

+0

ffffffffff600000不一定是頂部。我已經提到頂端未實現位是頂層實現位的副本。因此,如果僅實現了48位,則只有ffffff600000部分是「有意義的」,其餘的前16位(ffff)只是最重要的「有意義」位的拷貝,等於1. –

+0

您可以在內核和用戶模式下使用您喜歡的任何地址。但是內存保護機制不會讓你真正從用戶模式代碼中讀取/寫入內核內存。沒有什麼能夠阻止你將任意值(地址)加載到'rbx'中,並試圖執行'mov al,[rbx]'來讀取'al'中包含在'rbx'中的地址的字節值。你可以試試。但是如果沒有足夠的權限,處理器將不會執行這條指令。相反,它會生成#GP或#PF,操作系統將處理該操作,並且此處唯一有意義的操作是終止該應用程序。 –

0

您檢查到Linux進程不能從mmapMAP_FIXED開始於(void*)0的段。

因此,出於實際的目的,您可以放心地假定第一頁0 - 0xfff從不是mmap -ed(頁面的4Kb大小取決於處理器和系統,但通常是4kb)。然後,你可以假設在第一個頁面內取消引用指針(從Linux應用程序內)給出SIGSEGV

同樣在0xffffffffffffffff(即2^64-1)結束最後一頁

+0

mmap(0,4096,PROT_READ | PROT_WRITE,MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,-1,0)返回-1和EPERM,所以不對不對。 –

+0

嗯,我相信我更加正確,因爲我寫過,你可以假設第一頁不是'mmap'-ed。我編輯了我的答案。 –