unsigned num,
                      int (*unknown)(char *param, char *val));
 
+/* Called by module remove. */
+#ifdef CONFIG_SYSFS
+extern void destroy_params(const struct kernel_param *params, unsigned num);
+#else
+static inline void destroy_params(const struct kernel_param *params,
+                                 unsigned num)
+{
+}
+#endif /* !CONFIG_SYSFS */
+
 /* All the helper functions */
 /* The macros to do compile-time type checking stolen from Jakub
    Jelinek, who IIRC came up with this idea for the 2.4 module init code. */
 
        /* Module unload stuff */
        module_unload_free(mod);
 
+       /* Free any allocated parameters. */
+       destroy_params(mod->kp, mod->num_kp);
+
        /* release any pointers to mcount in this module */
        ftrace_release(mod->module_core, mod->core_size);
 
        unsigned int symindex = 0;
        unsigned int strindex = 0;
        unsigned int modindex, versindex, infoindex, pcpuindex;
-       unsigned int num_kp, num_mcount;
-       struct kernel_param *kp;
+       unsigned int num_mcount;
        struct module *mod;
        long err = 0;
        void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
 
        /* Now we've got everything in the final locations, we can
         * find optional sections. */
-       kp = section_objs(hdr, sechdrs, secstrings, "__param", sizeof(*kp),
-                         &num_kp);
+       mod->kp = section_objs(hdr, sechdrs, secstrings, "__param",
+                              sizeof(*mod->kp), &mod->num_kp);
        mod->syms = section_objs(hdr, sechdrs, secstrings, "__ksymtab",
                                 sizeof(*mod->syms), &mod->num_syms);
        mod->crcs = section_addr(hdr, sechdrs, secstrings, "__kcrctab");
         */
        list_add_rcu(&mod->list, &modules);
 
-       err = parse_args(mod->name, mod->args, kp, num_kp, NULL);
+       err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, NULL);
        if (err < 0)
                goto unlink;
 
-       err = mod_sysfs_setup(mod, kp, num_kp);
+       err = mod_sysfs_setup(mod, mod->kp, mod->num_kp);
        if (err < 0)
                goto unlink;
        add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
 
 #include <linux/err.h>
 #include <linux/slab.h>
 
+/* We abuse the high bits of "perm" to record whether we kmalloc'ed. */
+#define KPARAM_KMALLOCED       0x80000000
+
 #if 0
 #define DEBUGP printk
 #else
                return -ENOSPC;
        }
 
-       *(char **)kp->arg = (char *)val;
+       if (kp->perm & KPARAM_KMALLOCED)
+               kfree(*(char **)kp->arg);
+
+       /* This is a hack.  We can't need to strdup in early boot, and we
+        * don't need to; this mangled commandline is preserved. */
+       if (slab_is_available()) {
+               kp->perm |= KPARAM_KMALLOCED;
+               *(char **)kp->arg = kstrdup(val, GFP_KERNEL);
+               if (!kp->arg)
+                       return -ENOMEM;
+       } else
+               *(const char **)kp->arg = val;
+
        return 0;
 }
 
 }
 #endif
 
+void destroy_params(const struct kernel_param *params, unsigned num)
+{
+       unsigned int i;
+
+       for (i = 0; i < num; i++)
+               if (params[i].perm & KPARAM_KMALLOCED)
+                       kfree(*(char **)params[i].arg);
+}
+
 static void __init kernel_add_sysfs_param(const char *name,
                                          struct kernel_param *kparam,
                                          unsigned int name_skip)