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;
};