从内核模块更改用户空间内存保护标志

emp*_*ice 5 memory-management mmap process linux-kernel

我正在编写一个可以访问特定进程内存的内核模块.我在一些用户空间内存上做了一个匿名映射do_mmap():

#define MAP_FLAGS   (MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS)

prot = PROT_WRITE;
retval = do_mmap(NULL, vaddr, vsize, prot, MAP_FLAGS, 0);
Run Code Online (Sandbox Code Playgroud)

vaddr并且vsize先前设置,并且呼叫成功.在我从内核模块(via copy_to_user)写入该内存块后,我想删除PROT_WRITE它的权限(就像我mprotect在普通用户空间中所做的那样).我似乎无法找到允许这样做的功能.

我试图取消映射该区域并使用正确的保护重新映射它,但是这会将内存块清零,删除我刚刚编写的所有数据; 设置MAP_UNINITIALIZED可能会修复,但是,从手册页:

MAP_UNINITIALIZED(自Linux 2.6.33起)

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

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

emp*_*ice 1

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