* Dave Anderson <[EMAIL PROTECTED]> [2007-12-21 16:00]:
>
> Maybe it should cut down on the initial 32/64-bit verifier
> to check only the ELFMAG and the bytes in the E_IDENT string.
> Then inside of the 32 and 64 bit blocks, first check for
> the architecture and bail out with a "arch-mismatch" error.
> (although in doing so, the e_machine switch statement would
> have to have cases for each arch and its byte-toggled version)
>
> Then the current endian check could be made, and if it
> doesn't match bail out with an "endian" error.
>
> And then for sanity's sake, the remainder of header checks
> could be done, which if we get that far, are pretty much
> guaranteed to never happen.

Sounds sane. What about this:


---
 defs.h    |    3 +
 netdump.c |  119 ++++++++++++++++++++++++++++++++++++++++++++++----------------
 tools.c   |    9 ++++
 3 files changed, 100 insertions(+), 31 deletions(-)

--- a/defs.h
+++ b/defs.h
@@ -3198,7 +3198,8 @@ void stall(ulong);
 char *pages_to_size(ulong, char *);
 int clean_arg(void);
 int empty_list(ulong);
-int machine_type(char *);
+int machine_type(const char *);
+int is_big_endian(void);
 void command_not_supported(void);
 void option_not_supported(int);
 void please_wait(char *);
--- a/netdump.c
+++ b/netdump.c
@@ -36,6 +36,47 @@ static void check_dumpfile_size(char *);
 #define ELFREAD  0
 
 #define MIN_PAGE_SIZE (4096)
+#define TOGGLE_ENDIAN_16(val) \
+       (((val >> 8) & 0xff) | ((val << 8) & 0xff00))
+
+
+
+/*
+ * Checks if the machine type of the host matches required_type.
+ * If not, it prints a short error message for the user.
+ */
+static int machine_type_error(const char *required_type)
+{
+       if (machine_type(required_type))
+               return 1;
+       else {
+               fprintf(stderr, "Looks like a valid ELF dump, but host "
+                               "architecture (%s) doesn't match dump "
+                               "architecture (%s).\n",
+                               MACHINE_TYPE, required_type);
+               return 0;
+       }
+}
+
+/*
+ * Returns endianess in a string
+ */
+static const char *endianess_to_string(int big_endian)
+{
+       return big_endian ? "BE" : "LE";
+}
+
+/*
+ * Prints an endian error.
+ */
+static void endian_error(int target_big_endian)
+{
+       fprintf(stderr, "Looks like a valid ELF dump, but host "
+                       "endianess (%s) doesn't match target "
+                       "endianess (%s)\n",
+                       endianess_to_string(is_big_endian()),
+                       endianess_to_string(target_big_endian));
+}
        
 /*
  *  Determine whether a file is a netdump/diskdump/kdump creation, 
@@ -99,21 +140,34 @@ is_netdump(char *file, ulong source_quer
         *  is obviously subject to change.
         */
         if (STRNEQ(elf32->e_ident, ELFMAG) && 
-           (elf32->e_ident[EI_CLASS] == ELFCLASS32) &&
-           (elf32->e_ident[EI_DATA] == ELFDATA2LSB) &&
-           (elf32->e_ident[EI_VERSION] == EV_CURRENT) &&
-           (elf32->e_type == ET_CORE) &&
-           (elf32->e_version == EV_CURRENT) &&
-           (elf32->e_phnum >= 2)) {
+           (elf32->e_ident[EI_CLASS] == ELFCLASS32)) {
+
+               /* check arch */
                switch (elf32->e_machine)
                {
                case EM_386:
-                       if (machine_type("X86"))
-                               break;
+               case TOGGLE_ENDIAN_16(EM_386):
+                       if (!machine_type_error("X86"))
+                               goto bailout;
+                       break;
                default:
                        goto bailout;
                }
 
+               /* check endianess */
+               if ((elf32->e_ident[EI_DATA] == ELFDATA2LSB && is_big_endian()) 
||
+                   (elf32->e_ident[EI_DATA] == ELFDATA2MSB && 
!is_big_endian())) {
+                           endian_error(elf32->e_ident[EI_DATA] == 
ELFDATA2MSB);
+                           goto bailout;
+               }
+
+               /* check other ELF headers */
+               if ((elf32->e_ident[EI_VERSION] != EV_CURRENT) ||
+                   (elf32->e_type != ET_CORE) ||
+                   (elf32->e_version != EV_CURRENT) ||
+                   (elf32->e_phnum < 2))
+                       goto bailout;
+
                 load32 = (Elf32_Phdr *)
                         &header[sizeof(Elf32_Ehdr)+sizeof(Elf32_Phdr)];
                 size = (size_t)load32->p_offset;
@@ -124,45 +178,52 @@ is_netdump(char *file, ulong source_quer
                else
                        tmp_flags |= NETDUMP_ELF32;
        } else if (STRNEQ(elf64->e_ident, ELFMAG) &&
-           (elf64->e_ident[EI_CLASS] == ELFCLASS64) &&
-           (elf64->e_ident[EI_VERSION] == EV_CURRENT) &&
-           (elf64->e_type == ET_CORE) &&
-           (elf64->e_version == EV_CURRENT) &&
-           (elf64->e_phnum >= 2)) { 
+           (elf64->e_ident[EI_CLASS] == ELFCLASS64)) {
+
+               /* check arch */
                switch (elf64->e_machine)
                {
                case EM_IA_64:
-                       if ((elf64->e_ident[EI_DATA] == ELFDATA2LSB) &&
-                               machine_type("IA64"))
-                               break;
-                       else
+               case TOGGLE_ENDIAN_16(EM_IA_64):
+                       if (!machine_type_error("IA64"))
                                goto bailout;
+                       break;
 
                case EM_PPC64:
-                       if ((elf64->e_ident[EI_DATA] == ELFDATA2MSB) &&
-                               machine_type("PPC64"))
-                               break;
-                       else
+               case TOGGLE_ENDIAN_16(EM_PPC64):
+                       if (!machine_type_error("PPC64"))
                                goto bailout;
+                       break;
 
                case EM_X86_64:
-                       if ((elf64->e_ident[EI_DATA] == ELFDATA2LSB) &&
-                               machine_type("X86_64"))
-                               break;
-                       else
+               case TOGGLE_ENDIAN_16(EM_X86_64):
+                       if (!machine_type_error("X86_64"))
                                goto bailout;
+                       break;
 
                case EM_386:
-                       if ((elf64->e_ident[EI_DATA] == ELFDATA2LSB) &&
-                               machine_type("X86"))
-                               break;
-                       else
+               case TOGGLE_ENDIAN_16(EM_386):
+                       if (!machine_type_error("X86"))
                                goto bailout;
+                       break;
 
                default:
                        goto bailout;
                }
 
+               /* check endianess */
+               if ((elf64->e_ident[EI_DATA] == ELFDATA2LSB && is_big_endian()) 
||
+                   (elf64->e_ident[EI_DATA] == ELFDATA2MSB && 
!is_big_endian())) {
+                           endian_error(elf64->e_ident[EI_DATA] == 
ELFDATA2MSB);
+                           goto bailout;
+               }
+
+               if ((elf64->e_ident[EI_VERSION] != EV_CURRENT) ||
+                   (elf64->e_type != ET_CORE) ||
+                   (elf64->e_version != EV_CURRENT) ||
+                   (elf64->e_phnum < 2))
+                       goto bailout;
+
                 load64 = (Elf64_Phdr *)
                         &header[sizeof(Elf64_Ehdr)+sizeof(Elf64_Phdr)];
                 size = (size_t)load64->p_offset;
--- a/tools.c
+++ b/tools.c
@@ -4518,11 +4518,18 @@ empty_list(ulong list_head_addr)
 }
 
 int
-machine_type(char *type)
+machine_type(const char *type)
 {
        return STREQ(MACHINE_TYPE, type);
 }
 
+int
+is_big_endian(void)
+{
+       unsigned short value = 0xff;
+       return *((unsigned char *)&value) != 0xff;
+}
+
 void
 command_not_supported()
 {

--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to