netdev
[Top] [All Lists]

[PATCH][2.5.22] OOPS in tcp_v6_get_port

To: "David S. Miller" <davem@xxxxxxxxxx>
Subject: [PATCH][2.5.22] OOPS in tcp_v6_get_port
From: Carl Ritson <critson@xxxxxxxxxxxx>
Date: Mon, 17 Jun 2002 21:26:23 +0100 (BST)
Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxx>, Linux Kernel Mailing List <linux-kernel@xxxxxxxxxxxxxxx>, <netdev@xxxxxxxxxxx>
Sender: owner-netdev@xxxxxxxxxxx
Sorry for the repeat email but this bug is also in 2.5.22 and my patch is still
valid, although I'm not entirely sure it is the correct fix for the problem?

-- From Previous email --
2.5.21 and 2.5.22 OOPS at boot on my test machine, the decoded OOPS is attached.
Also attached is a program that triggers the bug, it emulates the behavior 
of bind on my test machine and binds to two ports one IPv4 and one IPv6 
with the same port number but different IP addresses.

The bug appears to be the IPv6 TCP code, in net/ipv6/tcp_ipv6.c
Line 149:
        struct ipv6_pinfo *np2 = inet6_sk(sk2);

        if (sk != sk2 &&
            sk->bound_dev_if == sk2->bound_dev_if) {
                if (!sk_reuse   ||
                    !sk2->reuse ||
                    sk2->state == TCP_LISTEN) {
                        /* NOTE: IPv6 tw bucket have different format */
                        if (!inet_sk(sk2)->rcv_saddr ||
                            addr_type == IPV6_ADDR_ANY ||
                            !ipv6_addr_cmp(&np->rcv_saddr,
                                        sk2->state != TCP_TIME_WAIT ?
BUG -->                                 &np2->rcv_saddr :
                                        &((struct 
tcp_tw_bucket*)sk)->v6_rcv_saddr) ||
                            (addr_type==IPV6_ADDR_MAPPED && 
sk2->family==AF_INET &&
                             inet_sk(sk)->rcv_saddr ==
                             inet_sk(sk2)->rcv_saddr))
                                break;
                        }
                }
        }

np2 can be NULL if the socket is an IPv4 socket, since IPv6 and IPv4 
share the port address space.  While the test of !inet_sk(sk2-)->rcv_addr 
_should_ prevent this it is not assured in C that the conditions to an if 
statement will be evaluated in the order written?  At least my gcc 
(2.95.4 from compiled from CVS) doesn't think so :-).

I propose a diff similar to the one below to fix the problem maybe?

Many thanks,
Carl Ritson
critson@xxxxxxxxxxxx

--- orig/net/ipv6/tcp_ipv6.c    Sat Jun 15 19:23:44 2002
+++ linux/net/ipv6/tcp_ipv6.c   Sat Jun 15 19:21:46 2002
@@ -156,14 +156,16 @@
                                                /* NOTE: IPv6 tw bucket have 
different format */
                                                if (!inet_sk(sk2)->rcv_saddr ||
                                                    addr_type == IPV6_ADDR_ANY 
||
-                                                   
!ipv6_addr_cmp(&np->rcv_saddr,
-                                                                  sk2->state 
!= TCP_TIME_WAIT ?
-                                                                  
&np2->rcv_saddr :
-                                                                  &((struct 
tcp_tw_bucket*)sk)->v6_rcv_saddr) ||
                                                    
(addr_type==IPV6_ADDR_MAPPED && sk2->family==AF_INET &&
                                                     inet_sk(sk)->rcv_saddr ==
                                                     inet_sk(sk2)->rcv_saddr))
                                                        break;
+                                               if (np2 != NULL) 
+                                                       if 
(!ipv6_addr_cmp(&np->rcv_saddr,
+                                                                  sk2->state 
!= TCP_TIME_WAIT ?
+                                                                  
&np2->rcv_saddr :
+                                                                  &((struct 
tcp_tw_bucket*)sk)->v6_rcv_saddr))
+                                                               break;
                                        }
                                }
                        }

Attachment: decoded-oops
Description: Text document

Attachment: ipv6-bind.c
Description: Text document

<Prev in Thread] Current Thread [Next in Thread>