2012-08-17 50 views
5

我正在编写可访问特定进程内存的内核模块。我已经做了一些用户存储空间的匿名映射与do_mmap()从内核模块更改用户空间内存保护标志

#define MAP_FLAGS (MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS) 

prot = PROT_WRITE; 
retval = do_mmap(NULL, vaddr, vsize, prot, MAP_FLAGS, 0); 

vaddrvsize被先前设置,呼叫成功。在我从内核模块(通过copy_to_user)写入该内存块后,我想要删除它的PROT_WRITE权限(就像我在普通用户空间中使用mprotect)。我似乎无法找到一个允许这个功能。

我试图解开映射区域并用正确的保护重新映射它,但是将内存块清零,擦除了我刚写入的所有数据;设置MAP_UNINITIALIZED可能会解决这个问题,但是,从手册页:

MAP_UNINITIALIZED(因为Linux 2.6.33)

不清除匿名页面。此标志旨在提高嵌入式设备的性能。只有在内核配置了 CONFIG_MMAP_ALLOW_UNINITIALIZED选项时,才能使用该标志。由于安全隐患,该选项 通常仅在嵌入式设备(即其中一个具有完整的用户内存内容控制权的设备)上启用。

所以,虽然这可能做我想要的,它不会很便携。有没有一个标准的方法来完成我所建议的?

+0

为什么哦你为什么要在你的内核模块中做所有的事情?有了一个明确定义的API,没有理由不能由用户空间进程本身完成。 – mpe 2012-08-17 12:13:10

+0

@mpe我在用户空间中无法完成的原因是我正在编写的模块是一个进程加载器;我对用户空间代码没有任何影响力。 – nosuchthingasstars 2012-08-17 12:31:40

+0

流程加载器是什么意思?你的意思是一个binfmt处理程序? – mpe 2012-08-17 15:33:27

回答

1

一些调查研究后,我发现了一个名为get_user_pages()功能(我发现最好的文档here)返回的,可以被映射到内核空间kmap()并写入到从用户空间在一个给定的地址页面列表方式(在我的情况下,使用kernel_read())。这可以用作copy_to_user()的替代品,因为它允许在检索到的页面上强制写入权限。唯一的缺点是你必须一页接一页地写,而不是一页一页,但它确实解决了我在我的问题中描述的问题。

0

在用户空间中有一个系统调用mprotect,它可以修改现有映射上的保护标志。您可能需要从该系统调用的实现中继续,或者直接从您的代码中直接调用它。见mm/protect.c