Re: help needed with EXPORT_SYMBOL

Previous thread: [PATCH] mips: irq: add statckoverflow detection by jiang.adam on Friday, August 20, 2010 - 11:31 pm. (3 messages)

Next thread: [-next PATCH] Fix s390 keyboard driver build break by Sachin Sant on Saturday, August 21, 2010 - 12:21 am. (2 messages)
From: Aijaz Baig
Date: Friday, August 20, 2010 - 11:57 pm

Hello,

Ive been trying to EXPORT a SYMBOL from a netfilter module (actually a
hook) to the KERNEL. Various modules seem to export various symbols to
the kernel (or so it seems), an example being x_tables which exports a
whole lot of functions like xt_register_target and so on and all other
netfilter modules which use these functions dont seem to have any
problems.

So why is it that when my netfilter module is exporting something to the
kernel and im tryin to use it from within a core kernel file, the
compiler flags a 'undefined reference to' error?

I googled and came to the conclusion from the kernelnewbies mailing list
that using kallsyms_lookup() seems to be the answer or is it?
So, if I do intend to use kallsyms_lookup how do I use it? There aren't
so many instances of it being used it seems.
 
Ive seen it being used in dev/core.c like so:
symname = kallsyms_lookup((unsigned long)sym, &symsize,&offset,&modname,
namebuf);

I am basically trying to call a function that MY module EXPORTs inside
one of the core linux routines. This would also mean that my netfilter
module must be compiled (and linked also maybe?..not so sound with link
time stuff) before the address becomes visible so that kallsyms_lookup
can find it. So do I really shd be using it and if so, how?

Any input is appreciated.

Regards,
Aijaz Baig.



--

From: Jan Engelhardt
Date: Saturday, August 21, 2010 - 2:23 am

There, you answered yourself. Exports only go one way. And that is
core -> module -> module.

--

From: Aijaz Baig
Date: Sunday, August 22, 2010 - 10:14 pm

Hello,

Yeah I do understand that part, but there has to be a way to do what I
am trying to do here isn't it?

And can anyone tell me can kallsyms_lookup() be used in such a
situation? If yes than how do I use it?

Regards,
Aijaz 

On Sat, Aug 21, 2010 at 2:53 PM, Jan  Engelhardt <jengelh@medozas.de>
wrote:
        
There, you answered yourself. Exports only go one way. And that is
core -> module -> module.




--

From: Brian Gerst
Date: Monday, August 23, 2010 - 4:48 am

Use an exported function pointer in the main kernel as a hook that the
module sets when it is loaded.  Note, you must use module_get and
module_put around the call to the module to prevent it from unloading
while in use.

--
Brian Gerst
--

From: Peter Zijlstra
Date: Monday, August 23, 2010 - 6:17 am

Please don't do any such thing, its impossible to use correctly.

Suppose there are two modular users, A and B.

Both have something like:

extern void (*fptr)(void);

static void (*old_fptr)(void);

static void func(void)
{
	/* foo */
	if (old_fptr)
		old_fptr();
}

module_init()
{
	old_fptr = fptr;
	fptr = A_func;
}

Then you load A, load B and unload A, then guess what happens?
--

From: Jan Engelhardt
Date: Monday, August 23, 2010 - 6:32 am

Though in case there is just a single user it can work out.
Just like bridge.c, and the bunch of nf_nat_*.c. :-)
Though yeah. Bad bad.

This is starting to sound pretty much like an XY problem: XY problem: 
You want to do X, but don't know how. You think you can solve it using 
Y, but don't know how to do that, either. You ask about Y, which is a 
strange thing to want to do. Just ask about X.

(And then there is still the "good idea to do X in the first place" 
thing.) Like what's so important to have as a module when you can build 

--

From: Peter Zijlstra
Date: Monday, August 23, 2010 - 6:43 am

We have this problem in several areas in the kernel (pm_idle being the
one I hate most since its in code I touch actually grew tons of users).

If you really need to export hooks, provide a registration mechanism and
an arbiter. A very simple, already existing, implementation of this
would be notification chains (include/linux/notifier.h), these provide a
registration interface, and the arbiter is a combination of static
priority combined with return codes.

A more complex example would be the cpuidle/pm_qos subsystem, where you
can register idle states and provide various attributes (exit latency,
energy break even duration, etc) and have the governor pick an idle
state depending on the predicted idle time and required exit latencies.

Bare function pointers suck.
--

From: Brian Gerst
Date: Monday, August 23, 2010 - 6:44 am

The assumption was that there was a single module using that hook.
For multiple users you'd need to use a register function that adds the
module to a linked list.

--
Brian Gerst
--

From: Peter Zijlstra
Date: Monday, August 23, 2010 - 7:05 am

Not really a future-proof design, is it?
--

From: Aijaz Baig
Date: Monday, August 23, 2010 - 9:44 pm

Hello everyone, 

thanks for sending in the replies with so many options. I am still a
relative newbie so please do bear with me guys if I sound a bit naive at
times.

I'll first start with brian's suggestion. He said:
"Use an exported function pointer in the main kernel as a hook that the
module sets when it is loaded.  Note, you must use module_get and
module_put around the call to the module to prevent it from unloading
while in use."

I have never used such a technique and do not understand what you mean.
Could you please elaborate a little. Do you mean I should NF_HOOK within
the kernel code and then make the function that I would like to execute
as the hookfn? Well..if this is what u meant then wouldn't it also cause
all hooks at that particular position to be executed as well? 

And then peter and finally jan came up with, perhaps better suggestions
(i really cannot judge the quality of any of these suggestions..m too
much of a noob to do that). I got confused in the XY explanation by jan
since there both X and Y are modules it seems and I was talking about a
module exporting a certain symbol to be used by the kernel. Peter did
suggest notification chains. Is there a simple example that I can look
at? Will it allow the kernel to see symbols defined within the module? 

Lastly, will I be able to use kallsyms_lookup() to do what I can? I
notice that it replaced EXPORT_SYMTAB sometime back. So if yes I can use
it, does anyone know how to fill in the very first parameter of this
function which says address (of what exactly and how am I supposed to
know this address?)

Keen to hear from you and once again, thank you for your inputs,

Regards,
Aijaz Baig.





--

From: Aijaz Baig
Date: Wednesday, August 25, 2010 - 2:27 am

Hi everyone

I am trying to understand if its possible to add functions dynamically
to the kernel source based on the presence of certain modules in the
running kernel image.

I did try what brian suggested with the function pointer and yeah it
does work. But I could not understand what peter was trying to say about
modular users since I suppose he mentioned one module (B in this case)
using a function pointer defined in (or by) module A. In my case, since
it is the kernel that is gonna use the function, I need to make sure
that the module doesn't get unloaded while we are using the function.

By the way Jan I couldnt find bridge.c although there is an object file
called bridge.o within /net/bridge. Nonetheless, I did check
nf_nat_ftp.c as an example to see if something similar is being done
there too. What I did find out is that nf_nat_ftp_hook is rcu assigned
in nf_nat_ftp.c however this function pointer is being used with
nf_contrack_ftp.c (im talkin 2.6.27.45 here). In this case, it still is
module1 <- module2 and not kernel <- module. Could you please elaborate
a little how it affects the latter case. Or perhaps u were commenting on
the former case since peter brought that to our notice.

thanks again for your replies and keen to hear your input
Regards,


--

From: Jan Engelhardt
Date: Wednesday, August 25, 2010 - 3:06 am

$ git grep -e br_handle_frame_hook v2.6.35 net/bridge/

See that, which is used kernel<-module. This frame hook has been changed 
in 2.6.36-rc1 which is why looking at 2.6.35 would be the short route.
--

From: Peter Zijlstra
Date: Wednesday, August 25, 2010 - 3:23 am

Right, so there's two problems there:

 - the exposed function pointer
 - unload serialization

The problem with the exposed function pointer is that two competing
modules can set the function pointer:

extern void (*ptr)(void);

static void (*old_ptr)(void);

void func(void)
{
  /* do something */
}

module_init()
{
  old_ptr = ptr;
  ptr = func;
}

module_exit()
{
  ptr = old_ptr;
  synchronize_stuff();
}

Now suppose two modules A and B both have that template, then load
module A, at that time ptr == A::func, A::old_ptr = NULL, right?

Then load B, then ptr == B:func, B::old_ptr = A::func.

then unload A, then ptr == NULL; /* hey where's B gone? */

Suppose module_exit() had read:

module_exit()
{
  if (ptr == func)
    ptr = old_ptr;
}

Then after A got unloaded, you'd have: ptr = B::func, B::old_ptr ==
A:func, and the world goes *bang* when you unload B.

If you'd have exposed the thing like:

static void (*callback)(void);

int set_foo_callback(void (*func)(void))
{
  if (callback && func)
    return -EBUSY;

  callback = func;
  synchronize_world();
  return 0;
}
EXPORT_SYMBOL_GPL(set_foo_callback);

Then there'd be no confusion, as loading B while A was already loaded
would fail since set_foo_callback() would fail with -EBUSY.


Now the synchronization issue, above represented by synchronize_world();
that will have to do something that ensures all current users of the ptr
have gone, taking a reference on the module will likely result in an
pinned module, since what will drop the ref again?

Module unload does a fairly heavy stop-machine thing, which might be
sufficient for some, but a sensible solution really depends on the
problem domain, RCU could be used in various ways.
--

From: Randy Dunlap
Date: Wednesday, August 25, 2010 - 8:37 am

See net/bridge/Makefile:

obj-$(CONFIG_BRIDGE) += bridge.o

bridge-y	:= br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \
			br_ioctl.o br_notify.o br_stp.o br_stp_bpdu.o \
			br_stp_if.o br_stp_timer.o br_netlink.o

and see Documentation/kbuild/makefiles.txt.

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
--

Previous thread: [PATCH] mips: irq: add statckoverflow detection by jiang.adam on Friday, August 20, 2010 - 11:31 pm. (3 messages)

Next thread: [-next PATCH] Fix s390 keyboard driver build break by Sachin Sant on Saturday, August 21, 2010 - 12:21 am. (2 messages)