linux程式設計之mprotect

2021-06-01 12:15:07 字數 1487 閱讀 4998

mmap 的第三個引數指定對記憶體區域的保護,由標記讀、寫、執行許可權的 prot_read、prot_write 和 prot_exec 按位與操作獲得,或者是限制沒有訪問許可權的 prot_none。如果程式嘗試在不允許這些許可權的本地記憶體上操作,它將被 sigsegv 訊號(segmentation fault,段錯誤)終止。

在記憶體對映完成後,這些許可權仍可以被 mprotect 系統呼叫所修改。mprotect 的引數分別為記憶體區間的位址,區間的大小,新的保護標誌設定。所指定的記憶體區間必須包含整個頁:區間位址必須和整個系統頁大小對齊,而區間長度必須是頁大小的整數倍。這些頁的保護標記被這裡指定的新保護模式替換。

獲得頁面對齊的記憶體

應注意的是, malloc 返回的記憶體區域通常並不與記憶體頁面對齊,甚至在記憶體的大小是頁大小整數倍的情況下也一樣。如果您想保護從 malloc 獲得的記憶體,您不得不分配乙個更大的記憶體區域並在其中找到乙個與頁對齊的區間。

您可以選擇使用 mmap 系統呼叫來繞過 malloc 並直接從 linux 核心中分配頁面對齊記憶體。

mmap通過對映 /dev/zero 來分配記憶體頁。記憶體將被初始化為可讀和可寫模式。

int fd = open (「/dev/zero」, o_rdonly);

char* memory = mmap (null, page_size, prot_read | prot_write, map_private, fd, 0);

close (fd);

然後,您的程式可以使用 mprotect 把它變成唯讀:

mprotect (memory, page_size, prot_read);
有一種監控記憶體訪問的高階技巧,可以通過利用 mmap 和 mprotect 保護目標記憶體區間,然後當程式訪問時候接收並處理 linux 系統傳送的 sigsegv 訊號。** 展示了這個技巧。

**使用mprotect檢測記憶體訪問

#include #include #include #include #include #include #include #include static int alloc_size;

static char* memory;

void segv_handler (int signal_number)

int main ()

上述程式按照如下步驟執行:

程式為 sigsegv 建立乙個訊號處理控制代碼。

程式通過對映 /dev/zero 分配乙個記憶體分頁,然後通過寫入資料的方式獲得乙個私有複本。

程式通過呼叫帶 prot_none 許可權的 mprotect 保護了記憶體。

當程式在後續執行中寫入記憶體時,linux 向程序傳送 sigsegv,這個訊號被 segv_handler 控制代碼接收處理。這個控制代碼將解除記憶體保護,因而程式記憶體訪問得以繼續。

當訊號控制代碼執行完成時,程式控制權返回 main 函式,程式將使用 munmap 來釋放記憶體。

Linux程式設計之fork

fork 建立乙個子程序 建立失敗返回負值 同時會有不同的錯誤碼 errno eagain 系統程序個數限制 enomem 申請記憶體失敗 enosys 系統平台不支援 建立成功將會返回兩個值 0 子程序的返回值,說明當前程式在子程序執行 0 父程序的返回值,說明當前程式在父程序執行,返回值為生成子...

linux程式設計之檢視幫助

想要在linux下獨擋一面的程式設計,有一技能必須掌握,那就是檢視幫助。要檢視乙個命令的幫助有兩個方法 這兩種方式一般命令都會有其中一種形式,有些兩種形式都有,而它們的輸出也很類似,都會告訴你命令的用法和命令支援的選項,比如 g help man g 命令g help輸出中第一句就是 usage g...

Linux網路程式設計之廣播

1.概念 前面介紹的tcp,udp都是單播方式,即一對一.而廣播是一台主機向區域網內的所有主機傳送資料。這時,同一網段的所有主機都能接收到資料。傳送廣播包的步驟大致如下 1 確定乙個傳送廣播的介面,如eth0 2 確定廣播的位址,通過ioctl函式,請求碼設定為siocgifbrdaddr得到廣播的...