bug in __tcp_inherit_port ?

From: Bulent Abali (abali@us.ibm.com)
Date: Sun Jul 01 2001 - 20:00:44 EST


I get an occasional panic in __tcp_inherit_port(sk,child). I believe the
reason is tb=sk->prev is NULL.

sk->prev is set to NULL in only few places including __tcp_put_port(sk).
Perhaps there is a serialization problem between __tcp_inherit_port and
__tcp_put_port ??? One possibility is that sk->num != child->num.
Therefore spin_locks in the two routines do not serialize.

This code is out of my league so I couldn't debug any further. Ingo, this
is the same problem that I posted to linux-kernel couple weeks ago for
tcp_v4_syn_recv_sock.

Problem occurs when running TUX-B6, 2.4.5-ac4 with SPECweb99, dual PIII,
and one acenic adapter. It is difficult to trigger but did occur few
times so far. In the following are the oops and objdump
/bulent.

=========

/* Caller must disable local BH processing. */
static __inline__ void __tcp_inherit_port(struct sock *sk, struct sock
*child)
{
     struct tcp_bind_hashbucket *head =
&tcp_bhash[tcp_bhashfn(child->num)];
     struct tcp_bind_bucket *tb;

     spin_lock(&head->lock);
     tb = (struct tcp_bind_bucket *)sk->prev; <** line 149
     if ((child->bind_next = tb->owners) != NULL) <** panic here
          tb->owners->bind_pprev = &child->bind_next;
     tb->owners = child;
     child->bind_pprev = &tb->owners;
     child->prev = (struct sock *) tb;
     spin_unlock(&head->lock);
}

__inline__ void __tcp_put_port(struct sock *sk)
{
     struct tcp_bind_hashbucket *head = &tcp_bhash[tcp_bhashfn(sk->num)];
     struct tcp_bind_bucket *tb;

     spin_lock(&head->lock);
     tb = (struct tcp_bind_bucket *) sk->prev;
     if (sk->bind_next)
          sk->bind_next->bind_pprev = sk->bind_pprev;
     *(sk->bind_pprev) = sk->bind_next;
     sk->prev = NULL;
     sk->num = 0;
     if (tb->owners == NULL) {
          if (tb->next)
               tb->next->pprev = tb->pprev;
          *(tb->pprev) = tb->next;
          kmem_cache_free(tcp_bucket_cachep, tb);
     }
     spin_unlock(&head->lock);
}

====
oops output

NULL pointer dereference at virtual address 00000008
 printing eip:
c0247a34
*pde = 00000000
Oops: 0000
CPU: 0
EIP: 0010:[<c0247a34>]
EFLAGS: 00010246
eax: 00000000 ebx: f74224c0 ecx: 00000000 edx: f74224c0
esi: f7500000 edi: f71e6cf0 ebp: f74225b4 esp: c0313c00
ds: 0018 es: 0018 ss: 0018
Process swapper (pid: 0, stackpage=c0313000)
Stack: f2a55ec4 f2d6bf64 459d1162 f74224c0 c024aff9 f74224c0 f2a55ec4
f2d6bf64
       00000000 459d1163 459d1162 459d1163 00000000 00001000 f74225b4
f740f58c
       f7760c00 c022a3c5 f740f58c c0231e76 e11d2a9c f7760cd8 f740083c
00000000
Call Trace: [<c024aff9>] [<c022a3c5>] [<c0231e76>] [<c01bff2c>]
[<f8805514>]
   [<c02ac6b0>] [<f8805000>] [<c0231e76>] [<c022a3c5>] [<c0231e76>]
[<c0224962>]
   [<c0231e76>] [<c0220f5c>] [<c02210a8>] [<c02321e4>] [<c02444ff>]
[<c0220f5c>]
   [<c02210a8>] [<c023d85c>] [<c023db31>] [<c0220f5c>] [<c02210a8>]
[<c0247b1c>]
   [<c0247e4b>] [<c024833f>] [<c022f5b8>] [<c022f955>] [<c01bf55a>]
[<c02251bb>]
   [<c0224eb2>] [<c0108d7e>] [<c0120e5b>] [<c0109189>] [<c0105220>]
[<c0105220>]
   [<c0107544>] [<c0105220>] [<c0105220>] [<c010524d>] [<c01052d2>]
[<c0105000>]
   [<c01001cf>]

Code: 8b 41 08 89 43 18 85 c0 74 09 8b 51 08 8d 43 18 89 42 1c 89
 <0>Kernel panic: Aiee, killing interrupt handler!
In interrupt handler - not syncing

====
ksymoops output

Code; c0247a34 <tcp_v4_syn_recv_sock+284/330>
00000000 <_EIP>:
Code; c0247a34 <tcp_v4_syn_recv_sock+284/330>
   0: 8b 41 08 mov 0x8(%ecx),%eax //panics in
child->bind_next=tb->owners
Code; c0247a37 <tcp_v4_syn_recv_sock+287/330>
   3: 89 43 18 mov %eax,0x18(%ebx)
Code; c0247a3a <tcp_v4_syn_recv_sock+28a/330>
   6: 85 c0 test %eax,%eax
Code; c0247a3c <tcp_v4_syn_recv_sock+28c/330>
   8: 74 09 je 13 <_EIP+0x13> c0247a47
<tcp_v4_syn_recv_sock+297/330>
Code; c0247a3e <tcp_v4_syn_recv_sock+28e/330>
   a: 8b 51 08 mov 0x8(%ecx),%edx
Code; c0247a41 <tcp_v4_syn_recv_sock+291/330>
   d: 8d 43 18 lea 0x18(%ebx),%eax
Code; c0247a44 <tcp_v4_syn_recv_sock+294/330>
  10: 89 42 1c mov %eax,0x1c(%edx)
Code; c0247a47 <tcp_v4_syn_recv_sock+297/330>
  13: 89 00 mov %eax,(%eax)

====
objdump -S

/usr/src/linux-2.4.5-ac4/include/asm/spinlock.h:104
c0247a21: f0 fe 0e lock decb (%esi)
c0247a24: 0f 88 85 79 03 00 js c027f3af
<stext_lock+0x5c6f>
/usr/src/linux-2.4.5-ac4/net/ipv4/tcp_ipv4.c:149
c0247a2a: 8b 54 24 14 mov 0x14(%esp,1),%edx
c0247a2e: 8b 8a a4 00 00 00 mov 0xa4(%edx),%ecx //tb =
sk->prev
/usr/src/linux-2.4.5-ac4/net/ipv4/tcp_ipv4.c:150
c0247a34: 8b 41 08 mov 0x8(%ecx),%eax //
child->bind_next=tb->owners
c0247a37: 89 43 18 mov %eax,0x18(%ebx)
c0247a3a: 85 c0 test %eax,%eax
c0247a3c: 74 09 je c0247a47
<tcp_v4_syn_recv_sock+0x297>
/usr/src/linux-2.4.5-ac4/net/ipv4/tcp_ipv4.c:151
c0247a3e: 8b 51 08 mov 0x8(%ecx),%edx
c0247a41: 8d 43 18 lea 0x18(%ebx),%eax
c0247a44: 89 42 1c mov %eax,0x1c(%edx)
/usr/src/linux-2.4.5-ac4/net/ipv4/tcp_ipv4.c:152
c0247a47: 89 59 08 mov %ebx,0x8(%ecx)
/usr/src/linux-2.4.5-ac4/net/ipv4/tcp_ipv4.c:153
c0247a4a: 8d 41 08 lea 0x8(%ecx),%eax
c0247a4d: 89 43 1c mov %eax,0x1c(%ebx)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Jul 07 2001 - 21:00:09 EST