kprobes_register
カーネルシンボルのアドレスを取得するために使用される次のカーネルモジュールのソースコードを検討してください。
このようなシンボルには機能しますflush_tlb_all
が、それは機能しませんsys_call_table
。
すばやく検索するには、次のコマンドを使用します/proc/kallsyms
。
sudo cat /proc/kallsyms | grep -E '\sflush_tlb_all$|\ssys_call_table$'
ffffffff86a83e20 T flush_tlb_all
ffffffff87a002e0 D sys_call_table
違いは、(man nm
)がflush_tlb_all
このtext
セクションにあり、sys_call_table
このdata
セクションにあることです。ただし、両方の記号はグローバル(外部)です。
kprobes_register
住所を照会するためになぜ使用できないのですかsys_call_table
?
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#define MAX_SYMBOL_LEN 64
static char symbol[MAX_SYMBOL_LEN] = "flush_tlb_all";
module_param_string(symbol, symbol, sizeof(symbol), 0644);
/* For each probe you need to allocate a kprobe structure */
static struct kprobe kp = {
.symbol_name = symbol,
};
static int __init kprobe_init(void)
{
int ret;
ret = register_kprobe(&kp);
if (ret < 0) {
pr_err("register_kprobe failed, returned %d\n", ret);
return ret;
}
pr_info("Planted kprobe at %p\n", kp.addr);
return 0;
}
static void __exit kprobe_exit(void)
{
unregister_kprobe(&kp);
pr_info("kprobe at %p unregistered\n", kp.addr);
}
module_init(kprobe_init);
module_exit(kprobe_exit);
MODULE_LICENSE("GPL");
ベストアンサー1
違いは、(
man nm
)がflush_tlb_all
このtext
セクションにあり、sys_call_table
このdata
セクションにあることです。ただし、両方の記号はグローバル(外部)です。
これがまさにregister_kprobe
失敗する理由ですsys_call_table
。カーネルテキストでのみ検索を許可します。kprobe_register
着信電話check_kprobe_address_safe
調査するアドレスがある場合、後者はアドレスがカーネルテキストの一部であることを確認します。