从内核空间写入用户进程的.text部分

时间:2014-07-24 18:20:57

标签: linux-kernel virtual-memory

我正在为研究项目编写内核空间组件,这需要我在执行的不同点拦截和检查用户空间进程(具体说明)。由于各种原因,我无法修改用户空间程序或者ptrace那个过程。

为了实现这个目标,我试图在用户空间进程中插入一个断点(INT 3指令),我需要检查它,然后在内核空间中拦截SIGTRAP。不幸的是,我似乎无法弄清楚如何从该进程的内核空间正确修改用户空间代码的只读文本部分。我目前正在尝试使用get_user_pages API强制页面可写并修改它们,但文本数据似乎没有变化。代码I尝试使用的相关部分如下。 user_addr是在(unsigned long)处插入断点的用户空间地址; pagestruct page *

char *addr;
unsigned long aligned_user_addr = user_addr & ~((unsigned long)PAGE_SIZE - 1);

down_read(&current->mm->mmap_sem);
rc = get_user_pages(current, current->mm, aligned_user_addr, 
                    1, 1, 1, &page, &vma);
up_read(&current->mm->mmap_sem);
BUG_ON(rc != 1);

addr = kmap(page);
BUG_ON(!addr);

offs = user_addr % PAGE_SIZE;

/* NOTE: INT3_INSTR is defined to be 0xCC */
addr[offs] = INT3_INSTR;
BUG_ON(addr[offs] != INT3_INSTR); // Assertion fails

set_page_dirty(page);
kunmap(page);
page_cache_release(page);

我希望有更多内核知识和经验的人能够告诉我我做错了什么,或者正确的方法来完成我的任务。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

事实证明我的问题实际上是C符号扩展。 INT3_INSTR定义为:

#define INT3_INSTR 0xCC

这使它成为一个整数,并且行:

BUG_ON(addr[offs] != INT3_INSTR);

评估addr[offs]signed char。在c中,当signed charint进行比较时,其类型被提升为int的类型,并且由于其签名,如果其MSB为1,则将对其进行签名扩展。作为0xCC&#39 ; MSB始终为1,总是评估为:

BUG_ON(0xFFFFFFCC != 0xCC);

评价为假。将addr更改为unsigned char *可解决此问题。然后上面的代码工作。