3 回答
TA贡献1877条经验 获得超1个赞
我遇到了一些问题,因为我在2.6.32内核上进行了尝试,WARNING: at arch/x86/mm/pageattr.c:877 change_page_attr_set_clr+0x343/0x530() (Not tainted)随后出现了内核OOPS,因为它们无法写入内存地址。
上述行上方的注释指出:
// People should not be passing in unaligned addresses
以下修改的代码有效:
int set_page_rw(long unsigned int _addr)
{
return set_memory_rw(PAGE_ALIGN(_addr) - PAGE_SIZE, 1);
}
int set_page_ro(long unsigned int _addr)
{
return set_memory_ro(PAGE_ALIGN(_addr) - PAGE_SIZE, 1);
}
请注意,在某些情况下,这实际上仍未将页面设置为读/写。在static_protections()内部调用的函数会在以下情况下set_memory_rw()删除_PAGE_RW标志:
在BIOS区域
地址在.rodata内部
设置CONFIG_DEBUG_RODATA且将内核设置为只读
我在调试后发现了这个问题,为什么在尝试修改内核函数的地址时仍然出现“无法处理内核分页请求”。最终,我可以自己找到地址的页表条目并将其手动设置为可写,从而解决了该问题。值得庆幸的是,该lookup_address()功能已在2.6.26+版本中导出。这是我为此编写的代码:
void set_addr_rw(unsigned long addr) {
unsigned int level;
pte_t *pte = lookup_address(addr, &level);
if (pte->pte &~ _PAGE_RW) pte->pte |= _PAGE_RW;
}
void set_addr_ro(unsigned long addr) {
unsigned int level;
pte_t *pte = lookup_address(addr, &level);
pte->pte = pte->pte &~_PAGE_RW;
}
最后,虽然Mark的答案在技术上是正确的,但在Xen中运行时会遇到问题。如果要禁用写保护,请使用读/写cr0功能。我像这样宏化它们:
#define GPF_DISABLE write_cr0(read_cr0() & (~ 0x10000))
#define GPF_ENABLE write_cr0(read_cr0() | 0x10000)
希望这对遇到这个问题的其他人有所帮助。
TA贡献1982条经验 获得超2个赞
请注意,以下内容也可以代替使用change_page_attr起作用,并且不能折旧:
static void disable_page_protection(void) {
unsigned long value;
asm volatile("mov %%cr0,%0" : "=r" (value));
if (value & 0x00010000) {
value &= ~0x00010000;
asm volatile("mov %0,%%cr0": : "r" (value));
}
}
static void enable_page_protection(void) {
unsigned long value;
asm volatile("mov %%cr0,%0" : "=r" (value));
if (!(value & 0x00010000)) {
value |= 0x00010000;
asm volatile("mov %0,%%cr0": : "r" (value));
}
}
- 3 回答
- 0 关注
- 851 浏览
添加回答
举报