mmap 失败并返回 -EPERM 错误问题

问题现象

Philip Ye
Philip Ye
Jul 10, 2017 · 4 min read

在我们的应用系统初始化过程中,用户态程序会读取 /proc/task_info 第一个字段的值作为物理地址传入 mmap/dev/mem 做内存映射。/proc/task_info 的内容如下:

$ cat /proc/task_info
0x81b0000 0xd555555555555555 0x5

也就是将 0x81b0000 (每次运行值可能不同)作为物理地址传入 mmap,此时返回 errno 为 -1,表示无权限:

#define EPERM 1 /* Operation not permitted */

源码分析

内存设备节点 /dev/mem 作为可随机读写的字符设备,在内核源码的 drivers/char/mem.c 中初始化(/dev/kmem, /dev/null, /dev/zero, /dev/random, /dev/urandom 等设备节点也都在这个文件中定义),对 /dev/memmmap 操作定义为 mmap_mem()。在 mmap_mem() 中返回 -EPERM 的代码片段如下:

if (!range_is_allowed(vma->vm_pgoff, size))
return -EPERM;

当定义了 CONFIG_STRICT_DEVMEM 时,在 range_is_allowed() 中会逐页调用 devmem_is_allowed() 检查是否可访问:

static inline int range_is_allowed(unsigned long pfn, unsigned long size)
{
u64 from = ((u64)pfn) << PAGE_SHIFT;
u64 to = from + size;
u64 cursor = from;

while (cursor < to) {
if (!devmem_is_allowed(pfn)) {
printk(KERN_INFO
“Program %s tried to access /dev/mem between %Lx->%Lx.\n”,
current->comm, from, to);
return 0;
}
cursor += PAGE_SIZE;
pfn++;
}
return 1;
}

devmem_is_allowed() 由各个体系结构实现,以 PowerPC 为例,在 arch/powerpc/mm/mem.c 中,同样也是定义了 CONFIG_STRICT_DEVMEM 才有实现:

int devmem_is_allowed(unsigned long pfn)
{
if (iomem_is_exclusive(pfn << PAGE_SHIFT))
return 0;
if (!page_is_ram(pfn))
return 1;
if (page_is_rtas_user_buf(pfn))
return 1;
return 0;
}

devmem_is_allowed() 返回 1 表示允许访问,0 表示不允许访问。其中第一个 if 语句调用的 iomem_is_exclusive() 是用于判断 PCI 的内存空间(PCI mem)是否互斥访问的。由于我们访问的是内核生成的 /proc/task_info,与 PCI 无关,因此 mmap 失败是在 devmem_is_allowed() 最后的 return 0 返回了不允许访问。

解决方法

方法一:修改 devmem_is_allowed() 函数

devmem_is_allowed() 函数中,当访问的是 /proc/task_info 对应的页号时,返回 1 表示允许访问。

这种方法实现复杂,需要在生成 /proc/task_info 时保存其对应的页号(在 fs/proc/taskinfo.c 文件的 task_info_init() 函数中分配的页号);同时这个方法污染了内核代码,不具有通用性。

方法二:关闭 CONFIG_STRICT_DEVMEM 配置

从前面的说明中可以看出,几个检查函数都是在定义了 CONFIG_STRICT_DEVMEM 才生效的,因此最简单的方法,就是将内核配置中 CONFIG_STRICT_DEVMEM 选项关闭并重新编译内核,这也是我们的应用系统所采用的方法。

以上。

Philip Ye

Written by

Philip Ye

@yestyle

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade