如何在不崩溃Linux内核的情况下访问mmaped/dev/mem? [英] How to access mmaped /dev/mem without crashing the Linux kernel?

查看:110
本文介绍了如何在不崩溃Linux内核的情况下访问mmaped/dev/mem?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的程序,试图访问用户空间中的物理内存,内核在其中存储了第一个struct页面.在64位计算机上,该地址为:

I have a simple program that tries to access the physical memory in user space, where the kernel stores the 1st struct page. On a 64 bit machine this address is:

  • 内核虚拟地址:ffffea0000000000
  • 物理地址:0000620000000000

我正在尝试通过用户空间中的mmap访问此物理地址.但是以下代码使内核崩溃.

I am trying to access this physical address through mmap in user space. But the following code crashes the kernel.

int *addr;
if ((fd = open("/dev/mem", O_RDWR|O_SYNC)) < 0 ) {
    printf("Error opening file. \n");
    close(fd);
    return (-1);
}
/* mmap.  address of first struct page for 64 bit architectures 
 * is 0x0000620000000000.
 */
addr = (int *)mmap(0, num*STRUCT_PAGE_SIZE, PROT_READ, MAP_PRIVATE,
            fd, 0x0000620000000000);
printf("addr: %p \n",addr);
printf("addr: %d \n",*addr); /* CRASH. */

推荐答案

我认为我已经找到了问题-与x86上的/dev/mem内存映射保护有关.

I think I've found the issue -- it's to do with /dev/mem memory mapping protection on the x86.

请参阅此LWN文章: "x86:通过配置选项引入/dev/mem限制" http://lwn.net/Articles/267427/

Pl refer to this LWN article: "x86: introduce /dev/mem restrictions with a config option" http://lwn.net/Articles/267427/

CONFIG_NONPROMISC_DEVMEM

CONFIG_NONPROMISC_DEVMEM

现在(我在最近的3.2.21内核上对此进行了测试),config选项似乎称为CON​​FIG_STRICT_DEVMEM.

Now (i tested this on a recent 3.2.21 kernel), the config option seems to be called CONFIG_STRICT_DEVMEM.

我更改了内核配置:

$ grep DEVMEM .config
# CONFIG_STRICT_DEVMEM is not set
$ 

当上述prg与 previous 内核一起运行时,并设置了CONFIG_STRICT_DEVMEM: dmesg显示:

When the above prg was run with the previous kernel, with CONFIG_STRICT_DEVMEM SET: dmesg shows:

[29537.565599] Program a.out tried to access /dev/mem between 1000000->1001000.
[29537.565663] a.out[13575]: segfault at ffffffff ip 080485bd sp bfb8d640 error 4 in a.out[8048000+1000]

这是由于内核保护.

当重建内核(使用CONFIG_STRICT_DEVMEM UNSET )并运行上述prg时:

When the kernel was rebuilt (with the CONFIG_STRICT_DEVMEM UNSET) and the above prg was run :

# ./a.out 
mmap failed: Invalid argument
# 

这是因为'offset'参数> 1 MB(在x86上无效)(当时为16MB).

This is because the 'offset' parameter is > 1 MB (invalid on x86) (it was 16MB).

使mmap偏移量在1 MB以内:

After making the mmap offset to be within 1 MB:

# ./a.out 
addr: 0xb7758000
*addr: 138293760 
# 

有效! 有关详细信息,请参见上面的LWN文章.

It works! See the above LWN article for details.

在具有PAT支持(页面属性表)的x86架构上,内核仍然阻止DRAM区域的映射. 内核源代码是:

On x86 architectures with PAT support (Page Attribute Table), the kernel still prevents the mapping of DRAM regions. The reason for this as mentioned in the kernel source is:

This check is nedded to avoid cache aliasing when PAT is enabled

此检查将导致与上述错误类似的错误.例如:

This check will cause a similar error to the one mentioned above. For example:

Program a.out tried to access /dev/mem between [mem 68200000-68201000].

可以通过禁用PAT来消除此限制.可以通过在启动时向内核命令行添加"nopat"参数来禁用PAT.

This restriction can be removed by disabling PAT. PAT can be disabled by adding the "nopat" argument to the kernel command line at boot time.

这篇关于如何在不崩溃Linux内核的情况下访问mmaped/dev/mem?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆