Hi!

flow-expire dies on my computer with segmentation fault. I'm trying to
execute it as flow-expire -E10M -w
/var/log/netflow/a93core/2005-11/2005-11-22. I've got a core dump:

Core was generated by `flow-expire'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/lib/libwrap.so.4...done.
Loaded symbols for /usr/lib/libwrap.so.4
Reading symbols from /lib/libz.so.3...done.
Loaded symbols for /lib/libz.so.3
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /libexec/ld-elf.so.1...done.
Loaded symbols for /libexec/ld-elf.so.1
#0  0x0804b82e in ftfile_expire (fte=0xbfbfea80, doit=1, curbytes=0)
    at ftfile.c:358
358           fterr_info("remove/2 %s", n1->name);
(gdb) bt
#0  0x0804b82e in ftfile_expire (fte=0xbfbfea80, doit=1, curbytes=0)
    at ftfile.c:358
#1  0x08049c94 in main (argc=4, argv=0xbfbfeae8) at flow-expire.c:130

BTW, flow-capture dies too, when it tries to expire flow files.

I think, the problem is here:

  if (fte->max_bytes && (fte->num_bytes+curbytes > fte->max_bytes)) {
    FT_TAILQ_FOREACH(n1, &fte->head, chain) {
      fterr_info("remove/2 %s", n1->name);
      bytes += n1->size;
      ++i;
      if (doit) {
        FT_TAILQ_REMOVE(&fte->head, n1, chain);
        if (unlink(n1->name) == -1) 
          fterr_warn("unlink(%s)", n1->name);
        ftfile_entry_free(n1);
      } /* doit */

At first you ftfile_entry_free(n1) and on the next use n1 in
FT_TAILQ_REMOVE. But new FreeBSD's malloc fill free blocks with
0x5a. So, I see in gdb:

(gdb) p n1
$8 = (struct ftfile_entry *) 0xa000190
(gdb) p n1->chain.tqe_next
$9 = (struct ftfile_entry *) 0x5a5a5a5a

on the second iteration. I think here a problem too:

void ftfile_free(struct ftfile_entries *fte)
{
  struct ftfile_entry *n1, *n2;

  FT_TAILQ_FOREACH(n1, &fte->head, chain) {
    FT_TAILQ_REMOVE(&fte->head, n1, chain);
    n2 = n1;
    n1 = FT_TAILQ_NEXT(n1, chain);
    ftfile_entry_free(n2);
    if (!n1)
      break;
  }

You do FT_TAILQ_NEXT and do it AGAIN in FT_TAILQ_FOREACH. So you do
free every second element only.

This is a patch that I think fixes it all:

--- lib/ftfile.c.orig   Thu Feb 13 05:38:42 2003
+++ lib/ftfile.c        Fri Feb 10 10:39:40 2006
@@ -311,7 +311,7 @@
 int ftfile_expire (struct ftfile_entries *fte, int doit, int curbytes)
 {
   u_int i;
-  struct ftfile_entry *n1;
+  struct ftfile_entry *n1, *n2;
   u_int64 bytes;
 
   /*
@@ -323,15 +323,20 @@
   bytes = 0;
 
   if (fte->max_files && (fte->num_files > fte->max_files)) {
+    n2 = NULL;
     FT_TAILQ_FOREACH(n1, &fte->head, chain) {
+      if (n2 != NULL) {
+       ftfile_entry_free(n2);
+       n2 = NULL;
+      }
       fterr_info("remove/1 %s", n1->name);
       bytes += n1->size;
       ++i;
       if (doit) {
+        n2 = n1;
         FT_TAILQ_REMOVE(&fte->head, n1, chain);
         if (unlink(n1->name) == -1) 
           fterr_warn("unlink(%s)", n1->name);
-        ftfile_entry_free(n1);
       } /* doit */
       if ((fte->num_files - i) <= fte->max_files)
         break;
@@ -340,6 +345,10 @@
       fte->num_files -= i;
       fte->num_bytes -= bytes;
     } /* doit */
+    if (n2 != NULL) {
+      ftfile_entry_free(n2);
+      n2 = NULL;
+    }
   } /* if */
 
   if (debug)
@@ -354,15 +363,20 @@
    */
 
   if (fte->max_bytes && (fte->num_bytes+curbytes > fte->max_bytes)) {
+    n2 = NULL;
     FT_TAILQ_FOREACH(n1, &fte->head, chain) {
+      if (n2 != NULL) {
+       ftfile_entry_free(n2);
+       n2 = NULL;
+      }
       fterr_info("remove/2 %s", n1->name);
       bytes += n1->size;
       ++i;
       if (doit) {
+        n2 = n1;
         FT_TAILQ_REMOVE(&fte->head, n1, chain);
         if (unlink(n1->name) == -1) 
           fterr_warn("unlink(%s)", n1->name);
-        ftfile_entry_free(n1);
       } /* doit */
       if ((fte->num_bytes+curbytes - bytes) <= fte->max_bytes)
         break;
@@ -371,6 +385,10 @@
       fte->num_files -= i;
       fte->num_bytes -= bytes;
     } /* doit */
+    if (n2 != NULL) {
+      ftfile_entry_free(n2);
+      n2 = NULL;
+    }
   } /* if */
 
   if (debug)
@@ -762,13 +780,19 @@
 {
   struct ftfile_entry *n1, *n2;
 
+  n2 = NULL;
   FT_TAILQ_FOREACH(n1, &fte->head, chain) {
+    if (n2 != NULL) {
+      ftfile_entry_free(n2);
+      n2 = NULL;
+    }
     FT_TAILQ_REMOVE(&fte->head, n1, chain);
     n2 = n1;
-    n1 = FT_TAILQ_NEXT(n1, chain);
+  }
+
+  if (n2 != NULL) {
     ftfile_entry_free(n2);
-    if (!n1)
-      break;
+    n2 = NULL;
   }
 
 } /* ftfile_free */

-- 
DSS5-RIPE DSS-RIPN 2:550/[EMAIL PROTECTED] 2:550/[EMAIL PROTECTED]
mailto:[EMAIL PROTECTED] http://neva.vlink.ru/~dsh/
_______________________________________________
Flow-tools mailing list
[EMAIL PROTECTED]
http://mailman.splintered.net/mailman/listinfo/flow-tools

Reply via email to