On 10 Jul, Alex Zepeda wrote:
> On Wed, Jul 10, 2002 at 01:34:50PM -0700, Don Lewis wrote:
> 
>> > ../../../vm/uma_core.c:1332: could sleep with "inp" locked from 
>../../../netinet/tcp_subr.c:935
>> > ../../../vm/uma_core.c:1332: could sleep with "tcp" locked from 
>../../../netinet/tcp_subr.c:928
>> 
>> I've never seen that one.  I'll take a look at the code, though.
> 
> I'm seeing the same (once at bootup tho).
> 
> sm:blarf:~$uptime
>  8:48PM  up 18:52, 4 users, load averages: 0.11, 0.06, 0.01
> sm:blarf:~$

I tracked it down to tcp_getcred() calling SYSCTL_OUT(), which can
potentially block, before releasing the locks tcp_getcred() is holding.
This routine is used by the net.inet.tcp.getcred sysctl, and the only
user of that seems to be the builtin ident code in inetd.  I'm not
seeing this error because I'm not running inetd on my -current box.

This bug is similar to the "kernel linker" bug, but is much easier to
fix.  There are similar errors in tcp6_getcred() and udp_getcred().

Give this patch a try:

Index: sys/netinet/tcp_subr.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/tcp_subr.c,v
retrieving revision 1.134
diff -u -r1.134 tcp_subr.c
--- sys/netinet/tcp_subr.c      30 Jun 2002 20:07:21 -0000      1.134
+++ sys/netinet/tcp_subr.c      11 Jul 2002 08:23:37 -0000
@@ -931,24 +931,23 @@
        if (inp == NULL) {
                error = ENOENT;
                goto outunlocked;
-       } else {
-               INP_LOCK(inp);
-               if (inp->inp_socket == NULL) {
-                       error = ENOENT;
-                       goto out;
-               }
        }
-
+       INP_LOCK(inp);
+       if (inp->inp_socket == NULL) {
+               error = ENOENT;
+               goto out;
+       }
        error = cr_canseesocket(req->td->td_ucred, inp->inp_socket);
        if (error)
                goto out;
        cru2x(inp->inp_socket->so_cred, &xuc);
-       error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
 out:
        INP_UNLOCK(inp);
 outunlocked:
        INP_INFO_RUNLOCK(&tcbinfo);
        splx(s);
+       if (error == 0)
+               error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
        return (error);
 }
 
@@ -994,22 +993,22 @@
        if (inp == NULL) {
                error = ENOENT;
                goto outunlocked;
-       } else {
-               INP_LOCK(inp);
-               if (inp->inp_socket == NULL) {
-                       error = ENOENT;
-                       goto out;
-               }
+       }
+       INP_LOCK(inp);
+       if (inp->inp_socket == NULL) {
+               error = ENOENT;
+               goto out;
        }
        error = cr_canseesocket(req->td->td_ucred, inp->inp_socket);
        if (error)
                goto out;
        cru2x(inp->inp_socket->so_cred, &xuc);
-       error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
 out:
        INP_UNLOCK(inp);
 outunlocked:
        INP_INFO_RUNLOCK(&tcbinfo);
+       if (error == 0)
+               error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
        splx(s);
        return (error);
 }
Index: sys/netinet/udp_usrreq.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.114
diff -u -r1.114 udp_usrreq.c
--- sys/netinet/udp_usrreq.c    21 Jun 2002 22:54:16 -0000      1.114
+++ sys/netinet/udp_usrreq.c    11 Jul 2002 08:27:56 -0000
@@ -681,6 +681,7 @@
        INP_INFO_RLOCK(&udbinfo);
        inp = in_pcblookup_hash(&udbinfo, addrs[1].sin_addr, addrs[1].sin_port,
                                addrs[0].sin_addr, addrs[0].sin_port, 1, NULL);
+       /* XXX - call INP_LOCK(inp)? - see tcp_getcred() */
        if (inp == NULL || inp->inp_socket == NULL) {
                error = ENOENT;
                goto out;
@@ -689,10 +690,12 @@
        if (error)
                goto out;
        cru2x(inp->inp_socket->so_cred, &xuc);
-       error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
+       /* XXX - call INP_UNLOCK(inp)? */
 out:
        INP_INFO_RUNLOCK(&udbinfo);
        splx(s);
+       if (error == 0)
+               error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
        return (error);
 }
 



To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to