Как я могу проверить разрешение страницы в режиме пользователя в C? - PullRequest
1 голос
/ 12 мая 2019

Я в настоящее время внедряю распределенную систему и ее Протокол распределенной общей памяти . Может быть проще, если я смогу проверить разрешение страницы (rwx, сохраненное в pte) определенного виртуального адреса в режиме пользователя .


Что я хочу сделать:

Получить виртуальный адрес. Таким образом, я могу проверить последние 3 бита, хранящиеся в нем, представляющие PROT_READ / PROT_WRITE / PROT_NONE.


Что я сделал:

  1. Пытался использовать собственную ссылку на pmd для получения pte. Не удалось.
  2. Попробуйте другие методы. Глупо записывать все. Я попробовал это, и это сработало, но теперь я хочу улучшить это.

В qemu таких макросов нет

407         pgd_t *pgd;
408         pmd_t *pmd;
409         pte_t *ptep, pte;
410 
411         pgd = pgd_offset(mm, address);
412         if (pgd_none(*pgd) || pgd_bad(*pgd))
413                 goto out;
414 
415         pmd = pmd_offset(pgd, address);
416         if (pmd_none(*pmd) || pmd_bad(*pmd))
417                 goto out;
418 
419         ptep = pte_offset(pmd, address);
420         if (!ptep)
421                 goto out;
422 
423         pte = *ptep;

Таким образом, приведенный выше код не работает для меня, не говоря уже о том, что он работает в режиме ядра.

Предполагается, что в pgd есть собственная ссылка pmd, но я думаю, что нашел неправильный.

// I found it in qemu/roms/qemu-palcode/init.c
#define PAGE_SHIFT 13
#define VPTPTR 0xfffffffe00000000UL
static inline unsigned long
pt_index(unsigned long addr, int level)
{
    return (addr >> (PAGE_SHIFT + (10 * level))) & 0x3ff;
}
...
static void
init_page_table(void)
{
  /* Install the self-reference for the virtual page table base register.  */
  page_dir[pt_index(VPTPTR, 2)] = build_pte(page_dir);
...

Я не понимаю, почему VPTPTR установлен на такое значение и как я могу его использовать?

// fill the 4th page index(47-39) with 1
    unsigned long pgd_index = 0b0000000000000000111111111000000000000000000000000000000000000000;
    unsigned long pg_addr_pte = host_addr |= pgd_index;

Но это не работает, это неверный адрес.


Это может быть равно «получить физический адрес страницы в linux», так как физический адрес и права доступа к странице хранятся в pte.

Предоставлен виртуальный адрес, проверьте разрешение его страницы. В режиме пользователя.

Заранее спасибо.

...