[PATCH 09/16] modprobe: load modules with grab_elf_file_fd()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In the old implementation, the loader didn't care about whether
a file is an ELF-file or not, and let init_module() sort it out.

In the new implementation, the loading fails with errno = ENOEXEC
if the file isn't an ELF-file.

However, the new logic does not pass the testing, specifically
test-modprobe/10alias.sh. To work around this, the commit adds a
hack that replicates the old way, when grab_elf_file_fd() does
return errno = ENOEXEC.

Obviously, this needs to be fixed. To replicate the problem,
simply remove the hack.

Signed-off-by: Andreas Robinson <andr345@xxxxxxxxx>
---
 modprobe.c |   36 ++++++++++++++++++++++++------------
 1 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/modprobe.c b/modprobe.c
index c0680a7..1cbbeff 100644
--- a/modprobe.c
+++ b/modprobe.c
@@ -667,8 +667,7 @@ static int insmod(struct list_head *list,
 		   const char *cmdline_opts)
 {
 	int ret, fd;
-	unsigned long len;
-	void *map;
+	struct elf_file *module;
 	const char *command;
 	struct module *mod = list_entry(list->next, struct module, list);
 	int rc = 0;
@@ -712,21 +711,33 @@ static int insmod(struct list_head *list,
 		goto out_optstring;
 	}
 
-	map = grab_fd(fd, &len);
-	if (!map) {
+	module = grab_elf_file_fd(mod->filename, fd);
+	if (!module) {
+		/* This is an ugly hack that maintains the logic where
+		 * init_module() sets errno = ENOEXEC if the file is
+		 * not an ELF object.
+		 */
+		if (errno == ENOEXEC) {
+			struct stat st;
+			optstring = add_extra_options(mod->modname,
+				optstring, options);
+			if (dry_run)
+				goto out;
+			fstat(fd, &st);
+			ret = init_module(NULL, st.st_size, optstring);
+			goto out_hack;
+		}
+
 		error("Could not read '%s': %s\n",
 		      mod->filename, strerror(errno));
 		goto out_unlock;
 	}
-
-	/* Rename it? */
 	if (newname)
-		rename_module(mod, map, len, newname);
-
+		rename_module(mod, module->data, module->len, newname);
 	if (strip_modversion)
-		strip_section(mod, map, len, "__versions");
+		strip_section(mod, module->data, module->len, "__versions");
 	if (strip_vermagic)
-		clear_magic(mod, map, len);
+		clear_magic(mod, module->data, module->len);
 
 	/* Config file might have given more options */
 	optstring = add_extra_options(mod->modname, optstring, options);
@@ -736,7 +747,8 @@ static int insmod(struct list_head *list,
 	if (dry_run)
 		goto out;
 
-	ret = init_module(map, len, optstring);
+	ret = init_module(module->data, module->len, optstring);
+out_hack:
 	if (ret != 0) {
 		if (errno == EEXIST) {
 			if (first_time)
@@ -753,7 +765,7 @@ static int insmod(struct list_head *list,
 			rc = 1;
 	}
  out:
-	release_file(map, len);
+	release_elf_file(module);
  out_unlock:
 	close_file(fd);
  out_optstring:
-- 
1.6.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-modules" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux