[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