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