[Patch] Oops with serial module (was:RE: problem with automounter

Bernhard Kaindl (bk@suse.de)
Sat, 10 Jul 1999 14:36:01 +0200 (MEST)


Hi, Linus,

Summary: many Modules like serial.o can cause Oopses when inserted over a
comiled-in version of the same module.

On Thu, 8 Jul 1999, Frank Butter wrote:

> On 08-Jul-99 Guenther Sohler wrote:
> > cat /dev/ttyS0, cat /dev/ttyS1 reported an input/output-error
> >
> > proc/devices reports, that ttyS is loaded
> >
> > lsmod reports, that module serial is loaded ...
> > This made me thinking, because I was pretty sure, that I had compiled in
> > serial
> > support within the kernel core itself ..
>
> This is a well known problem in SuSE 6.1. The serial.o is loaded somehow
> "automatically", so when you compile it into the kernel also, it conflicts
> with that. Just leave it out it should work fine. Sorry, but since
> this was fixed so easily, I didn't spent more time for analysis...
>

The Oops can happen on any system i can think of when one installs
serial.o as module, later decides to compile it in and later somehow
the module gets loaded. One calls rmmod serial and when sombody accesses
the device, the Oops happens.

The fact is that not a user process explicitely requests overloading the
module, but kmod itself does it automatically e.g. when setserial is called.

The fact is, that inserting a compiled-in module often leads to an Oops,
e.g. also with sg.o, sr_mod.o if I remember correctly, but there are more.

Anyway, this patch prevents most of them to be get overloaded, it checks
the exports of the module and looks if they are already present i the kernel.
This fixes most oops possibilies and doesn't hurt trivial modules like dummy,
which don't export symbols, so they can still be overloaded.

Agreed?

--- linux/kernel/module.c Sun Dec 27 19:41:41 1998
+++ linux/kernel/module.c Fri Apr 9 14:20:14 1999
@@ -105,6 +105,25 @@
}

/*
+ * Find a kernel symbol
+ */
+
+static struct module_symbol *
+get_kernel_symbol(const char * symname)
+{
+ struct module_symbol *sym;
+ unsigned i;
+
+ for (i = kernel_module.nsyms, sym = kernel_module.syms; i > 0;
+ --i, ++sym) {
+ if (strcmp(sym->name, symname) == 0) {
+ return sym;
+ }
+ }
+ return 0;
+}
+
+/*
* Allocate space for a module.
*/

@@ -295,6 +314,25 @@
to make the I and D caches consistent. */
flush_icache_range((unsigned long)mod, (unsigned long)mod + mod->size);

+ /*
+ * Look if an exported symbol if already in the kernel,
+ * if so, i is likely that the driver cannot be reloaded now.
+ */
+ if (mod->nsyms) {
+ if (mod->syms) {
+ struct module_symbol * x;
+ if ((x=get_kernel_symbol(mod->syms->name))) {
+ error = -EEXIST;
+ printk(KERN_ERR "symbol %s: module %s compiled in!\n",
+ mod->syms->name, name);
+ put_mod_name(n_name);
+ *mod = mod_tmp;
+ module_list = mod->next;
+ goto err1;
+ }
+ }
+
+ }
/* Update module references. */
mod->next = mod_tmp.next;
mod->refs = NULL;

-- 

- Bernd

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/