システムコールのアドレスを取得するために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_name
addr
register_kprobe
出荷書類ビーチ):addr
関数の起動時にスタック内のすべての項目を含みます。これはゼロではない可能性が高いため、両方のsymbol_name
合計はaddr
ゼロではなくregister_kprobe
(22)失敗します。EINVAL
次のようにこの問題を解決できます。
int ret;
struct kprobe kp = {
.symbol_name = name
};
unsigned long retval;
これにより、構造の他のメンバーがデフォルト値に初期化されます。