如何从Linux内核访问用户空间内存?

Inf*_*ite 9 memory-management linux-kernel

我知道copy_to_user/ copy_from_user,get_user/ put_user函数就是为了这个目的.

我的问题是,给定一个用户空间地址/指针,如何从内核中访问地址所指向的数据?

我可以想象,首先我必须确保包含页面应该在物理内存中(而不是在磁盘中).

你下一步怎么做?我可以使用*p,其中p的指针指向某些用户空间中的数据,直接引用的数据?

或者我是否必须先调用kmap将包含的物理页面框架映射到内核虚拟地址空间?为什么?

gja*_*ain 6

您可能会发现这很有用。

让我们重复一遍,读和写方法的 buff 参数是一个用户空间指针。因此,它不能被内核代码直接取消引用。这种限制有几个原因:

  • 根据您的驱动程序运行的架构以及内核的配置方式,用户空间指针在内核模式下运行时可能根本无效。该地址可能没有映射,或者它可能指向其他一些随机数据。

  • 即使指针在内核空间中确实意味着相同的事情,用户空间内存也会被分页,并且在进行系统调用时,有问题的内存可能不会驻留在 RAM 中。试图直接引用用户空间内存可能会产生页面错误,这是内核代码不允许做的事情。结果将是“哎呀”,这将导致进行系统调用的进程死亡。

  • 有问题的指针是由用户程序提供的,这可能是错误的或恶意的。如果您的驱动程序曾经盲目地取消引用用户提供的指针,它会提供一个开放的门,允许用户空间程序访问或覆盖系统中任何位置的内存。如果您不想对损害用户系统的安全性负责,则永远不能直接取消对用户空间指针的引用。

来源:http : //www.makelinux.net/ldd3/chp-3-sect-7

也就是说,我自己很想知道如果用户空间地址确实有效会发生什么,并且上述条件都不适用......


Luc*_*ncu 4

仅靠指针是不够的!您需要知道该指针“属于”哪个进程。

当进程被抢占时,指针指向另一个进程的地址空间。该地址可能不再被映射,yadda yadda,

如果访问数据时该进程是当前进程,那么您应该使用 copy_to_user/copy_from_user 函数。

如果进程可能被调度,您可以尝试 mlock() RAM 中的页面并找出该页面的物理 RAM 地址。每当您想要访问它时,都可以将该物理页映射到内核虚拟地址。

笔记:

  • 恶意进程可以 munlock() 页面并诱骗您访问错误的 RAM 页面。
  • 我不确定 mlock() 语义是否要求下划线 RAM 页不能更改。
  • 内核应该能够将页面锁定到RAM中,我对mm子系统不熟悉。