【问题标题】:For arm Linux, could threads in user space access virtual address of Kernel space?对于arm Linux,用户空间的线程可以访问内核空间的虚拟地址吗?
【发布时间】:2012-07-01 16:59:21
【问题描述】:

虚拟内存分为两部分。传统上,0~3GB 用于用户空间,3GB~4GB 用于内核空间。

我的问题:

用户空间的线程可以访问内核空间的内存吗?

对于ARM datasheet,访问属性由域访问控制寄存器负责。但是在内核源代码中,用户空间虚拟内存的页表项中的域值与内核空间的页表项相同。

【问题讨论】:

  • 我得到了答案。访问权限管理仍然依赖于页表条目和域访问控制寄存器中的域和AP字段。在 2.6.38 之前,启动代码通过 DOMAIN_MANAGER 初始化 DOMAIN_USER。但是在 early_trap_init 中,系统会将 DOMAIN_USER 修改为 DOMAIN_CLIENT。而当域属性为DOMAIN_CLIENT 时,Page 表项中的AP 字段将生效。感谢以下答案。

标签: linux linux-kernel arm


【解决方案1】:

事实上,您的应用程序可能会访问页面 0xFFFF0000,因为它包含 swi-handler 和几个其他用户空间助手。所以不,3/1 分割没什么神奇的,内核很容易管理。

通常内核会将所有超过 3GB 的内存设置为只能由内核域本身访问。如果驱动程序需要在用户和内核空间之间共享内存,它通常会提供一个 mmap 接口,然后创建一个别名映射,因此您有两个虚拟地址用于同一个物理地址。这只适用于 VIPT-Cache 系统或大量仔细的显式缓存刷新。如果您不希望这样,您可以破解内核以使用户空间可以访问 3G 拆分之上的一块内存。但随后所有用户空间应用程序将共享此内存。我为 armv5 系统上的特殊应用程序做过一次。

【讨论】:

  • 感谢您的回答。我同意。你说,3GB以上的虚拟地址只能kernel-domain自己访问user-domainblocked我>。能否简单介绍一下如何实现?
  • 我得到了答案。谢谢。
【解决方案2】:

用户空间代码获取内核内存?唯一允许这样做的内核是 DOS 及其古老的朋友。 但回到问题上来,看看这个示例 C 代码:

char c=42;
*c=42;

我们取一个字节(char)并为其分配数值 42。然后我们取消引用这个非指针,它可能会尝试访问虚拟内存的第 42 个字节,它几乎绝对不是你的内存,而且,为了这个例子,内核内存。猜猜当你运行它时会发生什么(如果你设法将编译器放在枪口下):

Segmentation fault

Linux 与任何现代操作系统一样具有内存保护功能。如果您尝试访问另一个进程的内存,您的进程将在它可以做任何事情之前被终止(虽然我不太确定调试器会发生其他事情)。即使该内存是另一个 Userland 进程的内存,您仍然会被终止。我几乎可以肯定root 程序无法访问其他程序内存或内核内存。访问内核内存的唯一方法是成为内核的一部分,或者间接通过内核的合作。

【讨论】:

  • 足够特权的用户空间可以在 Linux(如果已配置)上打开 /dev/kmem,这是内核虚拟内存 ;-)
  • @ehemient:真的吗?但是足够的特权仍然不意味着它是可写的,对吧?还是“足够特权”只是以root 运行?
  • 如果内核配置了CONFIG_DEVKMEM=y并且没有LSM(如SELinux)阻塞访问,则具有CAP_SYS_RAWIOroot具有所有功能,并且可以授予其他进程)足以读写/dev/kmem。曾几何时,这就是模块加载的工作方式,但现在已经不是这样了。
  • @ehemient:真的吗?奇怪。但是,如果您在测试中使用 root 访问权限尝试渗透内核,那么您可能做错了什么。
  • 也有共享用户和内核空间内存的API,如packet-mmap,这些通常将内核空间mmap到用户空间,使用相同的物理地址,但不同的虚拟地址。当前没有允许共享相同物理地址和虚拟地址的内核接口。但是你可以(我已经做到了)创建所有用户空间进程都可以访问的内核内存。这是一种非常 hacky 和特定于架构的方法,但它是在受限环境中的特殊应用程序(共享内存而没有 VIVT-DCache 引入的别名问题)所需要的。
猜你喜欢
  • 2018-04-23
  • 2019-07-03
  • 1970-01-01
  • 2016-06-02
  • 1970-01-01
  • 2011-09-08
  • 2018-01-16
  • 2018-03-27
  • 2012-03-06
相关资源
最近更新 更多