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

Sta*_*k07 6 mmap privileges

就我的理解而言,用户空间程序以非特权模式运行,因此无法直接访问内存或 I/O。

那么当我们在用户空间程序中映射 /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);
Run Code Online (Sandbox Code Playgroud)

这是一种在嵌入式设备中非常常用的 hack。

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

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

甚至像

leds[0x20] = val;
Run Code Online (Sandbox Code Playgroud)

会工作。

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

来源

Cel*_*ada 9

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

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

crw-r----- 1 root kmem 1, 1 Sep  8 10:12 /dev/mem
Run Code Online (Sandbox Code Playgroud)

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

如果你/dev/mem和我一样,你的非特权进程甚至根本无法打开文件,更不用说mmap它了。

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

  • TL;DR 非特权进程*没有*直接访问系统资源,但是当这些资源映射到它们的虚拟地址空间时**可以**这样做。访问其堆栈/堆/rodata/任何内容和访问内核内存之间没有区别——它们最终都访问实际的物理内存,而后一种情况恰好在程序的控制之下。 (2认同)

小智 6

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

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