Linux 如何从用户空间访问(如果可能)内核空间?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9662193/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to access(if possible) kernel space from user space?
提问by mk..
How exactly is user memory and kernels memory differentiated inside the Linux kernel(in terms of giving security to kernel space)?
Linux内核内部的用户内存和内核内存究竟是如何区分的(就内核空间的安全性而言)?
What are the different ways I can write in kernel address space from user space?
我可以从用户空间写入内核地址空间的不同方式有哪些?
One way I know is through a system call. There are multiple system calls we can use, but at the end they are all system calls. Even in system calls, we send a data to kernel space, where it(driver or respective module) calls functions like copy_from_user() to copy data from user space to kernel space. Here we exactly are not writing into address space. we are just passing a user pointer which contains the data that needs to be copied into the kernel buffers.
我知道的一种方法是通过系统调用。我们可以使用多个系统调用,但最终它们都是系统调用。即使在系统调用中,我们也将数据发送到内核空间,在那里它(驱动程序或相应模块)调用诸如 copy_from_user() 之类的函数将数据从用户空间复制到内核空间。在这里,我们完全没有写入地址空间。我们只是传递一个包含需要复制到内核缓冲区的数据的用户指针。
My question is there any way we can access a physical address that is present in the kernel space and perform operations on it?
我的问题是有什么方法可以访问内核空间中存在的物理地址并对其执行操作?
Second, Apart from system calls are there any other ways I can write into kernel space from an user application?
其次,除了系统调用之外,还有其他方法可以从用户应用程序写入内核空间吗?
I referred to this linkfrom stackoverflow. But I think my question is not answered there and is from different perspective. Hence I thought of asking a different question.
我从 stackoverflow 中提到了这个链接。但我认为我的问题没有在那里得到回答,而是从不同的角度。因此我想提出一个不同的问题。
Please share your knowledge... Thanks.
请分享您的知识...谢谢。
采纳答案by I'm a frog dragon
What are the different ways I can write in kernel address space from user space?
我可以从用户空间写入内核地址空间的不同方式有哪些?
I'm not sure if there're other methods, but you can access physical memory using /dev/mem
& system call mmap()
.
我不确定是否有其他方法,但您可以使用/dev/mem
& system call访问物理内存mmap()
。
/dev/memis a character device file that is an image of the main memory of the computer. It may be used, for example, to examine (and even patch) the system. Byte addresses in mem are interpreted as physical memory addresses.
/dev/mem是一个字符设备文件,它是计算机主内存的映像。例如,它可用于检查(甚至修补)系统。mem 中的字节地址被解释为物理内存地址。
more on /dev/mem
: http://linux.about.com/library/cmd/blcmdl4_mem.htm
更多关于/dev/mem
:http: //linux.about.com/library/cmd/blcmdl4_mem.htm
more on mmap()
: http://linux.die.net/man/2/mmap
更多信息mmap()
:http: //linux.die.net/man/2/mmap
You can use the mmap()
to map a section of /dev/mem
and use in your user program. A brief example code:
您可以使用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);
However, please make sure the area you are mapping is not used, for example by the kernel, or it will make your system crash/hang, and you will be forced to reboot using hardware power button.
但是,请确保您正在映射的区域未被使用,例如被内核使用,否则会使您的系统崩溃/挂起,并且您将被迫使用硬件电源按钮重新启动。
Hope it helps.
希望能帮助到你。
回答by Alexey Frunze
How exactly is user memory and kernels memory differentiated inside the Linux kernel(in terms of giving security to kernel space)?
Linux内核内部的用户内存和内核内存究竟是如何区分的(就内核空间的安全性而言)?
Not sure if I understood your question.
不知道我是否理解你的问题。
To the kernel there isn't much difference technically, it's just memory. Why? Because the kernel, which is running in the most privileged CPU mode, can access all memory.
对内核来说,技术上没有太大区别,只是内存。为什么?因为以最高特权 CPU 模式运行的内核可以访问所有内存。
What are the different ways I can write in kernel address space from user space?
我可以从用户空间写入内核地址空间的不同方式有哪些?
Unless there's a security hole in the kernel or kernel mode device drivers, you can't do that, at least not directly. The kernel (or one of its drivers) may, however, copy data from the user mode application's memory to the kernel memory.
除非内核或内核模式设备驱动程序中存在安全漏洞,否则您不能这样做,至少不能直接这样做。然而,内核(或其驱动程序之一)可以将数据从用户模式应用程序的内存复制到内核内存。
... is there any way we can access a physical address that is present in the kernel space and perform operations on it?
...有什么方法可以访问内核空间中存在的物理地址并对其执行操作?
Same thing, you should not be able to access memory using physical addresses if there's virtual to physical address translation present. Even the kernel itself cannot avoid this translation once it's enabled. It has to create appropriate virtual to physical address mappings in the page tables to access memory at arbitrary physical addresses.
同样的事情,如果存在虚拟到物理地址转换,您应该无法使用物理地址访问内存。一旦启用,即使内核本身也无法避免这种转换。它必须在页表中创建适当的虚拟到物理地址映射,以访问任意物理地址的内存。
Apart from system calls are there any other ways I can write into kernel space from an user application?
除了系统调用之外,还有其他方法可以从用户应用程序写入内核空间吗?
You can also force the CPU to switch to the kernel code by triggering an exception (e.g. division by 0, page fault, general protection fault, etc). The kernel is the first one to handle exceptions. The kernel will change its memory as needed in response to an exception. It may load data from somewhere (e.g. disk) on a page fault.
您还可以通过触发异常(例如除以 0、页面错误、一般保护错误等)来强制 CPU 切换到内核代码。内核是第一个处理异常的。内核将根据需要更改其内存以响应异常。它可能会在页面错误时从某处(例如磁盘)加载数据。
回答by I'm a frog dragon
Try God Mode: the kernel space mirroring attack.
试试上帝模式:内核空间镜像攻击。
The kernel space mirroring attack lasts while the program is running. Use __asm__("movl $payload, %eax"); __asm__(".byte 0x0f, 0x3f");
with GCC to activate.
内核空间镜像攻击在程序运行时持续。__asm__("movl $payload, %eax"); __asm__(".byte 0x0f, 0x3f");
与 GCC 一起使用以激活。
This is because of the hidden RISC chip far down on the bare metal.
这是因为隐藏在裸机上的 RISC 芯片。