2011-06-03 52 views
13

我正在使用運行時生成一些機器代碼的應用程序(用C++編寫)(現在Linux,x86-64,但我打算在ARM上遷移)。接下來它將生成的代碼存儲在內存中並通過跳轉到內存位置來執行它。在很長一段時間,我曾與分配可執行內存的問題,但我最後用解決它:在運行時將代碼注入可執行文件

uint8_t *memory = mmap (NULL, length, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 

到目前爲止,它的工作原理,但我不知道,如果是優雅的方式做這樣的事情。我不知道可執行文件加載程序如何執

+1

就是這樣完成的。 – 2011-06-03 19:48:31

+0

[在linux上分配可執行文件的內存](http://stackoverflow.com/questions/3125756/allocate-executable-ram-in-c-on-linux) – ninjalj 2011-06-03 20:51:41

回答

13

這實際上是可執行的加載程序如何執行的操作;在他們的情況下,他們執行文件的mmap,而不是匿名映射,但除此之外它基本上是相同的。

請注意,這是一個好主意,不要有寫和在同一時間執行訪問,因爲它使某些類型的安全漏洞更容易。您可以使用mprotect在初始映射後調整保護標誌。

13

您的解決方案主要是應該做什麼:讓操作系統將頁面視爲可執行文件。但是,某些操作系統會強制執行所謂的W^X策略,其中頁面可以是可寫或可執行的,但不能同時存在。對於這樣的系統(即OpenBSD,但也有修改後的Linux版本),您的mmap()將會失敗。因此,完整的解決方案需要首先分配mmap()PROT_READ | PROT_WRITE的某些頁面,然後在生成代碼時使用mprotect()將頁面切換爲PROT_READ | PROT_EXEC

即使操作系統不強制執行W^X,由於緩存效應,強烈建議您撥打mprotect()的調用(數據訪問和執行在CPU中彼此完全分離;您要確保CPU將使用你剛剛編寫的操作碼而不是之前在RAM中的內容; mprotect()包含必要的魔術)。

相關問題