[PATCH][2.5.22] OOPS in tcp_v6_get_port

From: Carl Ritson (critson@perlfu.co.uk)
Date: Mon Jun 17 2002 - 15:26:23 EST


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@perlfu.co.uk

--- 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;
                                         }
                                 }
                         }





-
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 : Sun Jun 23 2002 - 22:00:14 EST