Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use exported symbols optionally only if they are present in an insmoded Linux Kernel module?

I am modifying a Linux Kernel to add some functionality to the Linux Virtual Server (LVS).

I developed a module (which I called net/netfilter/ipvs/ip_vs_utils.c) with some functions to be used when load-balancing. All the functions here are exported using EXPORT_SYMBOL().

This module, logically is not loaded all the time. My intention is to allow the user to decide if he want to use this additional functionality or not (loading or unloading the module).

My question is how could I invoke these functions OPTIONALLY (depending if the module is running or not) from a existing (and of course modified) module (net/netfilter/ipvs/ip_vs_core.c). Something like this:

if(ip_vs_utils_IsLoaded)
{
  function1(arg1, arg2, arg3); // being function1 defined on ip_vs_utils.c
}
like image 971
marcocamejo Avatar asked Jul 13 '12 02:07

marcocamejo


1 Answers

I think you need a trampoline always(or almost always) loaded into kernel.

In trampoline code, you need to such variables.

struct module *ip_vs_utils_mod;
EXPORT_SYMBOL(ip_vs_utils_mod);

/* function pointers */
ret_type (*ip_vs_utils_afunc_ptr)(func_arg_list); /* Add static if you put it in a header file! */
EXPORT_SYMBOL(ip_vs_utils_afunc_ptr); /*  ******EXPORTED***** */

When the ip_vs_utils is loaded, you need to init all the variables, initialization code in ip_vs_utils.c:

ip_vs_utils_mod = THIS_MODULE;

/* init function pointers */

/* ip_vs_utils_afunc_impl is the real implementation
 * of the function, it is *****NOT***** needed to export it
 */
ip_vs_utils_afunc_ptr = ip_vs_utils_afunc_impl;

And add the trampoline functions in trampoline code:

ret_type ip_vs_utils_afunc(func_arg_list)
{
   ret_type ret = DEFAULT_RET;

   if (try_module_get(ip_vs_utils_mod)) {
       ret = (*ip_vs_utils_afunc_ptr)(func_arg_list);
       module_put(ip_vs_utils_mod);
   }
   return ret;
}

try_module_get() is needed to protect the module from being suddenly unloaded while ip_vs_utils_afunc_ptr() is being invoked. You can also use RCU instead to reduce the overhead of try_module_get()/module_put(). (But it is hard)

Or you can used some trampoline-hack like dynamic link in userspace(you may need to change a lot in the linux kernel)

like image 104
Lai Jiangshan Avatar answered Nov 15 '22 10:11

Lai Jiangshan