We could also find the address of the kallsyms_lookup_name
function using kprobes
.
Quotes taken from here (kprobes)
Kprobes enables you to dynamically break into any kernel routine and collect debugging and performance information non-disruptively. You can trap at almost any kernel code address
To register a kprobe
, first a kprobe
struct needs to be initialized with the name of the symbol that needs to be trapped. We can do that by setting the symbol_name
in the kprobe
struct.
#include <linux/kprobes.h>
static struct kprobe kp = {
.symbol_name = "kallsyms_lookup_name"
};
The kprobe
struct has the following elements within it (shortened for brevity):
struct kprobe {
...
/* location of the probe point */
kprobe_opcode_t *addr;
/* Allow user to indicate symbol name of the probe point */
const char *symbol_name;
...
}
With the introduction of the “symbol_name” field to struct kprobe, the probepoint address resolution will now be taken care of by the kernel.
Once the symbol_name
is set, the address of the probe point is determined by the kernel.
So, now all that's left to do is to register the probe, extract the probepoint address and then unregister it:
typedef unsigned long (*kallsyms_lookup_name_t)(const char *name);
kallsyms_lookup_name_t kallsyms_lookup_name;
register_kprobe(&kp);
kallsyms_lookup_name = (kallsyms_lookup_name_t) kp.addr;
unregister_kprobe(&kp);
We now have the kallsyms_lookup_name
address. Using that we can find the sys_call_table
address the old-fashioned way:
kallsyms_lookup_name("sys_call_table");
Source for kprobe struct
Source for kprobe technique
/proc/kallsyms
but this seems like a bad idea and not generalizable." - FYI, replacing a system calls is a bad pattern too. It is used by some beginners as a "task" for their first kernel module. But Linux kernel is never encourages replacing a system calls. – Favour