inetd crashes VKERNEL

Nicolas Thery nthery at gmail.com
Sat Jul 5 08:05:07 PDT 2008


2008/7/4 Thomas Nikolajsen <thomas.nikolajsen at mail.dk>:
> inetd crashes VKERNEL, see below;
> it crashes almost every time.
>
> Also: I get no DDB prompt when VKERNEL crashes;
> using vkernel w/o SMP I do get DDB prompt.
>
>  -thomas
> -
> root at vonzales0# inetd
> root at vonzales0# panic: memory chunk 0x53f09190 is already free!
> mp_lock = 00000001; cpuid = 1
> Trace beginning at frame 0x56fc3b38
> panic(56fc3b5c,53f09190,53f080d0,53f09190,56fc3b84) at 0x80b3e80
> panic(81f607c,53f09190,53f09190,53f08000,4140048c) at 0x80b3e80
> kfree(53f09190,8226980,281460a0,1,0) at 0x80b196f
> so_pru_ctloutput(567f1ea0,56fc3c54,570bff00,56fc3c07,53f347a8) at 0x80e35b2
> sosetopt(567f1ea0,56fc3c54,56ffdaf0,822028c,5671fb98) at 0x80e45e4
> kern_setsockopt(4,56fc3c54,1,0,15) at 0x80e7a54
> sys_setsockopt(56fc3c98,6,0,0,56707c80) at 0x80e84c4

I can't reproduce the bug maybe because the suspicious code I mention
below seems
exercised by IPv6 only and I haven't configured that.

It looks like so_pru_ctloutput() passes an invalid sopt_val to
kfree().  This code was changed
recently:

http://leaf.dragonflybsd.org/mailarchive/commits/2008-06/msg00123.html

There is some pointer  arithmetic on sopt_val in soopt_mcopyout() that
may cause the panic you
observe.  sopt_val ends up pointing past the data copied from the
mbuf. Maybe this is
intentional as the code is old (imported straight from fbsd 4 and is
still in fbsd head).  This
would allow to append more data later on. On the other hand, maybe
that's a bug.  Only a
networking savvy person could say.

In the latter case, you could try the following (untested) patch:

Index: src2/sys/kern/uipc_socket.c
===================================================================
--- src2.orig/sys/kern/uipc_socket.c	2008-06-27 18:24:46.000000000 +0200
+++ src2/sys/kern/uipc_socket.c	2008-07-05 12:08:49.000000000 +0200
@@ -1646,23 +1646,24 @@ soopt_mcopyout(struct sockopt *sopt, str
 {
 	struct mbuf *m0 = m;
 	size_t valsize = 0;
+	void *val;

 	if (sopt->sopt_val == NULL)
 		return 0;
+	val = sopt->sopt_val;
 	while (m != NULL && sopt->sopt_valsize >= m->m_len) {
 		if (sopt->sopt_td != NULL) {
 			int error;

-			error = copyout(mtod(m, char *), sopt->sopt_val,
-				       m->m_len);
+			error = copyout(mtod(m, char *), val, m->m_len);
 			if (error != 0) {
 				m_freem(m0);
 				return (error);
 			}
 		} else
-			bcopy(mtod(m, char *), sopt->sopt_val, m->m_len);
+			bcopy(mtod(m, char *), val, m->m_len);
 	       sopt->sopt_valsize -= m->m_len;
-	       sopt->sopt_val = (caddr_t)sopt->sopt_val + m->m_len;
+	       val = (caddr_t)val + m->m_len;
 	       valsize += m->m_len;
 	       m = m->m_next;
 	}

Cheers,
Nicolas





More information about the Bugs mailing list