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);

vaddr并且vsize设置得更早,并且调用成功。从内核模块(通过)写入该内存块后copy_to_user,我想删除PROT_WRITE它的权限(就像我mprotect在普通用户空间中所做的那样)。我似乎找不到允许这样做的功能。

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

MAP_UNINITIALIZED(自 Linux 2.6.33 起)

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

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

4

2 回答 2

1

经过更多研究,我发现了一个名为get_user_pages()(我找到的最佳文档是here)的函数,它从给定地址的用户空间返回页面列表,可以映射到内核空间kmap()并以这种方式写入(在我的情况下,使用kernel_read())。这可以用作替代,copy_to_user()因为它允许在检索的页面上强制写入权限。唯一的缺点是您必须逐页编写,而不是一口气写完,但它确实解决了我在问题中描述的问题。

于 2012-08-20T04:33:44.470 回答
0

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

于 2012-08-17T04:47:52.957 回答