[PATCH 4/4] Clean up get_section()

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

 



Combines three duplicate and almost-duplicate implementations in
modinfo.c, modprobe.c and moduleops_core.c

The new version gets endianness swapping from the implementation in
modinfo.c and bounds checking from the implementation in modprobe.

Signed-off-by: Andreas Robinson <andr345@xxxxxxxxx>
---
 elf_core.c       |   43 ++++++++++++++++++++++++++++++
 modinfo.c        |   53 +-------------------------------------
 modprobe.c       |   76 +++---------------------------------------------------
 moduleops_core.c |   21 +-------------
 util.c           |   28 ++++++++++++++++++++
 util.h           |    6 ++++
 6 files changed, 84 insertions(+), 143 deletions(-)
 create mode 100644 elf_core.c

diff --git a/elf_core.c b/elf_core.c
new file mode 100644
index 0000000..1525c36
--- /dev/null
+++ b/elf_core.c
@@ -0,0 +1,43 @@
+void *PERBIT(get_section)(void *file,
+			  unsigned long fsize,
+			  const char *secname,
+			  unsigned long *secsize,
+			  int conv)
+{
+	ElfPERBIT(Ehdr) *hdr;
+	ElfPERBIT(Shdr) *sechdrs;
+	ElfPERBIT(Off) e_shoff;
+	ElfPERBIT(Half) e_shnum, e_shstrndx;
+
+	const char *secnames;
+	unsigned int i;
+
+	if (fsize > 0 && fsize < sizeof(*hdr))
+		return NULL;
+
+	hdr = file;
+	e_shoff = END(hdr->e_shoff, conv);
+	e_shnum = END(hdr->e_shnum, conv);
+	e_shstrndx = END(hdr->e_shstrndx, conv);
+
+	if (fsize > 0 && fsize < e_shoff + e_shnum * sizeof(sechdrs[0]))
+		return NULL;
+
+	sechdrs = file + e_shoff;
+ 
+	if (fsize > 0 && fsize < END(sechdrs[e_shstrndx].sh_offset, conv))
+		return NULL;
+
+	/* Find section by name, return pointer and size. */
+
+	secnames = file + END(sechdrs[e_shstrndx].sh_offset, conv);
+	for (i = 1; i < e_shnum; i++) {
+		if (streq(secnames + END(sechdrs[i].sh_name, conv), secname)) {
+			*secsize = END(sechdrs[i].sh_size, conv);
+			return file + END(sechdrs[i].sh_offset, conv);
+		}
+	}
+	*secsize = 0;
+	return NULL;
+}
+
diff --git a/modinfo.c b/modinfo.c
index 81e40f4..07199c2 100644
--- a/modinfo.c
+++ b/modinfo.c
@@ -21,57 +21,6 @@
 #define MODULE_DIR "/lib/modules"
 #endif
 
-static int elf_conv;
-
-#define TO_NATIVE(x) END(x, elf_conv)
-
-static void *get_section32(void *file, unsigned long *size, const char *name)
-{
-	Elf32_Ehdr *hdr = file;
-	Elf32_Shdr *sechdrs = file + TO_NATIVE(hdr->e_shoff);
-	const char *secnames;
-	unsigned int i;
-
-	secnames = file
-		+ TO_NATIVE(sechdrs[TO_NATIVE(hdr->e_shstrndx)].sh_offset);
-	for (i = 1; i < TO_NATIVE(hdr->e_shnum); i++)
-		if (streq(secnames + TO_NATIVE(sechdrs[i].sh_name), name)) {
-			*size = TO_NATIVE(sechdrs[i].sh_size);
-			return file + TO_NATIVE(sechdrs[i].sh_offset);
-		}
-	return NULL;
-}
-
-static void *get_section64(void *file, unsigned long *size, const char *name)
-{
-	Elf64_Ehdr *hdr = file;
-	Elf64_Shdr *sechdrs = file + TO_NATIVE(hdr->e_shoff);
-	const char *secnames;
-	unsigned int i;
-
-	secnames = file
-		+ TO_NATIVE(sechdrs[TO_NATIVE(hdr->e_shstrndx)].sh_offset);
-	for (i = 1; i < TO_NATIVE(hdr->e_shnum); i++)
-		if (streq(secnames + TO_NATIVE(sechdrs[i].sh_name), name)) {
-			*size = TO_NATIVE(sechdrs[i].sh_size);
-			return file + TO_NATIVE(sechdrs[i].sh_offset);
-		}
-	return NULL;
-}
-
-static void *get_section(void *file, unsigned long filesize,
-			 unsigned long *size, const char *name)
-{
-	switch (elf_ident(file, filesize, &elf_conv)) {
-	case ELFCLASS32:
-		return get_section32(file, size, name);
-	case ELFCLASS64:
-		return get_section64(file, size, name);
-	default:
-		return NULL;
-	}
-}
-
 struct param
 {
 	struct param *next;
@@ -367,7 +316,7 @@ int main(int argc, char *argv[])
 			continue;
 		}
 
-		info = get_section(mod, modulesize, &infosize, ".modinfo");
+		info = get_section(mod, modulesize, ".modinfo", &infosize);
 		if (!info) {
 			release_file(mod, modulesize);
 			free(filename);
diff --git a/modprobe.c b/modprobe.c
index 9d7153e..c2d0ef6 100644
--- a/modprobe.c
+++ b/modprobe.c
@@ -303,75 +303,6 @@ static void replace_modname(struct module *module,
 	warn("Could not find old name in %s to replace!\n", module->filename);
 }
 
-static void *get_section32(void *file,
-			   unsigned long size,
-			   const char *name,
-			   unsigned long *secsize)
-{
-	Elf32_Ehdr *hdr = file;
-	Elf32_Shdr *sechdrs = file + hdr->e_shoff;
-	const char *secnames;
-	unsigned int i;
-
-	/* Too short? */
-	if (size < sizeof(*hdr))
-		return NULL;
-	if (size < hdr->e_shoff + hdr->e_shnum * sizeof(sechdrs[0]))
-		return NULL;
-	if (size < sechdrs[hdr->e_shstrndx].sh_offset)
-		return NULL;
-		
-	secnames = file + sechdrs[hdr->e_shstrndx].sh_offset;
-	for (i = 1; i < hdr->e_shnum; i++)
-		if (streq(secnames + sechdrs[i].sh_name, name)) {
-			*secsize = sechdrs[i].sh_size;
-			return file + sechdrs[i].sh_offset;
-		}
-	return NULL;
-}
-
-static void *get_section64(void *file,
-			   unsigned long size,
-			   const char *name,
-			   unsigned long *secsize)
-{
-	Elf64_Ehdr *hdr = file;
-	Elf64_Shdr *sechdrs = file + hdr->e_shoff;
-	const char *secnames;
-	unsigned int i;
-
-	/* Too short? */
-	if (size < sizeof(*hdr))
-		return NULL;
-	if (size < hdr->e_shoff + hdr->e_shnum * sizeof(sechdrs[0]))
-		return NULL;
-	if (size < sechdrs[hdr->e_shstrndx].sh_offset)
-		return NULL;
-		
-	secnames = file + sechdrs[hdr->e_shstrndx].sh_offset;
-	for (i = 1; i < hdr->e_shnum; i++)
-		if (streq(secnames + sechdrs[i].sh_name, name)) {
-			*secsize = sechdrs[i].sh_size;
-			return file + sechdrs[i].sh_offset;
-		}
-	return NULL;
-}
-
-static void *get_section(void *file,
-			 unsigned long size,
-			 const char *name,
-			 unsigned long *secsize)
-{
-	switch (elf_ident(file, size, NULL)) {
-	case ELFCLASS32:
-		return get_section32(file, size, name, secsize);
-	case ELFCLASS64:
-		return get_section64(file, size, name, secsize);
-	default:
-		return NULL;
-	}
-}
-
 static void rename_module(struct module *module,
 			  void *mod,
 			  unsigned long len,
@@ -921,14 +852,15 @@ void dump_modversions(const char *filename, errfn_t error)
        struct modver32_info *info32;
        struct modver64_info *info64;
        int n;
+       int conv;
 
        if (!file) {
                error("%s: %s\n", filename, strerror(errno));
                return;
        }
-       switch (elf_ident(file, size, NULL)) {
+       switch (elf_ident(file, size, &conv)) {
        case ELFCLASS32:
-               info32 = get_section32(file, size, "__versions", &secsize);
+               info32 = get_section32(file, size, "__versions", &secsize, conv);
                if (!info32)
                        return;  /* Does not seem to be a kernel module */
                if (secsize % sizeof(struct modver32_info))
@@ -939,7 +871,7 @@ void dump_modversions(const char *filename, errfn_t error)
                break;
 
        case ELFCLASS64:
-               info64 = get_section64(file, size, "__versions", &secsize);
+               info64 = get_section64(file, size, "__versions", &secsize, conv);
                if (!info64)
                        return;  /* Does not seem to be a kernel module */
                if (secsize % sizeof(struct modver64_info))
diff --git a/moduleops_core.c b/moduleops_core.c
index d11457e..0313e27 100644
--- a/moduleops_core.c
+++ b/moduleops_core.c
@@ -1,27 +1,10 @@
 /* Load the given section: NULL on error. */
 static void *PERBIT(load_section)(ElfPERBIT(Ehdr) *hdr,
 			    const char *secname,
-			    unsigned long *size,
+			    unsigned long *secsize,
 			    int conv)
 {
-	ElfPERBIT(Shdr) *sechdrs;
-	unsigned int i;
-	char *secnames;
-
-	/* Grab section headers and strings so we can tell who is who */
-	sechdrs = (void *)hdr + END(hdr->e_shoff, conv);
-	secnames = (void *)hdr
-		+ END(sechdrs[END(hdr->e_shstrndx, conv)].sh_offset, conv);
-
-	/* Find the section they want */
-	for (i = 1; i < END(hdr->e_shnum, conv); i++) {
-		if (streq(secnames+END(sechdrs[i].sh_name, conv), secname)) {
-			*size = END(sechdrs[i].sh_size, conv);
-			return (void *)hdr + END(sechdrs[i].sh_offset, conv);
-		}
-	}
-	*size = 0;
-	return NULL;
+	return PERBIT(get_section)(hdr, 0, secname, secsize, conv);
 }
 
 static void PERBIT(load_symbols)(struct module *module)
diff --git a/util.c b/util.c
index c4515a4..0ee6064 100644
--- a/util.c
+++ b/util.c
@@ -162,3 +162,31 @@ int elf_ident(void *file, unsigned long fsize, int *conv)
 		*conv = native_endianness() != ident[EI_DATA];
 	return ident[EI_CLASS];
 }
+
+#define PERBIT(x) x##32
+#define ElfPERBIT(x) Elf32_##x
+#define ELFPERBIT(x) ELF32_##x
+#include "elf_core.c"
+
+#undef PERBIT
+#undef ElfPERBIT
+#undef ELFPERBIT
+#define PERBIT(x) x##64
+#define ElfPERBIT(x) Elf64_##x
+#define ELFPERBIT(x) ELF64_##x
+#include "elf_core.c"
+
+void *get_section(void *file, unsigned long filesize,
+		  const char *secname, unsigned long *secsize)
+{
+	int conv;
+
+	switch (elf_ident(file, filesize, &conv)) {
+	case ELFCLASS32:
+		return get_section32(file, filesize, secname, secsize, conv);
+	case ELFCLASS64:
+		return get_section64(file, filesize, secname, secsize, conv);
+	default:
+		return NULL;
+	}
+}
diff --git a/util.h b/util.h
index b545b3a..c73ad21 100644
--- a/util.h
+++ b/util.h
@@ -31,6 +31,12 @@ static inline void __swap_bytes(const void *src, void *dest, unsigned int size)
 int native_endianness(void);
 
 int elf_ident(void *file, unsigned long fsize, int *conv);
+void *get_section(void *file, unsigned long filesize,
+	const char *secname, unsigned long *secsize);
+void *get_section32(void *file, unsigned long filesize,
+	const char *secname, unsigned long *secsize, int conv);
+void *get_section64(void *file, unsigned long filesize,
+	const char *secname, unsigned long *secsize, int conv);
 
 #define streq(a,b) (strcmp((a),(b)) == 0)
 #define strstarts(a,start) (strncmp((a),(start), strlen(start)) == 0)
-- 
1.5.6.3

--
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