16

カーネルが最初の構造体ページを格納するユーザースペースの物理メモリにアクセスしようとする単純なプログラムがあります。64ビットマシンでは、このアドレスは次のとおりです。

  • カーネル仮想アドレス:ffffea0000000000
  • 物理アドレス:00006200000000000

ユーザースペースのmmapを介してこの物理アドレスにアクセスしようとしています。しかし、次のコードはカーネルをクラッシュさせます。

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. */
4

2 に答える 2

21

私は問題を見つけたと思います-それはx86の/dev/memメモリマッピング保護に関係しています。

PlはこのLWNの記事を参照してください:「x86:構成オプションで/ dev/mem制限を導入する」 http://lwn.net/Articles/267427/

CONFIG_NONPROMISC_DEVMEM

現在(最近の3.2.21カーネルでこれをテストしました)、configオプションはCONFIG_STRICT_DEVMEMと呼ばれているようです。

カーネル構成を変更しました:

$ grep DEVMEM .config
# CONFIG_STRICT_DEVMEM is not set
$ 

上記のprgが以前のカーネルでCONFIG_STRICT_DEVMEMSETを使用して実行された場合、dmesgは次のことを示します。

[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が実行されたとき:

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

これは、「offset」パラメーターが> 1 MB(x86では無効)(16MBであった)であるためです。

mmapオフセットを1MB以内にした後:

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

できます!詳細については、上記のLWNの記事を参照してください。

PATをサポートするx86アーキテクチャ(ページ属性テーブル)では、カーネルは引き続きDRAM領域のマッピングを防止します。カーネルソースに記載されているこの理由は次のとおりです。

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

このチェックにより、上記と同様のエラーが発生します。例えば:

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

この制限は、PATを無効にすることで取り除くことができます。PATは、起動時にカーネルコマンドラインに「nopat」引数を追加することで無効にできます。

于 2012-08-10T08:27:07.633 に答える
3

PATをサポートするx86アーキテクチャ(ページ属性テーブル)では、カーネルはDRAM領域のマッピングを防ぐことができます(CONFIG_NONPROMISC_DEVMEMを設定せずにコンパイルされた場合でも)。

カーネルソースに記載されているこの理由は次のとおりです。

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

このチェックにより、dmesg上記のkaiwanの回答に記載されているものと同様のエラーが表示されます。例えば:

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

この制限は、PATを無効にすることで取り除くことができます。

PATはnopat、起動時にカーネルコマンドラインに引数を追加することで無効にできます。

于 2016-04-14T21:34:35.300 に答える