2017-06-18 27 views
0

私は初期のカーネルプログラミングに取り組んでいましたが、ioctlシステムコールの代わりに/ hookを使用しようとしていました。モジュールを使ってsyscallテーブルにフックする

ターゲットシステムは、カーネル3.10のmips(o32)システムです。

私はx86ベースのシステムで見た類似のプロジェクト/例に基づいて、私はうまくいくと思った基本的なスニペットに到達しました。私はSystem.mapにアクセスできないが、sys_call_tableアドレスに気づいたので、アドレス上での試みはターゲットシステム上の/proc/kallsymsに基づいている。私はこのアドレスがカーネルビルドからビルドに変わることを知っていますが、それは今のところ問題ではありません。これは実験目的のみのものです。その全体が

モジュール:

#include <linux/module.h> 
#include <linux/kernel.h> 
#include <linux/syscalls.h> 

static u32 **sct = (u32**)0x80008660; // `grep sys_call_table /proc/kallsyms` 

asmlinkage int (*ioctl_orig)(s32 fd, u32 cmd, void* addr); 
asmlinkage int ioctl_new(s32 fd, u32 cmd, void* addr) 
{ 
    printk("[IOC] Intercepted ioctl 0x%x to addr 0x%p\n", cmd, addr); 
    return ioctl_orig(fd, cmd, addr); 
} 

static int __init _enter(void) 
{ 
    ioctl_orig = (void*)sct[__NR_ioctl]; 
    sct[__NR_ioctl] = (u32*)ioctl_new; 

    printk("[IOC] Original IOCTL addr: %p\n", ioctl_orig); 
    printk("[IOC] New IOCTL addr: %p\n", sct[__NR_ioctl]); 
    return 0; 
} 

static void __exit _exit(void) 
{ 
    sct[__NR_ioctl] = (u32 *)ioctl_orig; 
    printk("[IOC] Unloaded\n"); 
} 

module_init(_enter); 
module_exit(_exit); 
MODULE_LICENSE("GPL"); 

明らかにこれは動作しないか、私はここに壁をこすることはありません。モジュールは正常にロードされ、_enter/_exitからprintkが実際に表示されますが、何らかの方法でカーネルに向けてioctlsを実行すると何も起こりません(私は、迎え入れられたioctlメッセージをioctl_newから見ることになります)間違った箇所を修正しています。

質問:明らか

  • :私は間違って何をしているのですか?
  • /proc/kallsymsは、syscallテーブルの先頭に正しいポインタを提供できますか。
  • sys_ioctlに関連付けられた値が/proc/kallsyms*sct[__NR_ioctl]と一致する必要がありますか、何か不足していますか?
  • 正しくキャスティングされていますか?
  • mctに適用できるsctableを変更するこの方法はありますか?
+0

"私が間違って何をしているのですか?" x86では、同じことをするには、いくつかのasm行でページ保護を無効にする必要があります。私はmipsに相当するものがあると思います。 – purplepsycho

+0

"私は'/proc/kallsyms' ...に頼ることができますか?"あなたのシステムに' 'kallsyms_lookup_name(" sys_call_table ")関数が存在しましたか?それはあなたに必要なものを返すはずです(https://stackoverflow.com/a/39202118/1212012) – purplepsycho

+0

cr0ページ保護ビットを認識しています私はMIPSで同様のメカニズムの証拠が見つかりませんでした。 – bjorn

答えて

0

アーチを見るには、/ MIPS /カーネル/ ftrace.cあなたは私が間違っているのは何

+0

3.10ソースツリーにsys32_call_tableの言及はありません。もっと最近のようですか? – bjorn

+0

確かに3.10には何もありませんが、syscallの引数を調べる必要があると思います。O32のように、__NR_O32_Linuxをシステムコール番号から差し引く必要がありますか? MIPS。 https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable/+/linux-3.10.y/arch/mips/include/uapi/asm/unistd.hどちらにしても、フックを直接実装することができます"fs/ioctl.c"と "fs/compat_ioctl.c"にあります。モジュールが必要な場合は、security_file_ioctl経由でSELinuxやTomoyoのようなロード可能セキュリティモジュールを実装することができます – alexst

0

「sys32_call_table」と呼ばれるテーブルを使用する必要があると信じて私をリード?

カーネルモジュールからシステムコールテーブルを変更しようとしています。これは安全ではなく、サポートされていません。それをしないでください。

システムコールを検査する場合は、ftrace,perfSystemTapなど、カーネルで利用可能ないくつかのツールがあります。どちらがあなたに最も適しているかは、あなたの特定の要件に依存します。

+0

これが実践的であることを完全に認識しています。それが私たちを助けることができるかどうかを見るためにftraceをさらに見ていきます。他の2つのオプションは、ターゲットシステム上では使用できません(強化された組み込みカーネル)。 – bjorn

0

@alexst true answer! は、MIPSアーキテクチャ用のLinux/unistd.hによると:

#define __NR_Linux 4000 
... 
#define __NR_ioctl (__NR_Linux + 54) 

ですから、__NR_ioctlからsubstract __NR_Linuxを必要とし、例えば:

ioctl_orig = (void*)sct[__NR_ioctl-__NR_Linux]; 
関連する問題