Linux為什麼
為什麼 kprobes_register
(kprobes) 能夠檢索 flush_tlb_all
等符號的符號地址,但不能檢索 sys_call_table
?
考慮以下核心模組原始碼,它用於
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
節中,而 assys_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");
不同之處在於 (
man nm
)flush_tlb_all
是在text
節中,而 assys_call_table
在data
節中。但是,這兩個符號都是全域的(外部的)。這正是
register_kprobe
失敗的原因sys_call_table
:它只允許在核心文本中進行探測。kprobe_register
一旦它有要探測的地址就呼叫check_kprobe_address_safe
,後者檢查地址是否是核心文本的一部分。