2012-05-09 119 views
8

我知道copy_to_user/copy_from_user,get_user/put_user功能是为了这个目的。如何从Linux内核访问用户空间内存?

我的问题是,给定一个用户空间地址/指针,我怎样才能访问内核地址指向的数据?

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

下一步是什么?我能否使用*p,其中p是指向某些用户空间数据的指针,直接引用数据?

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

回答

4

指针本身还不够!您需要知道指针“属于”哪个进程。

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

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

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

注:

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

不同的用户空间应用程序有不同的页面表。 1)你需要获得用户空间程序pid。 2)在pid的页表中搜索addree。

下面是将用户空间虚拟地址转换为物理地址的示例代码。 它适用于x86平台。

taskpid = find_get_pid(curpid); 
task = pid_task(taskpid, PIDTYPE_PID); 
mm = get_task_mm(task); 
down_read(&mm->mmap_sem); 

start_vaddr = vaddr; 
end_vaddr = 0xC0000000; 

while(start_vaddr < end_vaddr){ 
    u32 end; 

    end = ((start_vaddr + PMD_SIZE) & PMD_MASK); 

    if(end < start_vaddr || end > end_vaddr) 
     end = end_vaddr; 

    ret = walk_pgd(start_vaddr, end, mm); 
    if(ret != 0){ 
     printk("ret: %08x \n", ret); 
     break; 
    } 

    start_vaddr = end; 

} 

up_read(&mm->mmap_sem); 

paddr = ret; 
kaddr = __va(paddr); 
mmput(mm); 
+0

好点,代码逻辑很好。但我想有一些哈希表或类似的数据结构,给定一个虚拟地址,可以帮助您快速找到物理页面。有一个缺陷:kaddr = __va(paddr);这条线只有在paddr驻留在低内存时才有效,对吧? – Infinite

+0

paddr表示物理地址,所以始终存在于内存中。 kaddr表示内核地址。在Linux内核中,define是'#define __va(x)((void *)((unsigned long)(x)+ PAGE_OFFSET))'。内核地址内存映射并不复杂,只是一个PAGE_OFFSET。 (在x86模式下应该是0xC0000000)。 还有其他方法可以获取地址。用户空间应用程序可以通过/ proc//pagemap访问内核地址来获取页面信息。如果能得到PFN,它也可以得到内核地址。 – richliu

0

你需要follow的地址就能获取相应的page结构(见follow_page的例子)。接下来,获取page结构,您需要通过kmapkmap_atomic将其映射到内核地址空间。

3

您可能会觉得这很有用。

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

  • 根据其架构您的驱动器上运行,并 内核是如何配置的,而在内核模式下运行 用户空间指针可能无效所有。该地址可能没有映射,也可能指向其他一些随机数据。

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

  • 有问题的指针由用户程序提供,其中 可能有问题或恶意。如果你的驱动永远盲目取消引用 用户提供的指针,它提供了一个开放的门道允许 用户空间程序来访问或 系统的任何地方覆盖内存。如果您不希望对用户系统的安全性产生影响,则不能直接取消引用 用户空间指针。

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

这么说,我是我自己很想知道,如果用户空间地址确实是有效的,并没有上述报考条件会发生什么......

相关问题