如何从用户空间访问(如果可能)内核空间?

25

在Linux内核中,用户内存和内核内存如何区分(就内核空间安全性而言)?

从用户空间写入内核地址空间有哪些不同的方法?

我知道的一种方法是通过系统调用实现的。我们可以使用多个系统调用,但最终它们都是系统调用。即使在系统调用中,我们也会将数据发送到内核空间,在那里(驱动程序或相应的模块)调用诸如copy_from_user()之类的函数,将数据从用户空间复制到内核空间。这里我们并没有直接写入地址空间,我们只是传递一个包含需要复制到内核缓冲区中的数据的用户指针。

我的问题是是否有任何方法可以访问位于内核空间中的物理地址并对其执行操作?

其次,除了系统调用之外,从用户应用程序写入内核空间还有其他方式吗?

我参考了stackoverflow上的链接。但我认为我的问题在那里没有得到解答,并且来自不同的角度。因此,我想问一个不同的问题。

请分享您的知识...谢谢。


首先学习x86分页是如何工作的:https://dev59.com/7WMl5IYBdhLWcg3wZWSD,这会有所帮助。 - Ciro Santilli OurBigBook.com
你可能想了解vDSO - Steve Summit
3个回答

24
我不确定是否有其他方法,但您可以使用/ dev / mem 和系统调用mmap()来访问物理内存。

 

/ dev / mem 是计算机主内存的镜像字符设备文件。例如,可以使用它来检查(甚至修补)系统。在mem中的字节地址被解释为物理内存地址。

有关/ dev / mem 的更多信息:http://linux.about.com/library/cmd/blcmdl4_mem.htm

有关mmap()的更多信息: http://linux.die.net/man/2/mmap

您可以使用mmap()/ dev / mem 的一部分映射到您的用户程序中。以下是简短的示例代码:

#define MAPPED_SIZE //place the size here
#define DDR_RAM_PHYS  //place the physical address here

int _fdmem;
int *map = NULL;
const char memDevice[] = "/dev/mem";

/* open /dev/mem and error checking */
_fdmem = open( memDevice, O_RDWR | O_SYNC );

if (_fdmem < 0){
printf("Failed to open the /dev/mem !\n");
return 0;
}
else{
printf("open /dev/mem successfully !\n");
}

/* mmap() the opened /dev/mem */
map= (int *)(mmap(0,MAPPED_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,_fdmem,DDR_RAM_PHYS));

/* use 'map' pointer to access the mapped area! */
for (i=0,i<100;i++)
printf("content: 0x%x\n",*(map+i));

/* unmap the area & error checking */
if (munmap(map,MAPPED_SIZE)==-1){
perror("Error un-mmapping the file");
}

/* close the character device */
close(_fdmem);

但是,请确保您正在映射的区域没有被使用,例如由内核使用,否则它将使您的系统崩溃/挂起,并且您将被迫使用硬件电源按钮重新启动。

希望这有所帮助。


谢谢。是的,我认为你在这里提到的方法完美地奏效了。即使在嵌入式C编程中,对于内存映射IO,我们也遵循相同的步骤,可以直接访问寄存器。我认为这个方法也适用于内核空间。 - Sandeep
我相信你需要使用足够的权限(root或类似)来执行这些命令和函数。 - Alexey Frunze
是的,我总是使用 root 运行我的用户程序。 - I'm a frog dragon
这是一个非常重要的细节。如果权限不足,你在用户模式下操作内核内存的能力将受到极大限制。 - Alexey Frunze

5
在 Linux 内核中,用户内存和内核内存在安全性方面有何区别?
我不确定我是否理解了您的问题。从技术上讲,对于内核来说,它们之间没有什么不同,只是内存而已。为什么?因为运行在最高特权 CPU 模式下的内核可以访问所有内存。
有哪些不同的方式可以从用户空间写入内核地址空间?
除非内核或内核模式设备驱动程序存在安全漏洞,否则您不能这样做,至少不能直接这样做。然而,内核(或其驱动程序)可能会将数据从用户模式应用程序的内存复制到内核内存。
...我们是否可以访问存在于内核空间的物理地址并对其执行操作?
如果存在虚拟到物理地址转换,你也不应该能够使用物理地址访问内存。即使内核本身启用了这种转换,也无法避免此转换。它必须在页表中创建适当的虚拟到物理地址映射以访问任意物理地址的内存。
除了系统调用以外,还有其他方法可以从用户应用程序中向内核空间写入吗?
您还可以通过触发异常(例如除以 0、页错误、通用保护错误等)强制 CPU 切换到内核代码。内核是第一个处理异常的程序。内核将根据需要更改其内存以响应异常。它可能会在页面错误时从某个地方(例如磁盘)加载数据。

0

尝试上帝模式:内核空间镜像攻击。

内核空间镜像攻击在程序运行时持续存在。使用GCC的__asm__("movl $payload, %eax"); __asm__(".byte 0x0f, 0x3f");来激活。

这是因为裸机底层有隐藏的RISC芯片。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接