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:
kallsyms_lookup_name+0x4/0xd0
has an offset of 4 so I tried removing that offset but to no avail.kallsyms_lookup_name
. I tried using this technique instead but it too yields the same results.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.
The dmesg
you posted showed this error, which gives you the exact line that broke the kernel:
[ +0.000006] ------------[ cut here ]------------
[ +0.000001] kernel BUG at arch/x86/kernel/traps.c:255!
[ +0.000004] invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
[ +0.000002] CPU: 13 PID: 12449 Comm: modprobe Tainted: G U W OE 6.2.13-arch1-1 #1 fa8d27bf98b6325495c4c46c21163862ead484d0
[ +0.000002] Hardware name: Dell Inc. XPS 15 9510/01V4T3, BIOS 1.9.0 03/17/2022
[ +0.000001] RIP: 0010:exc_control_protection+0xc2/0xd0
If you go to your kernel version to find that line you'll see the BUG()
came from exc_control_protection()
as expected. You'll see above on line 216 that this function is part of an ifdef
for the IBT security feature:
#ifdef CONFIG_X86_KERNEL_IBT
Purely for testing purposes, you can try to disable IBT in your kernel to get your code working. But ideally, you should figure out how to get your code to work when IBT is on, since it's meant to protect your computer from certain attacks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With