Linuxでの0番地のmmapについて

Linux Kernel では、ユーザプロセスが 0 番地に mmap を実行することが可能なので、

http://trackback.blogsys.jp/livedoor/kmckk/1202810

直接リンク先の本題とは関連しないけれど、Linuxでの0番地のmmapについて思い出したことがあるのでちょっとメモしておく。

まず、kernelのソースの fs/binfmt_elf.c の関数load_elf_binary の中にこんなコードがあった。

	if (current->personality & MMAP_PAGE_ZERO) {
		/* Why this, you ask???  Well SVr4 maps page 0 as read-only,
		   and some applications "depend" upon this behavior.
		   Since we do not have the power to recompile these, we
		   emulate the SVr4 behavior. Sigh. */
		down_write(&current->mm->mmap_sem);
		error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
				MAP_FIXED | MAP_PRIVATE, 0);
		up_write(&current->mm->mmap_sem);
	}

どういう時かよくわからないけど、SVr4との互換性のために0番地のページをread-only,実行可能でマッピングするケースがある。



それから、以前Ubuntu 8.04でqemuを使うときにmmapがPermisson deniedではじかれたことがあった。
Ubuntu7.10では問題がなかったのにUbuntu8.04ではkernelのバージョンが上がって若いアドレスへのmmapが制限されている。
デフォルトでは最初の64KBの空間への一般ユーザのmmapは禁止されている。sudo すれば可。
ここで話したときのスライドに載せた。(24ページ目)

これの対策は /etc/sysctl.confを以下のように修正してリブートする
vm.mmap_min_addr = 65536  -> これを4096に変更
vm.vdso_enabled = 0   を追加

似たようなことがWineでもあるらしい。
Wine problems with new vm.mmap_min_addr setting

要するに最近のkernelでは0番地のページをmmapしようとしたら意識して許可してやる必要があるようだ。


(2009.7.24 追記)

Ubuntu 9.04でwineをインストールすると /etc/sysctrl.d/30-wine.conf というファイルができて、その中身は

$ cat /etc/sysctl.d/30-wine.conf 
# Wine needs to access the bottom 64k of memory in order to launch
# 16 bit programs.
vm.mmap_min_addr = 0
$ 

つまり、0番地からmmapが許可される設定になる。