Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Aug 1999 13:38:38 +0930 (CST)
From:      "Daniel O'Connor" <doconnor@gsoft.com.au>
To:        freebsd-hackers@freebsd.org
Cc:        bvandepe@gsoft.com.au
Subject:   Kernel malloc problem?
Message-ID:  <XFMail.990811133838.doconnor@gsoft.com.au>

next in thread | raw e-mail | index | archive | help
This message is in MIME format
--_=XFMail.1.3.p0.FreeBSD:990811133838:611=_
Content-Type: text/plain; charset=us-ascii

We are experiencing what appears to be a memory corruption
problem with a kernel device driver running under FreeBSD
2.2.8-STABLE with the CAM patches.

The driver manages a series of memory buffers implemented
using a singly-linked tail list. The number and size of
buffers may be changed via an ioctl call which causes all
of the currently-allocated buffers (one per tail list element)
to be deallocated, and a new set - matching the required buffer
size - to be malloc'ed. The tail queue holding the newly-
allocated buffers is a local copy, and not subject to change
in the event of an interrupt meant for the driver. Given
certain choices for the size and number of buffers, we are observing
corruption of the local copy of the tail queue during and 
after the memory allocation process. The corruption usually takes the
form of a NULL pointer overwriting the linking member of a
queue element somewhere in the list, thus rendering some
protions of the allocated memory to be "lost", or non-free-able.

The particular combination of buffer size and number of buffers
which exhibits the problem is:

        buffer_size = 8k + 8 bytes (8k buffer + link pointer etc)
        num_buffers >= 22. 

If less than 22 buffers are allocated, the list appears to remain
intact. I'm not sure if it's relavant, but I note that
22 * 8k is just over the 256 kb size, while 21 * 8k is less than this
total.

Here is the snipet of code which builds the list ->

   STAILQ_INIT(&buildlist);

   gsio_tossbuffers(sc);           /* dump old buffers */
   i = args->value;

   while(i--) {            /* allocate required buffers */
     gb = malloc(sizeof(struct gsio_buf) + args->which, M_DEVBUF, M_NOWAIT);
     debug(BUF2, "g_freelist +> %p", gb);
                   
     if (gb == NULL) {           /* allocate failed, toss all
                                  * buffers */
       debug(BUF, "failed to allocate buffers, freeing");
       while ((gb = STAILQ_FIRST(&buildlist)) != NULL) {
         STAILQ_REMOVE_HEAD(&buildlist, g_link);
         free(gb, M_DEVBUF);
       }
       error = ENOMEM;
       break;
     } else {
       STAILQ_INSERT_HEAD(&buildlist, gb, g_link);
       debug(BUF, "New buffer at %p length 0x%x, next is %p ,tail is %p",
                gb, sizeof(struct gsio_buf) + args->which,
                gb->g_link.stqe_next,
                buildlist.stqh_last);
     }
   }

---
Daniel O'Connor software and network engineer
for Genesis Software - http://www.gsoft.com.au
"The nice thing about standards is that there
are so many of them to choose from."
  -- Andrew Tanenbaum

--_=XFMail.1.3.p0.FreeBSD:990811133838:611=_
Content-Type: application/pgp-signature

-----BEGIN PGP MESSAGE-----
Version: 2.6.3ia

iQCVAwUBN7D3RVbYW/HEoF9pAQFRtwP9HuRIBLhozHk/bzcLA/QR/ElUMvgxUB9I
Ferhxxt6AwnxJuBqBSs2KytD2X5HWpNoB/Mw+PKj5HsTucL7XsJD2T7+Jd9+MHBD
jsKrTB11lYeSumDXbCN6g9kysQ3bUM0DzLDJGS/6MPQu5+vsV+jglf3bm7HFVFfx
T6OaL0vOans=
=mbl5
-----END PGP MESSAGE-----

--_=XFMail.1.3.p0.FreeBSD:990811133838:611=_--
End of MIME message


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?XFMail.990811133838.doconnor>