Hiya,

(that's on debian testing amd64 with libclamav6 0.97.2+dfsg-1)

I had a few c-icap crashes on scanning some debian packages for firefox
(for instance:
http://ftp.se.debian.org/debian/pool/main/i/iceweasel/iceweasel_7.0.1-2_amd64.deb)

It can be reproduced on amd64 with
clamscan --max-recursion=5 iceweasel_7.0.1-2_amd64.deb

That gives:
*** glibc detected *** clamscan: double free or corruption
(out): 0x0000000002191fd0 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x72606)[0x7f370d743606]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x6c)[0x7f370d74833c]
/usr/lib/libclamav.so.6(html_tag_arg_free+0x25)[0x7f370dd62b15]
/usr/lib/libclamav.so.6(+0xf2862)[0x7f370dd63862]
/usr/lib/libclamav.so.6(html_normalise_map+0x23)[0x7f370dd66763]
[...]

That's on the free(ctx.fmap) in scanners.c

Running valgrind:

==31006== Invalid write of size 8
==31006==    at 0x62D9D72: magic_scandesc (scanners.c:1985)
==31006==    by 0x62E0C14: fileblobScan (blob.c:639)
==31006==    by 0x62E026A: fileblobScanAndDestroy (blob.c:399)
==31006==    by 0x62E547B: saveTextPart (mbox.c:2589)
==31006==    by 0x62E45C6: parseEmailBody (mbox.c:2100)
==31006==    by 0x62E136F: cli_parse_mbox (mbox.c:511)
==31006==    by 0x62E0D69: cli_mbox (mbox.c:311)
==31006==    by 0x62BB4B3: cli_scanmail (scanners.c:1553)
==31006==    by 0x62DACC8: magic_scandesc (scanners.c:2164)
==31006==    by 0x62D97C5: cli_scanfile (scanners.c:2489)
==31006==    by 0x62D995A: cli_scandir (scanners.c:146)
==31006==    by 0x62BB3F1: cli_scanhtml (scanners.c:1019)
==31006==  Address 0x10a7a738 is 0 bytes after a block of size
56 alloc'd
==31006==    at 0x4C25E84: calloc (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==31006==    by 0x6AD64F1: cli_calloc (others_common.c:214)
==31006==    by 0x62DC7D7: cl_scandesc_callback
(scanners.c:2425)
==31006==    by 0x601618F: srvclamav_end_of_data_handler
(srv_clamav.c:502)
==31006==    by 0x40B76C: do_request (in /usr/bin/c-icap)
==31006==    by 0x40BA0B: process_request (in /usr/bin/c-icap)
==31006==    by 0x4146A9: thread_main (in /usr/bin/c-icap)
==31006==    by 0x4E33B3F: start_thread (pthread_create.c:304)

fmap is calloced as an array of maxreclevel + 2 pointers.

I can definitely see fmap being increased past that in gdb (gdb
output below).

This patch makes the problem go away but it's probably not the
right fix as it rather seems that there's at least one place where
recursion is not increased where it should be. See comments in gdb
output for more info.

diff --git a/libclamav/scanners.c b/libclamav/scanners.c
index c7a152c..37bc9f3 100644
--- a/libclamav/scanners.c
+++ b/libclamav/scanners.c
@@ -2624,7 +2624,7 @@ int cl_scandesc_callback(int desc, const char **virname,
unsigned long int *scan
     ctx.container_size = 0;
     ctx.dconf = (struct cli_dconf *) engine->dconf;
     ctx.cb_ctx = context;
-    ctx.fmap = cli_calloc(sizeof(fmap_t *), ctx.engine->maxreclevel + 2);
+    ctx.fmap = cli_calloc(ctx.engine->maxreclevel + 3, sizeof(fmap_t *));
     if(!ctx.fmap)
        return CL_EMEM;
     if (!(ctx.hook_lsig_matches = cli_bitset_init())) {



GDB Output (the bt output is not useful so not included):

> Hardware watchpoint 2: ctx.fmap
> 
> Old value = (fmap_t **) 0x0
> New value = (fmap_t **) 0xe52a00
> cl_scandesc_callback (desc=9, virname=<optimized out>, scanned=<optimized 
> out>, engine=<optimized out>, scanoptions=<optimized out>, context=<optimized 
> out>) at scanners.c:2426
> 2426        if(!ctx.fmap)
> (gdb)
> Continuing.
> Hardware watchpoint 2: ctx.fmap
> 
> Old value = (fmap_t **) 0xe52a00
> New value = (fmap_t **) 0xe52a08
> magic_scandesc (desc=9, ctx=0x7f1ebbd54c00, type=CL_TYPE_ANY) at 
> scanners.c:1985
> 1985        if(!(*ctx->fmap = fmap(desc, 0, sb.st_size))) {
> (gdb) break
> Breakpoint 4 at 0x7f1ec4438d6a: file scanners.c, line 1985.
> (gdb) commands 4
> Type commands for breakpoint(s) 4, one per line.
> End with a line saying just "end".
> >p ctx->fmap
> >p ctx->recursion
> >cont
> >end
> (gdb) cont
> Continuing.
> Hardware watchpoint 3: ctx.recursion
> 
> Old value = 0
> New value = 1
> magic_scandesc (desc=9, ctx=0x7f1ebbd54c00, type=CL_TYPE_BINARY_DATA) at 
> scanners.c:2077
> 2077        switch(type) {
> (gdb)
> Continuing.
> Hardware watchpoint 3: ctx.recursion
> 
> Old value = 1
> New value = 0
> magic_scandesc (desc=9, ctx=0x7f1ebbd54c00, type=<optimized out>) at 
> scanners.c:2314
> 2314        if(ret == CL_VIRUS) {
> (gdb)
> Continuing.
> [New Thread 0x7f1eba26b700 (LWP 2029)]
> 
> Watchpoint 2 deleted because the program has left the block in
> which its expression is valid.
 
Here recursion not increased but magic_scandesc reentered somehow via
cli_scanraw() -> ??? -> cli_bcapi_extract_new().
  
> magic_scandesc (desc=10, ctx=0x7f1ebbd54c00, type=CL_TYPE_ANY) at 
> scanners.c:1985
> 1985        if(!(*ctx->fmap = fmap(desc, 0, sb.st_size))) {
> $1 = (fmap_t **) 0xe52a10
> $2 = 0
> [...]
> Breakpoint 4, magic_scandesc (desc=16, ctx=0x7f1ebbd54c00, type=CL_TYPE_ANY) 
> at scanners.c:1985
> 1985        if(!(*ctx->fmap = fmap(desc, 0, sb.st_size))) {
> $1163 = (fmap_t **) 0xe52a38
> $1164 = 5

Recursion is 5, and we're writing at 0xe52a38, 0x38 bytes (7 * 8) after 
0xe52a00 returned by calloc(8,7).

-- 
Stephane

_______________________________________________
http://lurker.clamav.net/list/clamav-devel.html
Please submit your patches to our Bugzilla: http://bugs.clamav.net

Reply via email to