分段故障只是爲了瞭解事情是如何工作的,我想分配從內核的某些內存mmap
,然後設置保護位,使得任何存儲器存取導致分段故障,之後我想嘗試設置保護位以使分段故障不再發生。試圖引起MMAP
到的mprotect調用失敗,並在si_addr
地址是錯誤的,即使對於sigaction
Linux手冊頁說,siginfo
結構的si_addr
函數包含導致錯誤的地址。並且地址不是在main()
函數中分配的地址。 的代碼工作正常在Mac
#define _XOPEN_SOURCE
#include <iostream>
#include <signal.h>
#include <ucontext.h>
#include <sys/mman.h>
#include <string.h>
#include <cstdlib>
using std::cout;
using std::cerr;
using std::endl;
void handle_signal(int signal_number, siginfo_t* signal_info, void* context);
void register_signal_handler();
int counter = 0;
int main() {
register_signal_handler();
int* page_mapped = (int*) mmap(nullptr, 100, PROT_NONE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (page_mapped == MAP_FAILED) {
cerr << "mmap failed" << endl;
}
cout << "page mapped is " << reinterpret_cast<uintptr_t>(page_mapped)
<< endl;
// cause the segmentation fault
cout << *page_mapped << endl;
return 0;
}
void handle_signal(int, siginfo_t* siginfo, void*) {
cout << "Handled a segmentation fault" << endl;
cout << "The segmentation fault was caused by the address "
<< reinterpret_cast<uintptr_t>(siginfo->si_addr) << endl;
if (mprotect(siginfo->si_addr, 100, PROT_READ | PROT_WRITE) == -1) {
cerr << "mprotect failed" << endl;
exit(1);
}
// stop an infinite loop
++counter;
if (counter == 3) {
cerr << "Counter got to 3, probably going into an infinite loop.. "
"stopping" << endl;
exit(1);
}
}
void register_signal_handler() {
struct sigaction sigaction_information;
memset(&sigaction_information, 0, sizeof(struct sigaction));
sigaction_information.sa_sigaction = &handle_signal;
sigaction(SIGSEGV, &sigaction_information, nullptr);
}
* SIGSEGV信號處理程序應該改變機器狀態*爲什麼如果信號處理程序從頁面中刪除導致段錯誤的保護(因此重新啓動相同的機器指令不應該重新發出相同的信號),這是必要的? – Leon
更改保護正在改變機器狀態(例如,在MMU中)。 –
那麼如何獲得mprotect來正確保護導致分段錯誤的地址? – Curious