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