件名: PPC アセンブリ言語 - Linux Loadble カーネル モジュール
詳細:システムコール テーブル フックでカーネルから呼び出されたときにローカル TOC 領域 (r2) にアクセスするにはどうすればよいですか?
syscall テーブル フックを使用してシステム コールをインターセプトし、システム コールに関する情報をログに記録してから、元のハンドラにコールを渡す Linux 用のロード可能なカーネル モジュールを作成しました。これはセキュリティ製品の一部です。私のモジュールは問題なく動作し、32 ビットと 64 ビットの両方のカーネルをすべて x86 ハードウェアで実行する、多種多様な Linux カーネル バージョンとディストリビューションで実行される製品コードです。
このコードを PPC プロセッサ用の Linux で実行できるように移植しようとしていますが、いくつかの問題が発生しました。Linux カーネル ソースを使用すると、システム コール テーブルが PPC でどのように異なる方法で実装されているかを簡単に確認できます。テーブル内のエントリを、自分でコンパイルしたハンドラーの関数アドレスに置き換えることができます。問題ありません。
しかし、ここで私が問題を抱えている問題があります。PPC ABI は、CPU の R2 レジスタに格納されているテーブル オブ コンテンツ (TOC) アドレスと呼ばれるものを使用し、そのレジスタに含まれるアドレス (TOC アドレス) からのオフセットを使用して、モジュールのグローバルおよびローカル データをアドレス指定することを期待しています。これは、コンパイラーが呼び出しを行う前にモジュールの TOC アドレスをレジスターにロードすることを知っているため (または、通常、関数が独自のコードによって呼び出されるため、既にそこにあるため)、関数呼び出しが行われる通常のケースでは正常に機能します。
ただし、(実行時にロードされたカーネル モジュールから) 独自の関数のアドレスをシステム コール テーブルに配置すると、カーネルは、コンパイルされた C コードが期待するものではない R2 値でハンドラーを呼び出すため、コードが取得されます。データにアクセスできなくても制御できます。
この状況を処理する方法を示すサンプルコードを知っている人はいますか? カーネルを再コンパイルできません。これは実行時の syscall テーブル フックの簡単なケースですが、私はまだそれを理解していないか、PPC に固有の例を見つけていません。
アイデアは次のとおりです。
R2 値を保存し、レジスタにローカル TOC アドレスをロードし、コードを実行し、元のハンドラーを呼び出す前に古い値を復元するアセンブリ言語スタブを手作業でコーディングします。私にはこれを行うための PPC アセンブリの経験がありませんし、うまくいくかどうかもわかりません。
TOC を使用せずにコードを生成する魔法の gcc オプション。"-mno-toc"
私の PPC6 Linux では動作しない文書化された gcc オプションがあります。システム V.4 と組み込み PowerPC のオプションのみのようです。
どんな助けでも大歓迎です!
ありがとう!