[Pkg-clamav-commits] [SCM] Debian repository for ClamAV branch, master, updated. 4027557e7a080886ed92a78d2e948f4484471a1c
tkojm
tkojm at 77e5149b-7576-45b1-b177-96237e5ba77b
Sat Jun 13 00:45:17 UTC 2009
The following commit has been merged in the master branch:
commit 4027557e7a080886ed92a78d2e948f4484471a1c
Author: tkojm <tkojm at 77e5149b-7576-45b1-b177-96237e5ba77b>
Date: Fri Jun 12 10:31:24 2009 +0000
libclamav/elf.[ch]: add support for 64-bit ELF files (bb#1593)
git-svn-id: http://svn.clamav.net/svn/clamav-devel/trunk@5076 77e5149b-7576-45b1-b177-96237e5ba77b
diff --git a/ChangeLog b/ChangeLog
index 8275ac2..0d35f46 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Fri Jun 12 12:30:15 CEST 2009 (tk)
+----------------------------------
+ * libclamav/elf.[ch]: add support for 64-bit ELF files (bb#1593)
+
Wed Jun 10 19:01:11 CEST 2009 (tk)
----------------------------------
* V 0.95.2
diff --git a/libclamav/elf.c b/libclamav/elf.c
index 2d8144a..36f6f72 100644
--- a/libclamav/elf.c
+++ b/libclamav/elf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2008 Sourcefire, Inc.
+ * Copyright (C) 2007-2009 Sourcefire, Inc.
*
* Authors: Tomasz Kojm
*
@@ -84,6 +84,7 @@ int cli_scanelf(int desc, cli_ctx *ctx)
uint16_t shnum, phnum, shentsize, phentsize;
uint32_t entry, fentry, shoff, phoff, i;
uint8_t conv = 0, err;
+ unsigned int format;
cli_dbgmsg("in cli_scanelf\n");
@@ -99,9 +100,35 @@ int cli_scanelf(int desc, cli_ctx *ctx)
return CL_CLEAN;
}
- if(file_hdr.e_ident[4] != 1) {
- cli_dbgmsg("ELF: 64-bit binaries are not supported (yet)\n");
- return CL_CLEAN;
+ format = file_hdr.e_ident[4];
+ if(format != 1 && format != 2) {
+ cli_dbgmsg("ELF: Unknown ELF class (%u)\n", file_hdr.e_ident[4]);
+ return CL_EFORMAT;
+ }
+
+ if(format == 2) {
+ struct elf_file_hdr64 file_hdr64;
+ lseek(desc, 0, SEEK_SET);
+ if(read(desc, &file_hdr64, sizeof(file_hdr64)) != sizeof(file_hdr64)) {
+ /* Not an ELF file? */
+ cli_dbgmsg("ELF: Can't read file header\n");
+ return CL_CLEAN;
+ }
+ /* it's enough for us to handle ELF64 as 32 */
+ file_hdr.e_entry = file_hdr64.e_entry;
+ file_hdr.e_phoff = file_hdr64.e_phoff;
+ file_hdr.e_shoff = file_hdr64.e_shoff;
+ file_hdr.e_flags = file_hdr64.e_flags;
+ file_hdr.e_ehsize = file_hdr64.e_ehsize;
+ file_hdr.e_phentsize = file_hdr64.e_phentsize;
+ if(file_hdr.e_phentsize == sizeof(struct elf_program_hdr64))
+ file_hdr.e_phentsize = sizeof(struct elf_program_hdr32);
+ file_hdr.e_phnum = file_hdr64.e_phnum;
+ file_hdr.e_shentsize = file_hdr64.e_shentsize;
+ if(file_hdr.e_shentsize == sizeof(struct elf_section_hdr64))
+ file_hdr.e_shentsize = sizeof(struct elf_section_hdr32);
+ file_hdr.e_shnum = file_hdr64.e_shnum;
+ file_hdr.e_shstrndx = file_hdr64.e_shstrndx;
}
if(file_hdr.e_ident[5] == 1) {
@@ -142,47 +169,53 @@ int cli_scanelf(int desc, cli_ctx *ctx)
switch(EC16(file_hdr.e_machine, conv)) {
/* Due to a huge list, we only include the most popular machines here */
- case 0x0: /* EM_NONE */
+ case 0: /* EM_NONE */
cli_dbgmsg("ELF: Machine type: None\n");
break;
- case 0x2: /* EM_SPARC */
+ case 2: /* EM_SPARC */
cli_dbgmsg("ELF: Machine type: SPARC\n");
break;
- case 0x3: /* EM_386 */
+ case 3: /* EM_386 */
cli_dbgmsg("ELF: Machine type: Intel 80386\n");
break;
- case 0x4: /* EM_68K */
+ case 4: /* EM_68K */
cli_dbgmsg("ELF: Machine type: Motorola 68000\n");
break;
- case 0x8: /* EM_MIPS */
+ case 8: /* EM_MIPS */
cli_dbgmsg("ELF: Machine type: MIPS RS3000\n");
break;
- case 0x15: /* EM_PARISC */
+ case 9: /* EM_S370 */
+ cli_dbgmsg("ELF: Machine type: IBM System/370\n");
+ break;
+ case 15: /* EM_PARISC */
cli_dbgmsg("ELF: Machine type: HPPA\n");
break;
- case 0x20: /* EM_PPC */
+ case 20: /* EM_PPC */
cli_dbgmsg("ELF: Machine type: PowerPC\n");
break;
- case 0x21: /* EM_PPC64 */
+ case 21: /* EM_PPC64 */
cli_dbgmsg("ELF: Machine type: PowerPC 64-bit\n");
break;
- case 0x22: /* EM_S390 */
+ case 22: /* EM_S390 */
cli_dbgmsg("ELF: Machine type: IBM S390\n");
break;
- case 0x40: /* EM_ARM */
+ case 40: /* EM_ARM */
cli_dbgmsg("ELF: Machine type: ARM\n");
break;
- case 0x41: /* EM_FAKE_ALPHA */
+ case 41: /* EM_FAKE_ALPHA */
cli_dbgmsg("ELF: Machine type: Digital Alpha\n");
break;
- case 0x43: /* EM_SPARCV9 */
+ case 43: /* EM_SPARCV9 */
cli_dbgmsg("ELF: Machine type: SPARC v9 64-bit\n");
break;
- case 0x50: /* EM_IA_64 */
+ case 50: /* EM_IA_64 */
cli_dbgmsg("ELF: Machine type: IA64\n");
break;
+ case 62: /* EM_X86_64 */
+ cli_dbgmsg("ELF: Machine type: AMD x86-64\n");
+ break;
default:
- cli_dbgmsg("ELF: Machine type: Unknown (%d)\n", EC16(file_hdr.e_machine, conv));
+ cli_dbgmsg("ELF: Machine type: Unknown (0x%x)\n", EC16(file_hdr.e_machine, conv));
}
entry = EC32(file_hdr.e_entry, conv);
@@ -234,8 +267,28 @@ int cli_scanelf(int desc, cli_ctx *ctx)
cli_dbgmsg("------------------------------------\n");
for(i = 0; i < phnum; i++) {
+ err = 0;
+ if(format == 1) {
+ if(read(desc, &program_hdr[i], sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32))
+ err = 1;
+ } else {
+ struct elf_program_hdr64 program_hdr64;
+
+ if(read(desc, &program_hdr64, sizeof(program_hdr64)) != sizeof(program_hdr64)) {
+ err = 1;
+ } else {
+ program_hdr[i].p_type = program_hdr64.p_type;
+ program_hdr[i].p_offset = program_hdr64.p_offset;
+ program_hdr[i].p_vaddr = program_hdr64.p_vaddr;
+ program_hdr[i].p_paddr = program_hdr64.p_paddr;
+ program_hdr[i].p_filesz = program_hdr64.p_filesz;
+ program_hdr[i].p_memsz = program_hdr64.p_memsz;
+ program_hdr[i].p_flags = program_hdr64.p_flags;
+ program_hdr[i].p_align = program_hdr64.p_align;
+ }
+ }
- if(read(desc, &program_hdr[i], sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32)) {
+ if(err) {
cli_dbgmsg("ELF: Can't read segment #%d\n", i);
cli_dbgmsg("ELF: Possibly broken ELF file\n");
free(program_hdr);
@@ -317,8 +370,30 @@ int cli_scanelf(int desc, cli_ctx *ctx)
cli_dbgmsg("------------------------------------\n");
for(i = 0; i < shnum; i++) {
+ err = 0;
+ if(format == 1) {
+ if(read(desc, §ion_hdr[i], sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32))
+ err = 1;
+ } else {
+ struct elf_section_hdr64 section_hdr64;
+
+ if(read(desc, §ion_hdr64, sizeof(section_hdr64)) != sizeof(section_hdr64)) {
+ err = 1;
+ } else {
+ section_hdr[i].sh_name = section_hdr64.sh_name;
+ section_hdr[i].sh_type = section_hdr64.sh_type;
+ section_hdr[i].sh_flags = section_hdr64.sh_flags;
+ section_hdr[i].sh_addr = section_hdr64.sh_addr;
+ section_hdr[i].sh_offset = section_hdr64.sh_offset;
+ section_hdr[i].sh_size = section_hdr64.sh_size;
+ section_hdr[i].sh_link = section_hdr64.sh_link;
+ section_hdr[i].sh_info = section_hdr64.sh_info;
+ section_hdr[i].sh_addralign = section_hdr64.sh_addralign;
+ section_hdr[i].sh_entsize = section_hdr64.sh_entsize;
+ }
+ }
- if(read(desc, §ion_hdr[i], sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32)) {
+ if(err) {
cli_dbgmsg("ELF: Can't read section header\n");
cli_dbgmsg("ELF: Possibly broken ELF file\n");
free(section_hdr);
@@ -414,7 +489,7 @@ int cli_elfheader(int desc, struct cli_exe_info *elfinfo)
uint16_t shnum, phnum, shentsize, phentsize, i;
uint32_t entry, fentry = 0, shoff, phoff;
uint8_t conv = 0, err;
-
+ unsigned int format;
cli_dbgmsg("in cli_elfheader\n");
@@ -429,11 +504,37 @@ int cli_elfheader(int desc, struct cli_exe_info *elfinfo)
return -1;
}
- if(file_hdr.e_ident[4] != 1) {
- cli_dbgmsg("ELF: 64-bit binaries are not supported (yet)\n");
+ format = file_hdr.e_ident[4];
+ if(format != 1 && format != 2) {
+ cli_dbgmsg("ELF: Unknown ELF class (%u)\n", file_hdr.e_ident[4]);
return -1;
}
+ if(format == 2) {
+ struct elf_file_hdr64 file_hdr64;
+ lseek(desc, 0, SEEK_SET);
+ if(read(desc, &file_hdr64, sizeof(file_hdr64)) != sizeof(file_hdr64)) {
+ /* Not an ELF file? */
+ cli_dbgmsg("ELF: Can't read file header\n");
+ return -1;
+ }
+ /* it's enough for us to handle ELF64 as 32 */
+ file_hdr.e_entry = file_hdr64.e_entry;
+ file_hdr.e_phoff = file_hdr64.e_phoff;
+ file_hdr.e_shoff = file_hdr64.e_shoff;
+ file_hdr.e_flags = file_hdr64.e_flags;
+ file_hdr.e_ehsize = file_hdr64.e_ehsize;
+ file_hdr.e_phentsize = file_hdr64.e_phentsize;
+ if(file_hdr.e_phentsize == sizeof(struct elf_program_hdr64))
+ file_hdr.e_phentsize = sizeof(struct elf_program_hdr32);
+ file_hdr.e_phnum = file_hdr64.e_phnum;
+ file_hdr.e_shentsize = file_hdr64.e_shentsize;
+ if(file_hdr.e_shentsize == sizeof(struct elf_section_hdr64))
+ file_hdr.e_shentsize = sizeof(struct elf_section_hdr32);
+ file_hdr.e_shnum = file_hdr64.e_shnum;
+ file_hdr.e_shstrndx = file_hdr64.e_shstrndx;
+ }
+
if(file_hdr.e_ident[5] == 1) {
#if WORDS_BIGENDIAN == 1
conv = 1;
@@ -470,7 +571,28 @@ int cli_elfheader(int desc, struct cli_exe_info *elfinfo)
}
for(i = 0; i < phnum; i++) {
- if(read(desc, &program_hdr[i], sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32)) {
+ err = 0;
+ if(format == 1) {
+ if(read(desc, &program_hdr[i], sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32))
+ err = 1;
+ } else {
+ struct elf_program_hdr64 program_hdr64;
+
+ if(read(desc, &program_hdr64, sizeof(program_hdr64)) != sizeof(program_hdr64)) {
+ err = 1;
+ } else {
+ program_hdr[i].p_type = program_hdr64.p_type;
+ program_hdr[i].p_offset = program_hdr64.p_offset;
+ program_hdr[i].p_vaddr = program_hdr64.p_vaddr;
+ program_hdr[i].p_paddr = program_hdr64.p_paddr;
+ program_hdr[i].p_filesz = program_hdr64.p_filesz;
+ program_hdr[i].p_memsz = program_hdr64.p_memsz;
+ program_hdr[i].p_flags = program_hdr64.p_flags;
+ program_hdr[i].p_align = program_hdr64.p_align;
+ }
+ }
+
+ if(err) {
cli_dbgmsg("ELF: Can't read segment #%d\n", i);
free(program_hdr);
return -1;
@@ -521,14 +643,36 @@ int cli_elfheader(int desc, struct cli_exe_info *elfinfo)
}
for(i = 0; i < shnum; i++) {
+ err = 0;
+ if(format == 1) {
+ if(read(desc, §ion_hdr[i], sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32))
+ err = 1;
+ } else {
+ struct elf_section_hdr64 section_hdr64;
+
+ if(read(desc, §ion_hdr64, sizeof(section_hdr64)) != sizeof(section_hdr64)) {
+ err = 1;
+ } else {
+ section_hdr[i].sh_name = section_hdr64.sh_name;
+ section_hdr[i].sh_type = section_hdr64.sh_type;
+ section_hdr[i].sh_flags = section_hdr64.sh_flags;
+ section_hdr[i].sh_addr = section_hdr64.sh_addr;
+ section_hdr[i].sh_offset = section_hdr64.sh_offset;
+ section_hdr[i].sh_size = section_hdr64.sh_size;
+ section_hdr[i].sh_link = section_hdr64.sh_link;
+ section_hdr[i].sh_info = section_hdr64.sh_info;
+ section_hdr[i].sh_addralign = section_hdr64.sh_addralign;
+ section_hdr[i].sh_entsize = section_hdr64.sh_entsize;
+ }
+ }
- if(read(desc, §ion_hdr[i], sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32)) {
+ if(err) {
+ cli_dbgmsg("ELF: Can't read section header\n");
free(section_hdr);
free(elfinfo->section);
elfinfo->section = NULL;
return -1;
}
-
elfinfo->section[i].rva = EC32(section_hdr[i].sh_addr, conv);
elfinfo->section[i].raw = EC32(section_hdr[i].sh_offset, conv);
elfinfo->section[i].rsz = EC32(section_hdr[i].sh_size, conv);
diff --git a/libclamav/elf.h b/libclamav/elf.h
index badca48..c34ed2d 100644
--- a/libclamav/elf.h
+++ b/libclamav/elf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2008 Sourcefire, Inc.
+ * Copyright (C) 2007-2009 Sourcefire, Inc.
*
* Authors: Tomasz Kojm
*
@@ -43,6 +43,23 @@ struct elf_file_hdr32 {
uint16_t e_shstrndx;
};
+struct elf_file_hdr64 {
+ unsigned char e_ident[16];
+ uint16_t e_type;
+ uint16_t e_machine;
+ uint32_t e_version;
+ uint64_t e_entry;
+ uint64_t e_phoff;
+ uint64_t e_shoff;
+ uint32_t e_flags;
+ uint16_t e_ehsize;
+ uint16_t e_phentsize;
+ uint16_t e_phnum;
+ uint16_t e_shentsize;
+ uint16_t e_shnum;
+ uint16_t e_shstrndx;
+};
+
struct elf_program_hdr32 {
uint32_t p_type;
uint32_t p_offset;
@@ -54,6 +71,17 @@ struct elf_program_hdr32 {
uint32_t p_align;
};
+struct elf_program_hdr64 {
+ uint32_t p_type;
+ uint32_t p_flags;
+ uint64_t p_offset;
+ uint64_t p_vaddr;
+ uint64_t p_paddr;
+ uint64_t p_filesz;
+ uint64_t p_memsz;
+ uint64_t p_align;
+};
+
struct elf_section_hdr32 {
uint32_t sh_name;
uint32_t sh_type;
@@ -67,6 +95,19 @@ struct elf_section_hdr32 {
uint32_t sh_entsize;
};
+struct elf_section_hdr64 {
+ uint32_t sh_name;
+ uint32_t sh_type;
+ uint64_t sh_flags;
+ uint64_t sh_addr;
+ uint64_t sh_offset;
+ uint64_t sh_size;
+ uint32_t sh_link;
+ uint32_t sh_info;
+ uint64_t sh_addralign;
+ uint64_t sh_entsize;
+};
+
int cli_scanelf(int desc, cli_ctx *ctx);
int cli_elfheader(int desc, struct cli_exe_info *elfinfo);
--
Debian repository for ClamAV
More information about the Pkg-clamav-commits
mailing list