[Pkg-clamav-commits] [SCM] Debian repository for ClamAV branch, debian/unstable, updated. debian/0.95+dfsg-1-6156-g094ec9b

Tomasz Kojm tkojm at clamav.net
Sun Apr 4 00:58:39 UTC 2010


The following commit has been merged in the debian/unstable branch:
commit 3222a09656b40dd02486f7e97e09d40426e1b23f
Author: Tomasz Kojm <tkojm at clamav.net>
Date:   Tue Jul 14 18:19:54 2009 +0200

    libclamav: add support for Universal Binaries
    (archives with Mach-O files for different architectures, bb#1592)

diff --git a/ChangeLog b/ChangeLog
index 3fb4bff..b3744bb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Tue Jul 14 18:17:59 CEST 2009 (tk)
+----------------------------------
+ * libclamav: add support for Universal Binaries (archives with Mach-O files for
+	      different architectures, bb#1592)
+
 Mon Jul 13 21:40:51 CEST 2009 (tk)
 ----------------------------------
  * docs/signatures.pdf: cover Mach-O files
diff --git a/libclamav/cpio.c b/libclamav/cpio.c
index 524601a..cbc05e2 100644
--- a/libclamav/cpio.c
+++ b/libclamav/cpio.c
@@ -80,70 +80,7 @@ struct cpio_hdr_newc {
     char check[8];
 };
 
-#ifndef O_BINARY
-#define O_BINARY    0
-#endif
-
-static int cpio_scanfile(int fd, uint32_t size, cli_ctx *ctx)
-{
-	int newfd, bread, sum = 0, ret;
-	char buff[FILEBUFF];
-	char *name;
-
-
-    if(!(name = cli_gentemp(ctx->engine->tmpdir)))
-	return CL_EMEM;
-
-    if((newfd = open(name, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
-	cli_errmsg("cpio_scanfile: Can't create file %s\n", name);
-	free(name);
-	return CL_ECREAT;
-    }
-
-    while((bread = cli_readn(fd, buff, FILEBUFF)) > 0) {
-	if((uint32_t) (sum + bread) >= size) {
-	    if(write(newfd, buff, size - sum) == -1) {
-		cli_errmsg("cpio_scanfile: Can't write to %s\n", name);
-		cli_unlink(name);
-		free(name);
-		close(newfd);
-		return CL_EWRITE;
-	    }
-	    break;
-	} else {
-	    if(write(newfd, buff, bread) == -1) {
-		cli_errmsg("cpio_scanfile: Can't write to %s\n", name);
-		cli_unlink(name);
-		free(name);
-		close(newfd);
-		return CL_EWRITE;
-	    }
-	}
-	sum += bread;
-    }
-    cli_dbgmsg("CPIO: Extracted to %s\n", name);
-    lseek(newfd, 0, SEEK_SET);
-    if((ret = cli_magic_scandesc(newfd, ctx)) == CL_VIRUS)
-	cli_dbgmsg("cpio_scanfile: Infected with %s\n", *ctx->virname);
-
-    close(newfd);
-    if(!ctx->engine->keeptmp) {
-	if(cli_unlink(name)) {
-	    free(name);
-	    return CL_EUNLINK;
-	}
-    }
-    free(name);
-    return ret;
-}
-
-static inline uint16_t EC16(uint16_t v, int c)
-{
-    if(!c)
-	return v;
-    else
-	return ((v >> 8) + (v << 8));
-}
+#define EC16(v, conv)   (conv ? cbswap16(v) : v)
 
 static void sanitname(char *name)
 {
@@ -213,7 +150,7 @@ int cli_scancpio_old(int fd, cli_ctx *ctx)
 	    if(ret == CL_EMAXFILES) {
 		return ret;
 	    } else if(ret == CL_SUCCESS) {
-		ret = cpio_scanfile(fd, filesize, ctx);
+		ret = cli_dumpscan(fd, 0, filesize, ctx);
 		if(ret == CL_VIRUS)
 		    return ret;
 	    }
@@ -287,7 +224,7 @@ int cli_scancpio_odc(int fd, cli_ctx *ctx)
 	if(ret == CL_EMAXFILES) {
 	    return ret;
 	} else if(ret == CL_SUCCESS) {
-	    ret = cpio_scanfile(fd, filesize, ctx);
+	    ret = cli_dumpscan(fd, 0, filesize, ctx);
 	    if(ret == CL_VIRUS)
 		return ret;
 	}
@@ -363,7 +300,7 @@ int cli_scancpio_newc(int fd, cli_ctx *ctx, int crc)
 	if(ret == CL_EMAXFILES) {
 	    return ret;
 	} else if(ret == CL_SUCCESS) {
-	    ret = cpio_scanfile(fd, filesize, ctx);
+	    ret = cli_dumpscan(fd, 0, filesize, ctx);
 	    if(ret == CL_VIRUS)
 		return ret;
 	}
diff --git a/libclamav/filetypes.c b/libclamav/filetypes.c
index aebca76..0cbc096 100644
--- a/libclamav/filetypes.c
+++ b/libclamav/filetypes.c
@@ -57,6 +57,7 @@ static const struct ftmap_s {
     { "CL_TYPE_MSEXE",		CL_TYPE_MSEXE		},
     { "CL_TYPE_ELF",		CL_TYPE_ELF		},
     { "CL_TYPE_MACHO",		CL_TYPE_MACHO		},
+    { "CL_TYPE_MACHO_UNIBIN",	CL_TYPE_MACHO_UNIBIN	},
     { "CL_TYPE_POSIX_TAR",	CL_TYPE_POSIX_TAR	},
     { "CL_TYPE_OLD_TAR",	CL_TYPE_OLD_TAR		},
     { "CL_TYPE_CPIO_OLD",	CL_TYPE_CPIO_OLD	},
diff --git a/libclamav/filetypes.h b/libclamav/filetypes.h
index 5a47f88..da6433d 100644
--- a/libclamav/filetypes.h
+++ b/libclamav/filetypes.h
@@ -42,6 +42,7 @@ typedef enum {
     CL_TYPE_PE_DISASM,
     CL_TYPE_ELF,
     CL_TYPE_MACHO,
+    CL_TYPE_MACHO_UNIBIN,
     CL_TYPE_POSIX_TAR,
     CL_TYPE_OLD_TAR,
     CL_TYPE_CPIO_OLD,
diff --git a/libclamav/filetypes_int.h b/libclamav/filetypes_int.h
index f58b23b..1e1f1fa 100644
--- a/libclamav/filetypes_int.h
+++ b/libclamav/filetypes_int.h
@@ -148,6 +148,7 @@ static const char *ftypes_int[] = {
   "0:0:cffaedfe:Mach-O LE 64-bit:CL_TYPE_ANY:CL_TYPE_MACHO:45",
   "0:0:feedface:Mach-O BE:CL_TYPE_ANY:CL_TYPE_MACHO:45",
   "0:0:feedfacf:Mach-O BE 64-bit:CL_TYPE_ANY:CL_TYPE_MACHO:45",
+  "0:0:cafebabe:Universal Binary:CL_TYPE_ANY:CL_TYPE_MACHO_UNIBIN:46",
   NULL
 };
 
diff --git a/libclamav/macho.c b/libclamav/macho.c
index f07e15f..5b06aff 100644
--- a/libclamav/macho.c
+++ b/libclamav/macho.c
@@ -153,6 +153,21 @@ struct macho_thread_state_x86
     uint32_t gs;
 };
 
+struct macho_fat_header
+{
+    uint32_t magic;
+    uint32_t nfats;
+};
+
+struct macho_fat_arch
+{
+    uint32_t cputype;
+    uint32_t cpusubtype;
+    uint32_t offset;
+    uint32_t size;
+    uint32_t align;
+};
+
 #define RETURN_BROKEN					    \
     if(matcher)						    \
 	return -1;					    \
@@ -477,3 +492,57 @@ int cli_machoheader(int fd, struct cli_exe_info *fileinfo)
 {
     return cli_scanmacho(fd, NULL, fileinfo);
 }
+
+int cli_scanmacho_unibin(int fd, cli_ctx *ctx)
+{
+	struct macho_fat_header fat_header;
+	struct macho_fat_arch fat_arch;
+	unsigned int conv, i, matcher = 0;
+	int ret = CL_CLEAN;
+	struct stat sb;
+	off_t pos;
+
+    if(fstat(fd, &sb) == -1) {
+	cli_dbgmsg("cli_scanmacho_unibin: fstat failed for fd %d\n", fd);
+	return CL_ESTAT;
+    }
+
+    if(read(fd, &fat_header, sizeof(fat_header)) != sizeof(fat_header)) {
+	cli_dbgmsg("cli_scanmacho_unibin: Can't read fat_header\n");
+	return CL_EFORMAT;
+    }
+
+    if(fat_header.magic == 0xcafebabe) {
+	conv = 0;
+    } else if(fat_header.magic == 0xbebafeca) {
+	conv = 1;
+    } else {
+	cli_dbgmsg("cli_scanmacho_unibin: Incorrect magic\n");
+	return CL_EFORMAT;
+    }
+
+    fat_header.nfats = EC32(fat_header.nfats, conv);
+    if(fat_header.nfats > 32) {
+	cli_dbgmsg("cli_scanmacho_unibin: Invalid number of architectures\n");
+	RETURN_BROKEN;
+    }
+    cli_dbgmsg("UNIBIN: Number of architectures: %u\n", (unsigned int) fat_header.nfats);
+    for(i = 0; i < fat_header.nfats; i++) {
+	if(read(fd, &fat_arch, sizeof(fat_arch)) != sizeof(fat_arch)) {
+	    cli_dbgmsg("cli_scanmacho_unibin: Can't read fat_arch\n");
+	    RETURN_BROKEN;
+	}
+	pos = lseek(fd, 0, SEEK_CUR);
+	fat_arch.offset = EC32(fat_arch.offset, conv);
+	fat_arch.size = EC32(fat_arch.size, conv);
+	cli_dbgmsg("UNIBIN: Binary %u of %u\n", i + 1, fat_header.nfats);
+	cli_dbgmsg("UNIBIN: File offset: %u\n", fat_arch.offset);
+	cli_dbgmsg("UNIBIN: File size: %u\n", fat_arch.size);
+	ret = cli_dumpscan(fd, fat_arch.offset, fat_arch.size, ctx);
+	lseek(fd, pos, SEEK_SET);
+	if(ret == CL_VIRUS)
+	    break;
+    }
+
+    return ret; /* result from the last binary */
+}
diff --git a/libclamav/macho.h b/libclamav/macho.h
index bce0de8..d31a564 100644
--- a/libclamav/macho.h
+++ b/libclamav/macho.h
@@ -26,5 +26,6 @@
 
 int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo);
 int cli_machoheader(int fd, struct cli_exe_info *fileinfo);
+int cli_scanmacho_unibin(int fd, cli_ctx *ctx);
 
 #endif
diff --git a/libclamav/others.c b/libclamav/others.c
index ac2cc9d..83dbd94 100644
--- a/libclamav/others.c
+++ b/libclamav/others.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2007-2008 Sourcefire, Inc.
+ *  Copyright (C) 2007-2009 Sourcefire, Inc.
  *
  *  Authors: Tomasz Kojm, Trog
  *
@@ -837,6 +837,65 @@ int cli_rmdirs(const char *dirname)
 }
 #endif
 
+int cli_dumpscan(int fd, off_t offset, size_t size, cli_ctx *ctx)
+{
+	int newfd, bread, sum = 0, ret;
+	char buff[FILEBUFF];
+	char *name;
+
+    if(offset) {
+	if(lseek(fd, offset, SEEK_SET) == -1) {
+	    cli_dbgmsg("cli_dumpscan: Can't lseek to %u\n", (unsigned int) offset);
+	    return CL_EFORMAT; /* most likely because of corrupted file */
+	}
+    }
+
+    if(!(name = cli_gentemp(ctx->engine->tmpdir)))
+	return CL_EMEM;
+
+    if((newfd = open(name, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
+	cli_errmsg("cli_dumpscan: Can't create file %s\n", name);
+	free(name);
+	return CL_ECREAT;
+    }
+
+    while((bread = cli_readn(fd, buff, FILEBUFF)) > 0) {
+	if((uint32_t) (sum + bread) >= size) {
+	    if(write(newfd, buff, size - sum) == -1) {
+		cli_errmsg("cli_dumpscan: Can't write to %s\n", name);
+		cli_unlink(name);
+		free(name);
+		close(newfd);
+		return CL_EWRITE;
+	    }
+	    break;
+	} else {
+	    if(write(newfd, buff, bread) == -1) {
+		cli_errmsg("cli_dumpscan: Can't write to %s\n", name);
+		cli_unlink(name);
+		free(name);
+		close(newfd);
+		return CL_EWRITE;
+	    }
+	}
+	sum += bread;
+    }
+    cli_dbgmsg("DUMP&SCAN: File extracted to %s\n", name);
+    lseek(newfd, 0, SEEK_SET);
+    if((ret = cli_magic_scandesc(newfd, ctx)) == CL_VIRUS)
+	cli_dbgmsg("cli_dumpscan: Infected with %s\n", *ctx->virname);
+
+    close(newfd);
+    if(!ctx->engine->keeptmp) {
+	if(cli_unlink(name)) {
+	    free(name);
+	    return CL_EUNLINK;
+	}
+    }
+    free(name);
+    return ret;
+}
+
 /* Implement a generic bitset, trog at clamav.net */
 
 #define BITS_PER_CHAR (8)
diff --git a/libclamav/others.h b/libclamav/others.h
index b5a140c..21b7c29 100644
--- a/libclamav/others.h
+++ b/libclamav/others.h
@@ -45,7 +45,7 @@
  * in re-enabling affected modules.
  */
 
-#define CL_FLEVEL 45
+#define CL_FLEVEL 46
 #define CL_FLEVEL_DCONF	CL_FLEVEL
 
 extern uint8_t cli_debug_flag;
@@ -381,6 +381,7 @@ char *cli_gentemp(const char *dir);
 int cli_gentempfd(const char *dir, char **name, int *fd);
 unsigned int cli_rndnum(unsigned int max);
 int cli_filecopy(const char *src, const char *dest);
+int cli_dumpscan(int fd, off_t offset, size_t size, cli_ctx *ctx);
 bitset_t *cli_bitset_init(void);
 void cli_bitset_free(bitset_t *bs);
 int cli_bitset_set(bitset_t *bs, unsigned long bit_offset);
diff --git a/libclamav/scanners.c b/libclamav/scanners.c
index 4741ef7..22985cd 100644
--- a/libclamav/scanners.c
+++ b/libclamav/scanners.c
@@ -2090,6 +2090,11 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
 		ret = cli_scanmacho(desc, ctx, NULL);
 	    break;
 
+	case CL_TYPE_MACHO_UNIBIN:
+	    if(ctx->dconf->macho)
+		ret = cli_scanmacho_unibin(desc, ctx);
+	    break;
+
 	case CL_TYPE_SIS:
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_SIS))
 		ret = cli_scansis(desc, ctx);

-- 
Debian repository for ClamAV



More information about the Pkg-clamav-commits mailing list