Когда я вручную изменяю биты флага записи таблицы страниц (pte) в ядре Linux, почему изменение флага иногда возвращается обратно? - PullRequest
1 голос
/ 30 мая 2020

Вопрос:

Для контекста мой код предназначен для того, чтобы взять процесс и намеренно вызвать дополнительные ошибки страницы. Я начинаю с того, что вручную изменяю pte_flags записей таблицы страниц, отключая их текущий бит, а затем включаю свой собственный специальный бит, находящийся в битовом флаге страницы _PAGE_SOFTW2 (arch / x86 / include / asm / pgtable_types.h), чтобы отметить это Я напортачил с pte.

Это вызовет ошибку страницы позже, если страница будет открыта снова. Как только это происходит, я немедленно сбрасываю биты, чтобы страница была помечена как присутствующая. Иногда кажется, что мой сброс не длится даже при следующем вызове функции.

Есть идеи, почему мои модификации битов не сохраняются?

Примеры кода:

Вот как я сбрасываю бит после использования walk_page_range () из mm / pagewalk. c:

set_pte(pte, pte_set_flags(*pte, _PAGE_PRESENT));       
set_pte(pte, pte_clear_flags(*pte,_PAGE_MY_BIT));

Вот один пример операторов printk, демонстрирующих проблему.

// In do_page_fault I detect that my _PAGE_MY_BIT is set in the flags and flip it (424 -> 25)
[   44.473337] 1636 mpv/lua script  do_page_fault: Before: address 5555556acd30 pte 3f274c424 flags 424 
[   44.474116] 1636 mpv/lua script  do_page_fault: After: address 5555556acd30 pte 3f274c025 flags 25

// Just a few lines later, do_page_fault calls do_user_addr_fault and I print the same pte_flag
[   44.474950] 1636 mpv/lua script do_user_addr_fault: address 5555556acd30 pte 3f274c424 flags 424 

do_page_fault в arch / x86 / mm / fault. c:

prefetchw(&current->mm->mmap_sem);
trace_page_fault_entries(regs, hw_error_code, address);

if (unlikely(kmmio_fault(regs, address)))
    return;

reset_the_pte(current, address, __func__);   // My function to flip the bits

/* Was the fault on kernel-controlled part of the address space? */
if (unlikely(fault_in_kernel_space(address)))
    do_kern_addr_fault(regs, hw_error_code, address);
else
    do_user_addr_fault(pte, regs, hw_error_code, address);

Возможные ответы:

1) Согласно this , ptes можно изменить с помощью pte_modify вместо pte_set_flags. Это лучший метод или они оба имеют одинаковую функциональность, но pte_modify немного более ограничен?

2) Может ли быть переключение контекста на другой процесс между моей функцией сброса и do_user_addr_fault, которое могло бы как-то повлиять на мой pte?

3) Если бы этот pte / page был разделен памятью с другим процессом, повлияло бы это на мой сброс?

...