From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/4426 Path: news.gmane.org!not-for-mail From: Szabolcs Nagy Newsgroups: gmane.linux.lib.musl.general Subject: Re: Re: NULL deref SEGV in malloc.c:unbin() Date: Sun, 29 Dec 2013 01:01:12 +0100 Message-ID: <20131229000112.GY1685@port70.net> References: <20131227190544.GF24286@brightrain.aerifal.cx> <20131227221345.GG24286@brightrain.aerifal.cx> Reply-To: musl@lists.openwall.com NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1388275282 25635 80.91.229.3 (29 Dec 2013 00:01:22 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sun, 29 Dec 2013 00:01:22 +0000 (UTC) To: musl@lists.openwall.com Original-X-From: musl-return-4430-gllmg-musl=m.gmane.org@lists.openwall.com Sun Dec 29 01:01:26 2013 Return-path: Envelope-to: gllmg-musl@plane.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by plane.gmane.org with smtp (Exim 4.69) (envelope-from ) id 1Vx3os-0004tY-16 for gllmg-musl@plane.gmane.org; Sun, 29 Dec 2013 01:01:26 +0100 Original-Received: (qmail 1476 invoked by uid 550); 29 Dec 2013 00:01:24 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Original-Received: (qmail 1468 invoked from network); 29 Dec 2013 00:01:24 -0000 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) Xref: news.gmane.org gmane.linux.lib.musl.general:4426 Archived-At: * David Wuertele [2013-12-28 01:28:42 +0000]: > I removed all my calls to malloc(), now it is only musl that is > calling it. I'm watching everything that I think might be related. > It looks like calloc(), opendir(), or free() are the culprit. > > (gdb) info watch > Num Type Disp Enb Address What > 2 watchpoint keep y mal.bins[40].head > breakpoint already hit 2 times > print *mal.bins[40].head > bt > cont > 3 watchpoint keep y mal.bins[40].head.next > breakpoint already hit 47 times > print *mal.bins[40].head > bt > cont > 3.1 y mal.bins[40].head.next > 3.2 y mal.bins[40].head.next > 4 watchpoint keep y mal.bins[40].head.prev > breakpoint already hit 32 times > print *mal.bins[40].head > bt > cont > 4.1 y mal.bins[40].head.prev > 4.2 y mal.bins[40].head.prev > (gdb) c > > Watchpoint 4: mal.bins[40].head.prev > > Old value = (struct chunk *) 0xc9690 > New value = (struct chunk *) 0x0 > 0x0008b268 in calloc (m=519, n=2080) at src/malloc/calloc.c:20 > 20 in src/malloc/calloc.c > $78 = {psize = 2097, csize = 2097, next = 0x0, prev = 0x0} > #0 0x0008b268 in calloc (m=519, n=2080) at src/malloc/calloc.c:20 > #1 0x00089f30 in opendir (name=0xaa8d4 ".") at src/dirent/opendir.c:19 > #2 0x0000fb50 in mkchdir (path=0xbe83f89b "") at prog.c:1845 if i understand the code correctly the state is already corrupted here the printed head chunk is returned from malloc (calloc zeros out next/prev) but it is still in the free list (bin[40].head) after the last free chunk is used up in a bin i think head == tail == BIN_TO_CHUNK(i) should hold (and mal.binmap & (1ULL< Watchpoint 3: mal.bins[40].head.next > > Old value = (struct chunk *) 0x0 > New value = (struct chunk *) 0x10 > opendir (name=0xaa8d4 ".") at src/dirent/opendir.c:24 > 24 src/dirent/opendir.c: No such file or directory. > in src/dirent/opendir.c > $79 = {psize = 2097, csize = 2097, next = 0x10, prev = 0x0} > #0 opendir (name=0xaa8d4 ".") at src/dirent/opendir.c:24 > #1 0x0000fb50 in mkchdir (path=0xbe83f89b "") at prog.c:1845 this is just opendir setting dir->fd (dir == &head->next) > Watchpoint 3: mal.bins[40].head.next > > Old value = (struct chunk *) 0x10 > New value = (struct chunk *) 0x2139018 > free (p=0x2139020) at src/malloc/malloc.c:530 > 530 src/malloc/malloc.c: No such file or directory. > in src/malloc/malloc.c > $80 = {psize = 2096, csize = 2097, next = 0x2139018, prev = 0x0} > #0 free (p=0x2139020) at src/malloc/malloc.c:530 > #1 0x00089e84 in closedir (dir=0x2139020) at src/dirent/closedir.c:9 > #2 0x0000fc80 in mkchdir (path=0xd22bc "/var/spool") at prog.c:1873 a chunk is freed here (0x2139018) which we haven't seen yet but is put on the same free list that is already broken self->prev->next = self; triggers the watchpoint (where &self->prev->next == &bin[40].head) so the free-list has two chunks now: head is the broken chunk returned in opendir and the new one freed here > > Program received signal SIGSEGV, Segmentation fault. > 0x0008be70 in unbin (c=0x2139848, i=40) at src/malloc/malloc.c:241 > 241 in src/malloc/malloc.c > (gdb) > i assume 0x2139848 is the broken chunk and unbin stumbles on the 0 prev pointer so it seems the corruption starts before opendir it would be nice to see where 0x2139018 comes from and why mal.binmap and mal.bin[40] aren't managed properly