2017-03-23 5 views
1

カーネルモジュール(LKM)を使用すると、ftrace関数を使用して、FTRACE_OPS_FL_SAVE_REGSFTRACE_OPS_FL_IPMODIFYフラグを設定することができます。のようなシンボルアドレス:ftraceハンドラから元の関数に戻るときにタスクpt_regsを復元する

static void notrace my_ftrace_handler(unsigned long ip, unsigned long parent_ip, 
     struct ftrace_ops *fops, struct pt_regs *regs) { 
    regs->ip = new_addr; 
} 

ここで、new_addrは新しい機能のアドレスです。 kpatchツールはこれを使用しますが、元の関数には戻っていません。

関数の最後に指摘している場合new_addrで私がしようとするこの:

task_pt_regs(current)->ip = orig_addr + MCOUNT_INSN_SIZE; 

、一部の機能は問題なく進むが、ほとんどは、呼び出しプロセスのセグメンテーション違反を引き起こします。

ftrace関数には、元の関数に戻ったときに現在のタスクpt_regsを復元するコードが組み込まれています。そのため、自分自身の関数に行き、問題のない引数を持つことができます。ただし、コードのこの時点では、ftraceは含まれなくなりました。どのようにカーネルに現在のレジスタをリセットしないように指示するのでしょうか?新しい復帰アドレスで関数が使うことができますか?

答えて

0

これを投稿した後、おそらくftraceハンドラ内のpt_regs *regsポインタから直接引数を読み取ることができるとの考えがありました。あなたはそうすることができます。

int donotexec(void) { 
     return -EACCES; 
} 

static void notrace my_ftrace_handler(unsigned long ip, unsigned long parent_ip, 
        struct ftrace_ops *fops, struct pt_regs *regs) { 

    struct linux_binprm *bprm = (struct linux_binprm *)regs->di; 

    if (bprm->file) 
      if (allowed_to_exec(bprm->file)) 
        regs->ip = (unsigned long)donotexec; 
} 

この関数フックsecurity_bprm_checkallowed_to_execは別の機能チェックつまり:あなたは、ハンドラ自体からあったりどこかに戻るかどうかを決定しながら、別の関数にリダイレクトしないことで、あなたは、レジスタとリターンアドレスを保存することができますregs->diレジスタから読み取られたbprm->file

これはアーチに依存します(カーネルのpt_regs構造体がarch/x86/include/asm/ptrace.hにあります)。これは5つの関数引数に制限されています。

関連する問題