【问题标题】:Change user space memory protection flags from kernel module从内核模块更改用户空间内存保护标志
【发布时间】:2012-08-17 00:05:02
【问题描述】:

我正在编写一个可以访问特定进程内存的内核模块。我用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 选项。由于安全隐患,该选项 通常仅在嵌入式设备上启用(即,已完成 控制用户内存的内容)。

所以,虽然这可能会满足我的要求,但它的便携性并不高。有没有标准的方法来完成我的建议?

【问题讨论】:

  • 为什么哦,为什么要在内核模块中做所有这些事情?有了明确定义的 API,用户空间进程本身就没有理由不能完成。
  • @mpe 我在用户空间做不到的原因是我正在写的模块是一个进程加载器;我对用户空间代码没有任何影响。
  • 进程加载器是什么意思?您是说 binfmt 处理程序吗?
  • @mpe 是的,它是一个 binfmt 处理程序。
  • 有什么理由你不能在用户空间加载并使用 binfmt_misc 让它看起来内核正在直接加载你的程序? (参见文档/binfmt_misc.txt)

标签: memory-management process linux-kernel mmap


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-12
      • 2011-11-29
      • 2012-08-01
      • 2016-10-07
      • 2012-12-26
      • 2018-06-30
      • 1970-01-01
      • 2013-08-10
      相关资源
      最近更新 更多