[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#457337: libc6: mremap() returns invalid address



On Fri, Dec 21, 2007 at 09:20:14PM +0000, Andreas Klöckner wrote:
> On Freitag 21 Dezember 2007, Daniel Jacobowitz wrote:
> > On Fri, Dec 21, 2007 at 12:15:43PM -0500, Andreas Kloeckner wrote:
> > > Breakpoint 1, mmap_resize (m=0x2b6a5b236010, oldp=0x2b6a5bdb4000,
> > > nb=406784) at src/gklib/dlmalloc.c:2358
> > > 2358        if (cp != CMFAIL) {
> >
> > So you're here...
> >
> > > 2356        char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
> > > 2357                                      oldmmsize, newmmsize, 1);
> >
> > Having just done this...
> >
> > > #define CALL_MREMAP(addr, osz, nsz, mv) ((void)(addr),(void)(osz), \
> > >                                          (void)(nsz), (void)(mv),MFAIL)
> >
> > Which you said expands to this...
> >
> > > (gdb) p cp
> > > $3 = 0x5bdb4000 <Address 0x5bdb4000 out of bounds>
> >
> > So how can this possibly be true, and how does mremap have anything to
> > do with your problem?  Nowhere in this code are you calling it.
> >
> > I think we need a testcase for this problem, if you are convinced it
> > has something to do with glibc.  Also try strace.
> 
> Oops. I pasted the wrong line. CALL_MREMAP is
> 
> 8< ------------------------------------------------------------
> #define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
> 8< ------------------------------------------------------------
> 
> And there is indeed a call to mremap, and it is indeed the last thing the 
> process does. The strace return value looks ok, but the value that arrives in 
> C (at least according to gdb and the segfault) is not.
> 
> 8< ------------------------------------------------------------
> ...
> mremap(0x2ba79d9ef000, 573440, 409600, MREMAP_MAYMOVE) = 0x2ba79d9ef000
> --- SIGSEGV (Segmentation fault) @ 0 (0) ---
> +++ killed by SIGSEGV +++

  This strongly looks like a bug in dlmalloc, please read this mremap,
you ask for a _smaller_ map, and in that case, the kernel gives you the
same address, it just removes some pages at the end. I'd say that you
try to read in the old pages that you don't have anymore, and get a
sigsegv. Beware that `p cp` in gdb may yield surprising results in -O2,
especially since:

> > > Breakpoint 1, mmap_resize (m=0x2b6a5b236010, oldp=0x2b6a5bdb4000,
                                   ^^^^^^^^^^^^^^
> > > (gdb) p cp
> > > $3 = 0x5bdb4000 <Address 0x5bdb4000 out of bounds>
           ^^^^^^^^^^
> mremap(0x2ba79d9ef000, 573440, 409600, MREMAP_MAYMOVE) = 0x2ba79d9ef000
         ^^^^^^^^^^^^^^                                     ^^^^^^^^^^^^

  It looks like mremap does what it should, and that for _some_ reason
cp is broken, but according to strace, it's not mremap's fault.

  Some printf("%p\n", cp); just after the mremap would help you to debug
probably.
-- 
·O·  Pierre Habouzit
··O                                                madcoder@debian.org
OOO                                                http://www.madism.org

Attachment: pgpwuWQ8cmUYC.pgp
Description: PGP signature


Reply to: