From my understanding the function kallsyms_lookup_name
is not exported by the kernel, but a lot of modules use tricks to access it anyways. I was initially trying to use a module which uses kprobe
to get a pointer to kallsyms_lookup_name
, but when the pointer was called I get a segmentation fault. I've boiled that code down to the bare minimum to reproduce the error:
typedef unsigned long (*kallsymsFn)(const char *);
// Not part of the problem, just a utility function to log the symbol name of any found functions. The seg fault still happens without this.
static void log_symbol(void *symbol)
{
char *fname_lookup = kzalloc(NAME_MAX, GFP_KERNEL);
if (!fname_lookup)
return;
sprint_symbol(fname_lookup, symbol);
printk(KERN_INFO "Got '%s'.\n", fname_lookup);
kfree(fname_lookup);
}
// Function which initalizes the module
static int memflow_init(void)
{
struct kprobe kp = {0};
int ret = 0;
kp.symbol_name = "kallsyms_lookup_name";
printk(KERN_INFO "Regsitered kprobe.\n");
ret = register_kprobe(&kp);
if (ret < 0)
return ret;
kallsymsFn kallsyms = (kallsymsFn)kp.addr;
log_symbol(kallsyms);
unregister_kprobe(&kp);
printk(KERN_INFO "Unregsietered kprobe.\n");
// Seg fault happens when trying to call the found pointer to kallsyms_lookup_name
log_symbol(kallsyms("kvm_lock"));
return 0;
}
The full dmesg
output can be found here, but these are what I believe to be the important bits:
[ +3.821286] Regsitered kprobe.
[ +0.000815] Got 'kallsyms_lookup_name+0x4/0xd0'.
[ +0.048238] Unregsietered kprobe.
[ +0.000003] traps: Missing ENDBR: kallsyms_lookup_name+0x4/0xd0
...
[ +0.000004] ? kallsyms_lookup_name+0x4/0xd0
[ +0.000012] memflow_init+0x82/0xc0 [memflow 21eb138fb4e295ab5c057ad4052116921bf19468]
[ +0.000018] ? kallsyms_lookup_name+0x4/0xd0
[ +0.000008] ? __pfx_init_module+0x10/0x10 [memflow 21eb138fb4e295ab5c057ad4052116921bf19468]
As you can see, the function is found fine, but crashes and I don't know why. This clearly works for other people as well but there is something about my setup which causes this to break. My kernel is 6.2.13-arch1-1
and both CONFIG_KALLSYMS=y
, and CONFIG_KALLSYMS_ALL=y
are present in /proc/config.gz
.
Things I have tried:
I have tried to fix this for many hours, here's what doesn't work:
- Subtracting 4 (the offset) from the pointer. It seems like
kallsyms_lookup_name+0x4/0xd0
has an offset of 4 so I tried removing that offset but to no avail. - Trying a completely different method of capturing
kallsyms_lookup_name
. I tried using this technique instead but it too yields the same results. - Different target symbols. It doesn't seem to be anything special about
vm_list
.
To my untrained eyes it really seems like there's something wrong with the function pointer, but the other technique gave me the same thing so I'm at a loss for what could be causing this.