尽管处于非特权模式,但 mmap'ing /dev/mem 如何工作?

尽管处于非特权模式,但 mmap'ing /dev/mem 如何工作?

据我了解,用户空间程序运行在非特权模式下,因此无法直接访问内存或 I/O。

那么当我们在用户空间程序中mmap /dev/mem 时,究竟如何才能直接访问内存或I/O 位置呢?

例如:

int fd = 0;
u8 leds = 0;
fd = open("/dev/mem", O_RDWR|O_SYNC);
leds = (u8 *)mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x80840000);

这是嵌入式设备中非常常用的一种技巧。

现在该变量leds可以即时使用来访问可能存在于 0x80840000 处的任何设备。

我们将不再使用任何系统调用来访问该地址。

甚至像

leds[0x20] = val;

会工作。

但是特权操作,例如直接从 I/O 地址读取/写入,只能通过系统调用将处理器置于特权模式来实现。

来源

答案1

允许非特权进程访问/dev/mem确实是一个安全问题,不应该被允许。

在我的系统上,ls -l /dev/mem看起来像这样:

crw-r----- 1 root kmem 1, 1 Sep  8 10:12 /dev/mem

所以root可以读和写它,该kmem组的成员(恰好没有)可以读它但不能写它,其他人根本无法打开它。所以这应该是安全的。

如果您的/dev/mem与我的类似,那么您的非特权进程根本就不应该能够打开该文件,更不用说mmap它了。

检查您系统上的权限/dev/mem以确保它们是安全的!

答案2

用户进程(无论是作为 root 用户还是非特权用户运行)可见的地址都是虚拟地址,它们由 MMU 通过页表映射到物理地址。设置页表是一个特权操作,只能由内核代码执行;然而,一旦设置了页表,就允许在用户模式下访问内存。

具体来说,您的代码用于mmap请求内核设置页表以允许访问给定范围的物理内存。内核检查进程的权限(它具有读/写访问权限/dev/mem)并设置页表以允许其访问物理内存。

答案3

的值leds是一个虚拟地址。只要它在当前进程的用户空间中,进程就可以直接通过指令访问它,leds[0] = val而不必处于特权模式,无论这个虚拟地址映射到 RAM 中的哪个位置

相关内容