「kprobes_register」(kprobes)が「flush_tlb_all」などのシンボルのシンボルアドレスを検索できますが、「sys_call_table」は検索できないのはなぜですか?

「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セクションにあり、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調査するアドレスがある場合、後者はアドレスがカーネルテキストの一部であることを確認します。

おすすめ記事