Это очень похоже на домашнюю работу, которую я когда-то делал. В основном у меня был список «страниц» и список «фреймов» со связанной информацией. Используя SIGSEGV
, я бы улавливал ошибки и при необходимости изменял защитные биты памяти. Я включу части, которые вы можете найти полезными.
Создать отображение. Изначально у него нет разрешений.
int w_create_mapping(size_t size, void **addr)
{
*addr = mmap(NULL,
size * w_get_page_size(),
PROT_NONE,
MAP_ANONYMOUS | MAP_PRIVATE,
-1,
0
);
if (*addr == MAP_FAILED) {
perror("mmap");
return FALSE;
}
return TRUE;
}
Установить обработчик сигнала
int w_set_exception_handler(w_exception_handler_t handler)
{
static struct sigaction sa;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGSEGV);
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV, &sa, &previous_action) < 0)
return FALSE;
return TRUE;
}
Обработчик исключений
static void fault_handler(int signum, siginfo_t *info, void *context)
{
void *address; /* the address that faulted */
/* Memory location which caused fault */
address = info->si_addr;
if (FALSE == page_fault(address)) {
_exit(1);
}
}
Повышение защиты
int w_protect_mapping(void *addr, size_t num_pages, w_prot_t protection)
{
int prot;
switch (protection) {
case PROTECTION_NONE:
prot = PROT_NONE;
break;
case PROTECTION_READ:
prot = PROT_READ;
break;
case PROTECTION_WRITE:
prot = PROT_READ | PROT_WRITE;
break;
}
if (mprotect(addr, num_pages * w_get_page_size(), prot) < 0)
return FALSE;
return TRUE;
}
Я не могу публично сделать все это доступным, поскольку команда, скорее всего, снова использует ту же домашнюю работу.