カーネルモジュール(LKM)を使用すると、ftrace
関数を使用して、FTRACE_OPS_FL_SAVE_REGS
とFTRACE_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
は含まれなくなりました。どのようにカーネルに現在のレジスタをリセットしないように指示するのでしょうか?新しい復帰アドレスで関数が使うことができますか?