]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Fix module load failure case
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 10 Jun 2003 15:55:13 +0000 (08:55 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Tue, 10 Jun 2003 15:55:13 +0000 (08:55 -0700)
Milton Miller noticed a free-after-use problem in the cleanup path of a
failed module load.

The problem is that mod is moved to point from the sucked-in file
(always freed last) to the module core, after which time the
"free(mod->core), reference mod->percpu" sequence is bogus, eg.  when
the module_init function fails.

This is fixed by keeping the pointer in a local variable, which solves
the problem. We no longer need to reference the free'd data structure.

kernel/module.c

index 165c932882fdc521be05bd7df650fcaee70ae0ff..124cafd059ae8d901a50e26ea012f0b7b561238b 100644 (file)
@@ -1366,7 +1366,7 @@ static struct module *load_module(void __user *umod,
        long arglen;
        struct module *mod;
        long err = 0;
-       void *ptr = NULL; /* Stops spurious gcc uninitialized warning */
+       void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
 
        DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
               umod, len, uargs);
@@ -1496,13 +1496,14 @@ static struct module *load_module(void __user *umod,
 
        if (pcpuindex) {
                /* We have a special allocation for this section. */
-               mod->percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size,
-                                             sechdrs[pcpuindex].sh_addralign);
-               if (!mod->percpu) {
+               percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size,
+                                        sechdrs[pcpuindex].sh_addralign);
+               if (!percpu) {
                        err = -ENOMEM;
                        goto free_mod;
                }
                sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
+               mod->percpu = percpu;
        }
 
        /* Determine total sizes, and put offsets in sh_entsize.  For now
@@ -1643,8 +1644,8 @@ static struct module *load_module(void __user *umod,
  free_core:
        module_free(mod, mod->module_core);
  free_percpu:
-       if (mod->percpu)
-               percpu_modfree(mod->percpu);
+       if (percpu)
+               percpu_modfree(percpu);
  free_mod:
        kfree(args);
  free_hdr: