summary refs log tree commit diff
path: root/kernel
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2010-08-05 12:59:10 -0600
committerRusty Russell <rusty@rustcorp.com.au>2010-08-05 12:59:12 +0930
commit6526c534b2677ca601b7b92851437feb041d02a1 (patch)
treed6d0f6d8cf2b685b2d1d345d938ca5816860dd89 /kernel
parent49668688dd5a5f46c72f965835388ed16c596055 (diff)
downloadlinux-6526c534b2677ca601b7b92851437feb041d02a1.tar.gz
module: move module args strndup_user to just before use
Instead of copying and allocating the args and storing it in
load_info, we can just allocate them right before we need them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/module.c28
1 files changed, 13 insertions, 15 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 29dd232f8183..cabafe228444 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -114,7 +114,7 @@ struct load_info {
 	Elf_Ehdr *hdr;
 	unsigned long len;
 	Elf_Shdr *sechdrs;
-	char *secstrings, *args, *strtab;
+	char *secstrings, *strtab;
 	unsigned long *strmap;
 	unsigned long symoffs, stroffs;
 	struct {
@@ -2096,7 +2096,7 @@ static inline void kmemleak_load_module(const struct module *mod,
 }
 #endif
 
-/* Sets info->hdr, info->len and info->args. */
+/* Sets info->hdr and info->len. */
 static int copy_and_check(struct load_info *info,
 			  const void __user *umod, unsigned long len,
 			  const char __user *uargs)
@@ -2132,13 +2132,6 @@ static int copy_and_check(struct load_info *info,
 		goto free_hdr;
 	}
 
-	/* Now copy in args */
-	info->args = strndup_user(uargs, ~0UL >> 1);
-	if (IS_ERR(info->args)) {
-		err = PTR_ERR(info->args);
-		goto free_hdr;
-	}
-
 	info->hdr = hdr;
 	info->len = len;
 	return 0;
@@ -2150,7 +2143,6 @@ free_hdr:
 
 static void free_copy(struct load_info *info)
 {
-	kfree(info->args);
 	vfree(info->hdr);
 }
 
@@ -2468,7 +2460,7 @@ static struct module *layout_and_allocate(struct load_info *info)
 	err = module_frob_arch_sections(info->hdr, info->sechdrs,
 					info->secstrings, mod);
 	if (err < 0)
-		goto free_args;
+		goto out;
 
 	pcpusec = &info->sechdrs[info->index.pcpu];
 	if (pcpusec->sh_size) {
@@ -2476,7 +2468,7 @@ static struct module *layout_and_allocate(struct load_info *info)
 		err = percpu_modalloc(mod,
 				      pcpusec->sh_size, pcpusec->sh_addralign);
 		if (err)
-			goto free_args;
+			goto out;
 		pcpusec->sh_flags &= ~(unsigned long)SHF_ALLOC;
 	}
 
@@ -2507,8 +2499,7 @@ free_strmap:
 	kfree(info->strmap);
 free_percpu:
 	percpu_modfree(mod);
-free_args:
-	kfree(info->args);
+out:
 	return ERR_PTR(err);
 }
 
@@ -2594,7 +2585,12 @@ static noinline struct module *load_module(void __user *umod,
 
 	flush_module_icache(mod);
 
-	mod->args = info.args;
+	/* Now copy in args */
+	mod->args = strndup_user(uargs, ~0UL >> 1);
+	if (IS_ERR(mod->args)) {
+		err = PTR_ERR(mod->args);
+		goto free_arch_cleanup;
+	}
 
 	mod->state = MODULE_STATE_COMING;
 
@@ -2648,6 +2644,8 @@ static noinline struct module *load_module(void __user *umod,
  unlock:
 	mutex_unlock(&module_mutex);
 	synchronize_sched();
+	kfree(mod->args);
+ free_arch_cleanup:
 	module_arch_cleanup(mod);
  free_modinfo:
 	free_modinfo(mod);