lkml.org 
[lkml]   [2003]   [Sep]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
SubjectRe: oops in inet_bind/tcp_v4_get_port
From
In article <3F630C59.5090004@bigpond.com> (at Sat, 13 Sep 2003 22:23:53 +1000), James Harper <james.harper@bigpond.com> says:

> The crash is happening in net/ipv4/tcp_ipv4.c - tcp_bind_conflict (it's
> inline, which i guess is why it isn't in the oops trace, but it's called
> from tcp_v4_get_port), specifically in the call to the macro
> ipv6_only_sock. My guess is that while the sock says it's PF_INET6, it
> doesn't have the extra ipv6 stuff (specifically the pointer to
> ipv6_pinfo) so it's reading past the end of the structure, or that the
> stuff past the main sock struct is getting corrupted. I think the former
> is more likely but either possibility explains why I got a null pointer
> dereference one time, and the other oops the other time.

good point. please try this patch.

Index: linux-2.6/include/net/tcp.h
===================================================================
RCS file: /home/cvs/linux-2.5/include/net/tcp.h,v
retrieving revision 1.45
diff -u -r1.45 tcp.h
--- linux-2.6/include/net/tcp.h 10 Jul 2003 02:18:15 -0000 1.45
+++ linux-2.6/include/net/tcp.h 13 Sep 2003 11:36:32 -0000
@@ -219,6 +219,7 @@
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct in6_addr tw_v6_daddr;
struct in6_addr tw_v6_rcv_saddr;
+ u8 tw_v6_v6only;
#endif
};

@@ -285,6 +286,18 @@
extern void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo);
extern void tcp_tw_deschedule(struct tcp_tw_bucket *tw);

+/* Check if tcp socket is the "v6only" socket */
+int inline tcp6_only_sock(const struct sock *sk)
+{
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ if (sk->sk_state == TCP_TIME_WAIT)
+ return tcptw_sk(sk)->tw_v6_v6only;
+ else
+ return ipv6_only_sock(sk);
+#else
+ return 0;
+#endif
+}

/* Socket demux engine toys. */
#ifdef __BIG_ENDIAN
Index: linux-2.6/net/ipv4/tcp_ipv4.c
===================================================================
RCS file: /home/cvs/linux-2.5/net/ipv4/tcp_ipv4.c,v
retrieving revision 1.57
diff -u -r1.57 tcp_ipv4.c
--- linux-2.6/net/ipv4/tcp_ipv4.c 9 Sep 2003 23:24:51 -0000 1.57
+++ linux-2.6/net/ipv4/tcp_ipv4.c 13 Sep 2003 11:36:32 -0000
@@ -186,7 +186,7 @@

sk_for_each_bound(sk2, node, &tb->owners) {
if (sk != sk2 &&
- !ipv6_only_sock(sk2) &&
+ !tcp6_only_sock(sk2) &&
sk->sk_bound_dev_if == sk2->sk_bound_dev_if) {
if (!reuse || !sk2->sk_reuse ||
sk2->sk_state == TCP_LISTEN) {
@@ -418,7 +418,7 @@
sk_for_each(sk, node, head) {
struct inet_opt *inet = inet_sk(sk);

- if (inet->num == hnum && !ipv6_only_sock(sk)) {
+ if (inet->num == hnum && !tcp6_only_sock(sk)) {
__u32 rcv_saddr = inet->rcv_saddr;

score = (sk->sk_family == PF_INET ? 1 : 0);
@@ -457,7 +457,7 @@

if (inet->num == hnum && !sk->sk_node.next &&
(!inet->rcv_saddr || inet->rcv_saddr == daddr) &&
- (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
+ (sk->sk_family == PF_INET || !tcp6_only_sock(sk)) &&
!sk->sk_bound_dev_if)
goto sherry_cache;
sk = __tcp_v4_lookup_listener(head, daddr, hnum, dif);
Index: linux-2.6/net/ipv4/tcp_minisocks.c
===================================================================
RCS file: /home/cvs/linux-2.5/net/ipv4/tcp_minisocks.c,v
retrieving revision 1.40
diff -u -r1.40 tcp_minisocks.c
--- linux-2.6/net/ipv4/tcp_minisocks.c 27 Jun 2003 16:44:43 -0000 1.40
+++ linux-2.6/net/ipv4/tcp_minisocks.c 13 Sep 2003 11:36:32 -0000
@@ -367,7 +367,9 @@

ipv6_addr_copy(&tw->tw_v6_daddr, &np->daddr);
ipv6_addr_copy(&tw->tw_v6_rcv_saddr, &np->rcv_saddr);
- }
+ tw->tw_v6_v6only = np->ipv6only;
+ } else
+ tw->tw_v6_v6only = 0;
#endif
/* Linkage updates. */
__tcp_tw_hashdance(sk, tw);
Index: linux-2.6/net/ipv6/addrconf.c
===================================================================
RCS file: /home/cvs/linux-2.5/net/ipv6/addrconf.c,v
retrieving revision 1.53
diff -u -r1.53 addrconf.c
--- linux-2.6/net/ipv6/addrconf.c 9 Sep 2003 23:24:51 -0000 1.53
+++ linux-2.6/net/ipv6/addrconf.c 13 Sep 2003 11:36:32 -0000
@@ -968,16 +968,16 @@
struct ipv6_pinfo *np = inet6_sk(sk);
int addr_type = ipv6_addr_type(&np->rcv_saddr);

- if (!inet_sk(sk2)->rcv_saddr && !ipv6_only_sock(sk))
+ if (!inet_sk(sk2)->rcv_saddr && !tcp6_only_sock(sk))
return 1;

if (sk2->sk_family == AF_INET6 &&
ipv6_addr_any(&inet6_sk(sk2)->rcv_saddr) &&
- !(ipv6_only_sock(sk2) && addr_type == IPV6_ADDR_MAPPED))
+ !(tcp6_only_sock(sk2) && addr_type == IPV6_ADDR_MAPPED))
return 1;

if (addr_type == IPV6_ADDR_ANY &&
- (!ipv6_only_sock(sk) ||
+ (!tcp6_only_sock(sk) ||
!(sk2->sk_family == AF_INET6 ?
(ipv6_addr_type(&inet6_sk(sk2)->rcv_saddr) == IPV6_ADDR_MAPPED) :
1)))
@@ -991,7 +991,7 @@
return 1;

if (addr_type == IPV6_ADDR_MAPPED &&
- !ipv6_only_sock(sk2) &&
+ !tcp6_only_sock(sk2) &&
(!inet_sk(sk2)->rcv_saddr ||
!inet_sk(sk)->rcv_saddr ||
inet_sk(sk)->rcv_saddr == inet_sk(sk2)->rcv_saddr))
--
Hideaki YOSHIFUJI @ USAGI Project <yoshfuji@linux-ipv6.org>
GPG FP: 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA
-
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/

\
 
 \ /
  Last update: 2005-03-22 13:48    [W:0.053 / U:0.116 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site