Latest Tweets

MODEST: avoiding KERNEL OOPS when rmmod is executed

The matter

Current implementation of MODEST source code has an important issue: it is not capable of avoiding unloading it as long as a running instance of umodest user-space control utility is altering some process FDT.

The solution

Modern GNU/Linux kernels, like 2.6.18.X series, have a pair of C functions in order to control the reference counter of any loaded module.: try_module_get() and module_put(). Both of them are defined in the header file <linux/module.h>.

Because of the “strange” design of MODEST LKM, the kernel routines cannot control clearly what MODEST is doing at some time or, in fact, if there’s something using it and updating its reference counter accordingly. In the earlier GNU/Linux kernel versions, the reference counter must be updated by developers themselves using macros like MOD_INC_USE_COUNT, MOD_DEC_USE_COUNT. Nowadays, there’s no need to do this except in MODEST kernel module. What is the reason? Obviously, its internal design and concept.

Bear in mind that MODEST alters a process FDT through a user-space utility command called umodest. This tool is in charge of communicating with the LKM using /dev/modest special device file. As long as umodest is running in “-c” or “-d” mode, a FDT table is being altered but, checking the reference counter of kmodest.ko LKM, we can see it’s zero. So, what in heaven’s name is going on here? Clearly, there’s nothing telling the Kernel what’s happening. In particular, we are in charge of ensuring to increase or decrease the kmodest.ko reference counter by ourselves.

Inserting fd’ inside process FDT

Reading the sources, and no matter what kind of action will be taken using umodest user-space control utility, the only place where we have to put try_module_get() call will be in the do_insert_fd() function:

        /* Well, increases the count reference to this module : */
	/* Only we must increase its number in case of comopletely success inserting a new fd into the
	 * process's FDT, no matter what kind of action will be taken after doing this
	 */
	if(0==(try_module_get(THIS_MODULE)))
		/* OOps, there's an error !! : */
		printk(KERN_ERR "MODEST %s by %s: error in try_module_get()n", _VERSION_, _AUTHOR_);

Finally, to decrease the reference counter we have to add module_put() call inside the do_restore_task() function:

        /* Here, we can "release" its counter-usage field : */
	module_put(THIS_MODULE);

That’s all!! Just a piece of cake, isn’t it?

As a result …

There’s a video showing up these last MODEST changes right on the CVS repository. Stay tuned !