Possible bug in malloc-code

Willem Jan Withagen wjw at withagen.nl
Mon May 31 13:46:35 PDT 2004


> > > If a section is larger than INT_MAX, then overflow seems to occur here
> > > in __elfN_coredump():
> > >
> > > % for (i = 0; i < seginfo.count; i++) {
> > > % error = vn_rdwr_inchunks(UIO_WRITE, vp,
> > > %     (caddr_t)php->p_vaddr, php->p_filesz, offset,
> > >                              ^^^^^^^^^^^^^
> > > %     UIO_USERSPACE, IO_DIRECT, cred, NOCRED, NULL, td);
> > >
> > > php->p_filesz has type u_int64_t on 64-bit machines, but here it gets
> > > silently converted to int, so it overflows if the size is larger than
> > > INT_MAX.  (Overflow may occur even on 32-bit machines, but it's harder
> > > to fit a section larger than INT_MAX on a 32-bit machine.)  If ints
> > > are 32-bits 2's complement and the section size is between 2^31 and
> > > 2^32-1 inclusive, then the above asks vn_rdwr() a negative length.
> > > The negative length apparently gets as far as ffs_write() before
> > > causing a panic.
> > >
> > > It;s a longstanding bug that ssize_t is 64 bits and SSIZE_MAX is
> > > 2^63-1 on 64 bit machines, but writes from userland are limited to
> > > INT_MAX (normally 2^31-1), so 64-bit applications would have a hard
> > > time writing huge amounts.  Core dumps apparently have the same
> > > problem writing large sections.  A text section with size 2GB would
> > > be huge, but a data section with size 2GB is just large.
> > >
> > > The traceback should show the args, but that seems to be broken for
> > > amd64's.
> 
> Am I right in assuming that instead of 'int len' as parameter it then should
> read ssize_t??? Since that is what the description of ssize_t is. 
> Although I would expect ssize_t to be defined unsigned..

Aarrgh, just make it size_t.

Well it fixed crashing the box...

        i =         11
Alloc:  n =  335544320, ADR = 0x00000000485D7000
Alloc:  n =  402653184, ADR = 0x000000005C5D7000
Alloc:  n =  469762048, ADR = 0x00000000745D7000
Alloc:  n =  536870912, ADR = 0xFFFFFFFF905D7000
Free:   n =  536870912, ADR = 0xFFFFFFFF905D7000
rMemoryDrv in free(): error: junk pointer, too high to make sense
Abort (core dumped)

and delivers:

2891984 -rw-------  1 wjw   wheel  2959912960 May 31 22:37 rMemoryDrv.core

What is the procedure now???
I submit a diff relative to /usr/src in a PR??
Or is this sufficient, and does somebody want to commit this?

--- sys/kern/vfs_vnops.c.org    Mon May 31 22:42:48 2004
+++ sys/kern/vfs_vnops.c        Mon May 31 22:00:57 2004
@@ -370,7 +370,7 @@
        enum uio_rw rw;
        struct vnode *vp;
        caddr_t base;
-       int len;
+       size_t len;
        off_t offset;
        enum uio_seg segflg;
        int ioflg;
@@ -460,7 +460,7 @@
        enum uio_rw rw;
        struct vnode *vp;
        caddr_t base;
-       int len;
+       size_t len;
        off_t offset;
        enum uio_seg segflg;
        int ioflg;

--WjW



More information about the freebsd-current mailing list