1st attempt

0.96
aCaB 16 years ago
parent c124d71a69
commit 303f7b3477
  1. 39
      libclamav/fmap.c
  2. 6
      libclamav/fmap.h
  3. 59
      libclamav/ishield.c

@ -148,7 +148,7 @@ static int fmap_readpage(struct F_MAP *m, unsigned int page) {
return 0;
}
void *fmap_need(struct F_MAP *m, size_t at, size_t len) {
void *fmap_need_off(struct F_MAP *m, size_t at, size_t len) {
unsigned int i, first_page, last_page;
char *ret;
@ -174,6 +174,43 @@ void *fmap_need(struct F_MAP *m, size_t at, size_t len) {
return (void *)ret;
}
void *fmap_need_ptr(struct F_MAP *m, void *ptr, size_t len) {
return fmap_need_off(m, (char *)ptr - (char *)m - m->hdrsz, len);
}
void *fmap_need_str(struct F_MAP *m, void *ptr, size_t len) {
const size_t at = (char *)ptr - (char *)m - m->hdrsz;
unsigned int i, first_page, last_page;
if(!len)
len = m->len - at;
if(!CLI_ISCONTAINED(0, m->len, at, len)) {
cli_warnmsg("fmap: attempted oof need_str\n");
return NULL;
}
first_page = fmap_which_page(m, at);
last_page = fmap_which_page(m, at + len);
for(i=first_page; i<=last_page; i++) {
char *thispage = (char *)m + m->hdrsz;
unsigned int scanat, scansz;
if(fmap_readpage(m, i))
return NULL;
if(i == first_page) {
scanat = at % m->pgsz;
scansz = m->pgsz - scanat;
} else {
scanat = 0;
scansz = m->pgsz - scanat;
}
if(memchr(&thispage[scanat], 0, scansz))
return ptr;
}
return NULL;
}
void fmunmap(struct F_MAP *m) {
void *p = (void *)m;

@ -24,6 +24,8 @@
struct F_MAP;
struct F_MAP *fmap(int fd, off_t offset, size_t len);
void *fmunmap(struct F_MAP *m, size_t len);
void *fmunmap(struct F_MAP *m);
void *fmap_need_ptr(struct F_MAP *m, void *ptr, size_t len);
void *fmap_need_off(struct F_MAP *m, size_t at, size_t len);
void *fmap_need_str(struct F_MAP *m, void *ptr, size_t len);
#endif

@ -32,11 +32,6 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_MMAP
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#endif /* HAVE_MMAP */
#if HAVE_STRING_H
#include <string.h>
#endif
@ -49,6 +44,7 @@
#include "scanners.h"
#include "cltypes.h"
#include "others.h"
#include "fmap.h"
#include "ishield.h"
#ifndef O_BINARY
@ -483,13 +479,6 @@ struct IS_HDR {
};
#define IS_FREE_HDR if(map) munmap(map, mp_hdrsz); else free(hdr);
#if HAVE_MMAP
#define IS_MAX_NOMAP_SZ 0x100000
#else
#define IS_MAX_NOMAP_SZ CLI_MAX_ALLOCATION
#endif
/* Process data1.hdr and extracts all the available files from dataX.cab */
static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c) {
uint32_t h1_data_off, objs_files_cnt, objs_dirs_off;
@ -507,41 +496,29 @@ static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c) {
return CL_CLEAN;
}
if(c->hdrsz < IS_MAX_NOMAP_SZ) {
if(!(hdr = (char *)cli_malloc(c->hdrsz)))
return CL_EMEM;
if(pread(desc, hdr, c->hdrsz, c->hdr) < (ssize_t)c->hdrsz) {
cli_errmsg("is_parse_hdr: short read for header\n");
free(hdr);
return CL_EREAD; /* hdr must be within bounds, it's k to hard fail here */
}
} else {
#if defined(HAVE_MMAP) && defined(HAVE_CLI_GETPAGESIZE)
{
int psz = cli_getpagesize();
off_t mp_hdr = (c->hdr / psz) * psz;
mp_hdrsz = c->hdrsz + c->hdr - mp_hdr;
if((map = mmap(NULL, mp_hdrsz, PROT_READ, MAP_PRIVATE, desc, mp_hdr))==MAP_FAILED) {
if(!(map = fmap(desc, mp_hdr, mp_hdrsz))) {
cli_errmsg("is_parse_hdr: mmap failed\n");
return CL_EMEM;
}
hdr = map + c->hdr - mp_hdr;
#else
cli_warnmsg("is_parse_hdr: hdr too big and mmap is not usable\n");
return CL_CLEAN;
#endif
}
h1 = (struct IS_HDR *)hdr;
if(!CLI_ISCONTAINED(hdr, c->hdrsz, ((char *)h1), sizeof(*h1))) {
h1 = (struct IS_HDR *)fmap_need_ptr(map, hdr, sizeof(*h1));
if(!h1) {
cli_dbgmsg("is_parse_hdr: not enough room for H1\n");
IS_FREE_HDR;
fmunmap(map);
return CL_CLEAN;
}
h1_data_off = le32_to_host(h1->data_off);
objs = (struct IS_OBJECTS *)(hdr + h1_data_off);
if(!CLI_ISCONTAINED(hdr, c->hdrsz, ((char *)objs), sizeof(*objs))) {
objs = (struct IS_OBJECTS *)fmap_need_ptr(map, hdr + h1_data_off, sizeof(*objs));
if(!objs) {
cli_dbgmsg("is_parse_hdr: not enough room for OBJECTS\n");
IS_FREE_HDR;
fmunmap(map);
return CL_CLEAN;
}
@ -549,7 +526,7 @@ static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c) {
h1->magic, h1->unk1, h1->unk2, h1_data_off, h1->data_sz);
if(le32_to_host(h1->magic) != 0x28635349) {
cli_dbgmsg("is_parse_hdr: bad magic. wrong version?\n");
IS_FREE_HDR;
fmunmap(map);
return CL_CLEAN;
}
@ -590,9 +567,9 @@ static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c) {
objs_files_cnt = le32_to_host(objs->files_cnt);
off = h1_data_off + objs_dirs_off + le32_to_host(objs->dir_sz2);
for(i=0; i<objs_files_cnt ;i++) {
struct IS_FILEITEM *file = (struct IS_FILEITEM *)(&hdr[off]);
struct IS_FILEITEM *file = (struct IS_FILEITEM *)fmap_need_ptr(map, &hdr[off], sizeof(*file));
if(CLI_ISCONTAINED(hdr, c->hdrsz, ((char *)file), sizeof(*file))) {
if(file) {
const char *dir_name = "", *file_name = "";
uint32_t dir_rel = h1_data_off + objs_dirs_off + 4 * le32_to_host(file->dir_id); /* rel off of dir entry from array of rel ptrs */
uint32_t file_rel = objs_dirs_off + h1_data_off + le32_to_host(file->str_name_off); /* rel off of fname */
@ -601,12 +578,12 @@ static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c) {
memcpy(hash, file->md5, 16);
md5str((uint8_t *)hash);
if(CLI_ISCONTAINED(hdr, c->hdrsz, &hdr[dir_rel], 4)) {
if(fmap_need_ptr(map, &hdr[dir_rel], 4)) {
dir_rel = cli_readint32(&hdr[dir_rel]) + h1_data_off + objs_dirs_off;
if(CLI_ISCONTAINED(hdr, c->hdrsz, &hdr[dir_rel], 1) && memchr(&hdr[dir_rel], 0, c->hdrsz - dir_rel))
if(fmap_need_str(map, &hdr[dir_rel], c->hdrsz - dir_rel))
dir_name = &hdr[dir_rel];
}
if(CLI_ISCONTAINED(hdr, c->hdrsz, &hdr[file_rel], 1) && memchr(&hdr[file_rel], 0, c->hdrsz - file_rel))
if(fmap_need_str(map, &hdr[file_rel], c->hdrsz - file_rel))
file_name = &hdr[file_rel];
file_stream_off = le64_to_host(file->stream_off);
@ -646,7 +623,7 @@ static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c) {
scanned++;
if (ctx->engine->maxfiles && scanned >= ctx->engine->maxfiles) {
cli_dbgmsg("is_parse_hdr: File limit reached (max: %u)\n", ctx->engine->maxfiles);
IS_FREE_HDR;
fmunmap(map);
return CL_EMAXFILES;
}
cabret = is_extract_cab(desc, ctx, file_stream_off + c->cabs[j].off, file_size, file_csize);
@ -680,7 +657,7 @@ static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c) {
}
off += sizeof(*file);
}
IS_FREE_HDR;
fmunmap(map);
return ret;
}

Loading…
Cancel
Save