From patchwork Sun Nov 6 18:04:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Thibault X-Patchwork-Id: 691670 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3tBk4P2CjBz9tld for ; Mon, 7 Nov 2016 05:04:52 +1100 (AEDT) Received: from localhost ([::1]:45933 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1c3RoF-00016D-QG for incoming@patchwork.ozlabs.org; Sun, 06 Nov 2016 13:04:47 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55459) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1c3Rnc-0000nc-6x for qemu-devel@nongnu.org; Sun, 06 Nov 2016 13:04:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1c3RnY-0006qG-9B for qemu-devel@nongnu.org; Sun, 06 Nov 2016 13:04:08 -0500 Received: from hera.aquilenet.fr ([141.255.128.1]:59416) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1c3RnY-0006ou-0l for qemu-devel@nongnu.org; Sun, 06 Nov 2016 13:04:04 -0500 Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id A52AC986F; Sun, 6 Nov 2016 19:04:02 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at aquilenet.fr Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id BlzaeZx0Q8xW; Sun, 6 Nov 2016 19:04:01 +0100 (CET) Received: from var.youpi.perso.aquilenet.fr (unknown [IPv6:2a01:cb19:181:c200:3602:86ff:fe2c:6a19]) by hera.aquilenet.fr (Postfix) with ESMTPSA id C0F967193; Sun, 6 Nov 2016 19:04:01 +0100 (CET) Received: from samy by var.youpi.perso.aquilenet.fr with local (Exim 4.87) (envelope-from ) id 1c3RnV-0007ts-2V; Sun, 06 Nov 2016 19:04:01 +0100 Date: Sun, 6 Nov 2016 19:04:01 +0100 From: Samuel Thibault To: Stefan Hajnoczi , Brian Candler Message-ID: <20161106180401.GE27308@var.home> References: <95e79bc8-4547-b3b1-65b7-f641eb0c92f7@pobox.com> <20161104111419.GG9817@stefanha-x1.localdomain> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20161104111419.GG9817@stefanha-x1.localdomain> User-Agent: Mutt/1.5.21+34 (58baf7c9f32f) (2010-12-30) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 141.255.128.1 Subject: Re: [Qemu-devel] Crashing in tcp_close X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jan Kiszka , qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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 , > > p=, have_lock=0) at malloc.c:4006 > > 4006 malloc.c: No such file or directory. > > (gdb) bt > > #0 0x00007ffff6a1bb5b in _int_free (av=0x7ffff6d5fb20 , > > p=, have_lock=0) > > at malloc.c:4006 > > #1 0x00007ffff6a1fabc in __GI___libc_free (mem=) 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=) at slirp/tcp_subr.c:298 > > #4 0x00005555559a816b in tcp_timers (timer=, > > tp=0x555556621ed0) at slirp/tcp_timer.c:179 > > #3 0x00005555559a6c8f in tcp_drop (tp=tp@entry=0x555556621ed0, > > err=) at slirp/tcp_subr.c:298 > > #4 0x00005555559a816b in tcp_timers (timer=, > > 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; };