Hello,

Stefan Hajnoczi, on Fri 04 Nov 2016 11:14:19 +0000, wrote:
> CCing slirp maintainers to get attention on this bug

Thanks!

> > Thread 1 "qemu-system-x86" received signal SIGSEGV, Segmentation fault.
> > 0x00007ffff6a1bb5b in _int_free (av=0x7ffff6d5fb20 <main_arena>,
> > p=<optimised out>, have_lock=0) at malloc.c:4006
> > 4006    malloc.c: No such file or directory.
> > (gdb) bt
> > #0  0x00007ffff6a1bb5b in _int_free (av=0x7ffff6d5fb20 <main_arena>,
> > p=<optimised out>, have_lock=0)
> >     at malloc.c:4006
> > #1  0x00007ffff6a1fabc in __GI___libc_free (mem=<optimised out>) at
> > malloc.c:2969
> > #2  0x00005555559a6c0f in tcp_close (tp=tp@entry=0x555556621ed0) at
> > slirp/tcp_subr.c:334
> > #3  0x00005555559a6c8f in tcp_drop (tp=tp@entry=0x555556621ed0,
> > err=<optimised out>) at slirp/tcp_subr.c:298
> > #4  0x00005555559a816b in tcp_timers (timer=<optimised out>,
> > tp=0x555556621ed0) at slirp/tcp_timer.c:179
> > #3  0x00005555559a6c8f in tcp_drop (tp=tp@entry=0x555556621ed0,
> > err=<optimised out>) at slirp/tcp_subr.c:298
> > #4  0x00005555559a816b in tcp_timers (timer=<optimised out>,
> > tp=0x555556621ed0) at slirp/tcp_timer.c:179
> > #5  tcp_slowtimo (slirp=slirp@entry=0x55555658ecf0) at slirp/tcp_timer.c:89

> > * If so, what additional gdb output would you like me to provide?
> 
> I wonder if this connection has already been closed/freed before and the
> timer fires shortly afterward.  That's just a guess based on the
> backtrace.

That's very unlikely: soclose removes the socket from the list, so
tcp_slowtimo wouldn't be able to find it. That'd rather be a buffer
overflow. But it's hard to believe it could come from the socket
structure since it doesn't contain any buffer.

Brian, could you run it with

export MALLOC_CHECK_=2

and also this could be useful:

export MALLOC_PERTURB_=1234

Also, to rule out the double-free scenario, and try to catch a buffer
overflow coming from the socket structure itself, I have attached a
patch which adds some debugging.

> > * If developers want to reproduce this, let me know and I can probably send
> > the VM qcow2 file and/or packer source privately off-list [I need to check
> > permission for that]

That could be useful.

Samuel
diff --git a/slirp/socket.c b/slirp/socket.c
index 280050a..e603164 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -51,10 +51,12 @@ socreate(Slirp *slirp)
   so = (struct socket *)malloc(sizeof(struct socket));
   if(so) {
     memset(so, 0, sizeof(struct socket));
+    so->canary1 = 0xdeadbeef;
     so->so_state = SS_NOFDREF;
     so->s = -1;
     so->slirp = slirp;
     so->pollfds_idx = -1;
+    so->canary2 = 0xbe3fd3ad;
   }
   return(so);
 }
@@ -67,6 +69,14 @@ sofree(struct socket *so)
 {
   Slirp *slirp = so->slirp;
 
+  if (so->s == -1234)
+    fprintf(stderr,"oops, re-freeing a freed socket!\n");
+  if (so->canary1 != 0xdeadbeef)
+    fprintf(stderr,"oops, canary1 bogus!\n");
+  if (so->canary2 != 0xbe3fd3ad)
+    fprintf(stderr,"oops, canary2 bogus!\n");
+  so->s = -1234;
+
   if (so->so_emu==EMU_RSH && so->extra) {
        sofree(so->extra);
        so->extra=NULL;
diff --git a/slirp/socket.h b/slirp/socket.h
index 8feed2a..14fac1c 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -17,6 +17,7 @@
 
 struct socket {
   struct socket *so_next,*so_prev;      /* For a linked list of sockets */
+  int canary1;
 
   int s;                           /* The actual socket */
 
@@ -70,6 +71,7 @@ struct socket {
   struct sbuf so_rcv;          /* Receive buffer */
   struct sbuf so_snd;          /* Send buffer */
   void * extra;                        /* Extra pointer */
+  int canary2;
 };
 
 

Reply via email to