Mitsukiの魔法実験室

Mitsuki's Magic Laboratory
Since 2002.09.14

dlopen(3) した共有ライブラリファイルに書き込みしたら SEGV するらしい

Posted at 2007/04/01 16:15 in Unix

DSAS開発者の部屋:なぜ apache module を更新すると Segmentation fault するのか
を読んで最初に思ったのは、なんで .so の上書きそのもので "Text file busy" にならないんだろーという点。
 というのは最近の(*1) unix 系だと、exec(2) した実行ファイルを書き込み可能な形で open(2)等 しようとすると "Text file busy" なエラーになるので、そこからの推測で dlopen(3) でもそうなるんじゃないかなーと(*2)。exec(2) も dlopen(3) も実行可能バイナリをプロセス空間にマップするという意味では実質似たようなものだし。

*1)昔の商用 UNIX は exec(2) しててもそのまんま書き込めたので、実行中の(.soではない)実行ファイルを上書き cp して SEGV なんてイベントがそれなりにあったらしい。
*2)Windows は EXE も DLL も実行中は書き込みロックされるので、そちらからの連想もある。

 というわけで、実行環境が手元になかったので、何故か手元にあった FreeBSD のソースを眺めてみた。
 FreeBSD6 の場合、exec(2) した際に実行バイナリファイルを指す vnode に VV_TEXT フラグが付くので(src/sys/kern/kern_exec.c)、open(2) などファイルを変更する可能性のあるシステムコールではこれの有無をチェックして、VV_TEXT付きなら ETXTBSY を返す模様(src/sys/kern/vfs_vnops.c)。その結果 "Text file busy" のエラーになる。
 じゃあ dlopen(3) はというと、実行バイナリを O_RDONLY で open(2) して mmap(2) してるものの(libexec/rtld-elf/rtld.c)、VV_TEXT をセットしている様子はない。って、RTLD はユーザーコードなので付けようがないと思い直して、なら mmap(2) が PROT_EXEC のときに付けたりしてないかなーと思ったけど、特にそういう処理はしてないぽい。そもそも VV_TEXT の付加処理自体 exec(2) と LKM 関連でしか使ってなさげ。
 帰宅して実際の環境で動作中の .so を適当なファイルで上書きしてやると、見事撃墜成功。うーん……。

 Linux の場合はこんな事例があった。ってそういえば livepatch とか調べた時に読んだような気がする。

 exec(2) 中に上書きできなくなったのはセキュリティ的な理由(実行中にパッチ当てられても困る)と認識してたんだけど、.so が上書きできるんじゃ意味ないような気がする……なんか理由でもあるのかなあ。

 というようなことを金曜にやってた。

Page 1/2: 1 2 [>]