まず、__fork
は、__libc_fork
の同義語で、直接フォークシステムコールを行います。 fork
は同じことを指す弱い記号です。他の共有ライブラリがその特定の関数を呼び出している場合は、これらの関数をオーバーライドすることができます。
$ readelf -Wa /lib/x86_64-linux-gnu/libc.so.6 | grep b84c0
42: 00000000000b84c0 784 FUNC GLOBAL DEFAULT 13 [email protected]@GLIBC_PRIVATE
80: 00000000000b84c0 784 FUNC GLOBAL DEFAULT 13 [email protected]@GLIBC_2.2.5
408: 00000000000b84c0 784 FUNC WEAK DEFAULT 13 [email protected]@GLIBC_2.2.5
しかし、自身のlibc内、リンカは__fork
が同じライブラリ内に位置していることを知っていて、その機能に到達するためにPLT通過しないことを選択します。それは直接コール命令を出すだけです。これは、モジュールが静的関数を呼び出すとき、またはライブラリがそれ自身の関数の1つを呼び出すときにGCCが行う一般的な最適化です。 (それはPLTを経た場合、コールは[email protected]
になります)、以下を参照してください:
$ objdump -d /lib/x86_64-linux-gnu/libc.so.6 | grep __fork | head -n 4
6a074: e8 47 e4 04 00 callq b84c0 <[email protected]@GLIBC_2.2.5>
00000000000b84c0 <[email protected]@GLIBC_2.2.5>:
b84da: 74 5c je b8538 <[email protected]@GLIBC_2.2.5+0x78>
b84e1: 74 ed je b84d0 <[email protected]@GLIBC_2.2.5+0x10>
あなたはフォークを使用するlibcの変更した場合()内部で、それは弱いシンボルを呼んでいた、そしてそれらはoverridden by the userかもしれません。したがって、リンカはPLTを通過する呼び出しを出す以外に選択肢はありません。つまり、実際にはLD_PRELOAD
でオーバーロードすることができます。
一般的に、このようなフォークをハイジャックするのは簡単ではありません。関数は常にforkシステムコールを直接呼び出すことができ、それを傍受する方法はありません。コードでpthreadが使用されている場合は、pthread_atfork
に興味があります。 glibc内の配列__fork_handlers
に機能を追加します。残念ながら、その配列は保護されているとマークされ、シンボルに直接アクセスすることはできません。
ちなみに、この種のものをデバッグするには、LDBIND_NOW = 1を設定し、GDBでシングルステップを実行して、どのシンボルが呼び出されたかを正確に監視すると便利です。 – dwks