x86_32上のLinuxカーネルv3.5でsys_execvesyscallをフックしようとしています。sys_call_tableエントリアドレスをフック関数に変更するだけです
asmlinkage long (*real_execve)( const char __user*, const char __user* const __user*,
const char __user* const __user* );
...
asmlinkage long hook_execve( const char __user* filename, const char __user* const __user* argv,
const char __user* const __user* envp )
{
printk( "Called execve hook\n" );
return real_execve( filename, argv, envp );
}
...
real_execve = (void*)sys_call_table[ __NR_execve ];
sys_call_table[ __NR_execve ] = (unsigned long)hook_execve;
sys_call_tableエントリを変更するためのページ権限を設定しましたが、前述のスキームは別のsyscall(chdir、mkdirなど)でもうまく機能します。しかし、execveフックで、nullポインターの逆参照が発生しました。
Mar 11 14:18:08 mbz-debian kernel: [ 5590.596033] Called execve hook
Mar 11 14:18:08 mbz-debian kernel: [ 5590.596408] BUG: unable to handle kernel NULL pointer dereference at (null)
Mar 11 14:18:08 mbz-debian kernel: [ 5590.596486] IP: [< (null)>] (null)
Mar 11 14:18:08 mbz-debian kernel: [ 5590.596526] *pdpt = 0000000032302001 *pde = 0000000000000000
Mar 11 14:18:08 mbz-debian kernel: [ 5590.596584] Oops: 0010 [#1] SMP
arch/x86/kernel/entry_32.S
が含まれているため、3つのパラメーターを使用してsys_execveを呼び出しますPTREGSCALL3(execve)
。ただし、4つのパラメーター(追加struct pt_regs*
)を使用して呼び出しようとしましたが、同じエラーが発生しました。たぶん、実行するためのこのアプローチに何かが完全に間違っていますか?それとも私は何かを逃しましたか?
更新#1
実際には(ではなく)sys_call_table[ __NR_execve ]
のアドレスが含まれていることがわかりました。それは次のように定義されています:ptregs_execve
sys_execve
arch/x86/kernel/entry_32.S
#define PTREGSCALL3(name) \
ENTRY(ptregs_##name) ; \
CFI_STARTPROC; \
leal 4(%esp),%eax; \
pushl_cfi %eax; \
movl PT_EDX(%eax),%ecx; \
movl PT_ECX(%eax),%edx; \
movl PT_EBX(%eax),%eax; \
call sys_##name; \
addl $4,%esp; \
CFI_ADJUST_CFA_OFFSET -4; \
ret; \
CFI_ENDPROC; \
ENDPROC(ptregs_##name)
...
PTREGSCALL3(execve)
したがって、変更sys_execve
するには、アドレスを変更せずにコードを置き換える必要がありますか?私はここで似たようなものを読みました、これは行く方法ですか?
更新#2
実際、私は次の呼び出しシーケンスを見つけました。do_execve->do_execve_common->search_binary_handler->security_bprm_check
これsecurity_bprm_check
は、バイナリの実行を制御するLSM(Linux Security Module)操作のラッパーです。その後、私はこのリンクを読んでたどりました、そして私はそれを動かしました。実行するプロセスの名前が表示されるようになったので、問題は解決しましたが、それが正しいかどうかはまだわかりません。たぶん、他の誰かがこれらすべてのものについていくらかの明確さを追加するでしょう。