Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I access any kernel symbol in a kernel module?

I am wanting to use the function getname in my kernel module. It is not exported. Since I am running into this problem right now, I would like to know how to access and use any kernel symbol that is not exported. I figure that the steps necessary to use one will differ depending what the symbol is, so I'd like to see how it would be done for a type (e.g., a struct), a variable, a table of pointers (like the system call table), and a function. How can these be done in either of these cases:

  • When I know the address of the symbol from System.map or /proc/kallsyms.
  • When I know the name of the symbol and want to use kallsyms_lookup_name in retrieving it.

I currently know how to hijack system calls and this requires declaring something like

asmlinkage <return_type> (*<name_for_system_call>)(<the types of the its arguments separated by commas>);

Would something like that be used? In this answer to another question, the example presented by the poster is

#include <linux/kallsyms.h>

static void (*machine_power_off_p)(void);
machine_power_off = (void*) kallsyms_lookup_name("machine_power_off");

But what if the symbol returns a pointer? Would I place an asterisk to the left of (*machine_power_off_p)?

like image 858
Melab Avatar asked Nov 04 '16 20:11

Melab


1 Answers

#include <linux/fs.h> declares extern struct filename *getname(const char __user *);. A pointer to this function has type struct filename *(*)(const char __user *). If declaring a variable of that type, the variable name goes after the * in (*). So you can declare a variable of that type and assign the return value of kallsyms_lookup_name("getname") to it as follows:

static struct filename *(*getname_p)(const char __user *);

/* within a function body... */
getname_p = (struct filename *(*)(const char __user *))
            kallsyms_lookup_name("getname");

For your other case where you want to use a numeric address, just replace the kallsyms_lookup_name function call with the actual number (kallsyms_lookup_name returns the symbol value as a number anyway).

EDIT 2021-01-19

The GCC typeof extension can be used to copy the prototype of getname from #include <linux/fs.h> to the getname_p pointer as follows:

#include <linux/fs.h>

static typeof(&getname) getname_p;

/* within a function body... */
getname_p = (typeof(&getname))kallsyms_lookup_name("getname");

EDIT 2021-05-17

From the 5.7 kernel onwards kallsyms_lookup_name and kallsyms_on_each_symbol are no longer exported to loadable kernel modules.

like image 177
Ian Abbott Avatar answered Oct 22 '22 04:10

Ian Abbott