kprobeを登録できません。

kprobeを登録できません。

システムコールのアドレスを取得するためにkprobeを登録しようとしています。しかし、私の試みはすべてエラーコードとして-22を返すようです。次のコード例(完全ではありませんが、関連機能が含まれています)は、呼び出し用のカーネルプローブを登録しようとしますsys_mkdir

前処理器や後処理器を指定しても問題にならないようです。プローブを登録するだけでは機能しません。

kallsyms_lookup_name注:カーネル5.7以降では、エクスポートされなくなったエクスポートされていない代替品としてkprobesを使用してみました。

unsigned long lookup_name(const char *name)  
{
        int ret;
        struct kprobe kp;
        unsigned long retval;
 
        kp.symbol_name = name;
        ret = register_kprobe(&kp);     
        if (ret < 0) {
                printk(KERN_DEBUG "register_kprobe failed for symbol %s, returned %d\n", name,
 ret);
                return 0;
        }
        retval = (unsigned long)kp.addr;
        unregister_kprobe(&kp);
        return retval;
}
                                                                                                  
static int __init mod_init(void)                                                              
{                                                                                                 
        int (*fn)(unsigned long param);

        fn = (void*)lookup_name("__x64_sys_mkdir");   
} 

答え1

構造体が完全に初期化されていないため、および間の相互排除または要件をkprobe満たすことはできません(表の3項目)。symbol_nameaddrregister_kprobe出荷書類ビーチ):addr関数の起動時にスタック内のすべての項目を含みます。これはゼロではない可能性が高いため、両方のsymbol_name合計はaddrゼロではなくregister_kprobe(22)失敗します。EINVAL

次のようにこの問題を解決できます。

        int ret;
        struct kprobe kp = {
                .symbol_name = name
        };
        unsigned long retval;

これにより、構造の他のメンバーがデフォルト値に初期化されます。

関連情報