[PATCH 3/4] Clean up ELF header tester elf_ident()

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

 



Combines three slightly different implementations found in
depmod.c, modprobe.c and modinfo.c.

This new version will return error codes and optionally also
return the file endianness.

Signed-off-by: Andreas Robinson <andr345@xxxxxxxxx>
---
 depmod.c   |   22 ++++++++++------------
 modinfo.c  |   17 +++--------------
 modprobe.c |   16 +++-------------
 util.c     |   20 ++++++++++++++++++++
 util.h     |    2 ++
 5 files changed, 38 insertions(+), 39 deletions(-)

diff --git a/depmod.c b/depmod.c
index 9b6fda7..3544b89 100644
--- a/depmod.c
+++ b/depmod.c
@@ -283,25 +283,23 @@ static struct module *grab_module(const char *dirname, const char *filename)
 		goto fail_data;
 	}
 
-	/* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */
-	if (memcmp(new->data, ELFMAG, SELFMAG) != 0) {
-		warn("Module %s is not an elf object\n", new->pathname);
-		goto fail;
-	}
-
-	switch (((char *)new->data)[EI_CLASS]) {
+	switch (elf_ident(new->data, new->len, &new->conv)) {
 	case ELFCLASS32:
 		new->ops = &mod_ops32;
 		break;
 	case ELFCLASS64:
 		new->ops = &mod_ops64;
 		break;
-	default:
-		warn("Module %s has elf unknown identifier %i\n",
-		     new->pathname, ((char *)new->data)[EI_CLASS]);
+	case -ENOEXEC:
+		warn("Module %s is not an elf object\n", new->pathname);
 		goto fail;
-	}
-	new->conv = ((char *)new->data)[EI_DATA] != native_endianness();
+	case -EINVAL:
+		warn("Module %s has unknown endianness\n", new->pathname);
+		goto fail;
+ 	default:
+		warn("Module %s has unknown word size\n", new->pathname);
+ 		goto fail;
+ 	}
 	return new;
 
 fail:
diff --git a/modinfo.c b/modinfo.c
index 80e00d4..81e40f4 100644
--- a/modinfo.c
+++ b/modinfo.c
@@ -21,9 +21,9 @@
 #define MODULE_DIR "/lib/modules"
 #endif
 
-static int elf_endian;
+static int elf_conv;
 
-#define TO_NATIVE(x) END(x, elf_endian != native_endianness())
+#define TO_NATIVE(x) END(x, elf_conv)
 
 static void *get_section32(void *file, unsigned long *size, const char *name)
 {
@@ -59,21 +59,10 @@ static void *get_section64(void *file, unsigned long *size, const char *name)
 	return NULL;
 }
 
-static int elf_ident(void *mod, unsigned long size)
-{
-	/* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */
-	char *ident = mod;
-
-	if (size < EI_CLASS || memcmp(mod, ELFMAG, SELFMAG) != 0)
-		return ELFCLASSNONE;
-	elf_endian = ident[EI_DATA];
-	return ident[EI_CLASS];
-}
-
 static void *get_section(void *file, unsigned long filesize,
 			 unsigned long *size, const char *name)
 {
-	switch (elf_ident(file, filesize)) {
+	switch (elf_ident(file, filesize, &elf_conv)) {
 	case ELFCLASS32:
 		return get_section32(file, size, name);
 	case ELFCLASS64:
diff --git a/modprobe.c b/modprobe.c
index 8660f51..9d7153e 100644
--- a/modprobe.c
+++ b/modprobe.c
@@ -357,22 +357,12 @@ static void *get_section64(void *file,
 	return NULL;
 }
 
-static int elf_ident(void *mod, unsigned long size)
-{
-	/* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */
-	char *ident = mod;
-
-	if (size < EI_CLASS || memcmp(mod, ELFMAG, SELFMAG) != 0)
-		return ELFCLASSNONE;
-	return ident[EI_CLASS];
-}
-
 static void *get_section(void *file,
 			 unsigned long size,
 			 const char *name,
 			 unsigned long *secsize)
 {
-	switch (elf_ident(file, size)) {
+	switch (elf_ident(file, size, NULL)) {
 	case ELFCLASS32:
 		return get_section32(file, size, name, secsize);
 	case ELFCLASS64:
@@ -434,7 +424,7 @@ static void strip_section(struct module *module,
 			  unsigned long len,
 			  const char *secname)
 {
-	switch (elf_ident(mod, len)) {
+	switch (elf_ident(mod, len, NULL)) {
 	case ELFCLASS32:
 		invalidate_section32(mod, secname);
 		break;
@@ -936,7 +926,7 @@ void dump_modversions(const char *filename, errfn_t error)
                error("%s: %s\n", filename, strerror(errno));
                return;
        }
-       switch (elf_ident(file, size)) {
+       switch (elf_ident(file, size, NULL)) {
        case ELFCLASS32:
                info32 = get_section32(file, size, "__versions", &secsize);
                if (!info32)
diff --git a/util.c b/util.c
index 3a390f7..c4515a4 100644
--- a/util.c
+++ b/util.c
@@ -2,6 +2,8 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <string.h>
+#include <errno.h>
+#include <elf.h>
 #include "logging.h"
 #include "util.h"
 
@@ -142,3 +144,21 @@ int __attribute__ ((pure)) native_endianness()
 	 */
 	return (char) *((uint32_t*)("\1\0\0\2"));
 }
+
+/*
+ * Check ELF file header.
+ */
+int elf_ident(void *file, unsigned long fsize, int *conv)
+{
+	/* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */
+	unsigned char *ident = file;
+
+	if (fsize < EI_CLASS || memcmp(file, ELFMAG, SELFMAG) != 0)
+		return -ENOEXEC;	/* Not an ELF object */
+	if (ident[EI_DATA] == 0 || ident[EI_DATA] > 2)
+		return -EINVAL;		/* Unknown endianness */
+
+	if (conv != NULL)
+		*conv = native_endianness() != ident[EI_DATA];
+	return ident[EI_CLASS];
+}
diff --git a/util.h b/util.h
index 60e85e1..b545b3a 100644
--- a/util.h
+++ b/util.h
@@ -30,6 +30,8 @@ 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);
+
 #define streq(a,b) (strcmp((a),(b)) == 0)
 #define strstarts(a,start) (strncmp((a),(start), strlen(start)) == 0)
 #define my_basename(path) ((strrchr((path), '/') ?: (path) - 1) + 1)
-- 
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