netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH][2.5.22] OOPS in tcp_v6_get_port
@ 2002-06-17 20:26 Carl Ritson
  2002-06-17 21:33 ` David S. Miller
                   ` (2 more replies)
  0 siblings, 3 replies; 19+ messages in thread
From: Carl Ritson @ 2002-06-17 20:26 UTC (permalink / raw)
  To: David S. Miller; +Cc: Linus Torvalds, Linux Kernel Mailing List, netdev

[-- Attachment #1: Type: TEXT/PLAIN, Size: 2454 bytes --]


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


[-- Attachment #2: Type: TEXT/PLAIN, Size: 2217 bytes --]

ksymoops 2.4.4 on i686 2.4.19-pre8-ac2.  Options used
     -v /usr/src/linux-2.5.21/vmlinux (specified)
     -K (specified)
     -L (specified)
     -o /lib/modules/2.5.21/ (specified)
     -m /boot/System.map-2.5.21 (specified)

No modules in ksyms, skipping objects
Unable to handle kernel NULL pointer dereference at virtual address 00000010
c027244e
*pde = 00000000
Oops: 0000
CPU:    0
EIP:    0010:[<c027244e>]  Not tainted
Using defaults from ksymoops -t elf32-i386 -a i386
EFLAGS: 00010246
eax: cfd68b28   ebx: cea60360     ecx: 00000010       edx: cfd68a0a
esi: cfd68de8   edi: 00000010     ebp: cf9cf260       esp: ce8a7e98
ds: 0018   es: 0018   ss: 0018
Stack:  ce8a7f1c cfd68ac0 cfd68de8 c0341908 cfd68de8 0100007f 00000011 00000001
        cfd68ac0 cfd21dc8 03b93874 c0260f81 cfd68ac0 000003b9 ce8a7a40 ce8a7f14
        0000001c 40263874 00000011 03b919c8 0600007f cfd68dd8 cfd68bf8 c02227c0
Call Trace: [<c0260f81>] [<c02227c0>] [c0223629>] [<c0221cf5>] [<c0222d2e>]
   [<c0222d50>] [<c02232a0>] [<c0106a17>]
Code: f3 a6 74 2c 81 7c 24 18 00 10 00 00 75 17 66 83 7b 1c 02 75

>>EIP; c027244e <tcp_v6_get_port+1ae/2d4>   <=====
Trace; c0260f81 <inet6_bind+2b1/3d8>
Trace; c02227c0 <sys_bind+54/74>
Trace; c0222d50 <sys_setsockopt+6c/78>
Trace; c02232a0 <sys_socketcall+74/1fc>
Trace; c0106a17 <syscall_call+7/b>
Code;  c027244e <tcp_v6_get_port+1ae/2d4>
00000000 <_EIP>:
Code;  c027244e <tcp_v6_get_port+1ae/2d4>   <=====
   0:   f3 a6                     repz cmpsb %es:(%edi),%ds:(%esi)   <=====
Code;  c0272450 <tcp_v6_get_port+1b0/2d4>
   2:   74 2c                     je     30 <_EIP+0x30> c027247e <tcp_v6_get_port+1de/2d4>
Code;  c0272452 <tcp_v6_get_port+1b2/2d4>
   4:   81 7c 24 18 00 10 00      cmpl   $0x1000,0x18(%esp,1)
Code;  c0272459 <tcp_v6_get_port+1b9/2d4>
   b:   00 
Code;  c027245a <tcp_v6_get_port+1ba/2d4>
   c:   75 17                     jne    25 <_EIP+0x25> c0272473 <tcp_v6_get_port+1d3/2d4>
Code;  c027245c <tcp_v6_get_port+1bc/2d4>
   e:   66 83 7b 1c 02            cmpw   $0x2,0x1c(%ebx)
Code;  c0272461 <tcp_v6_get_port+1c1/2d4>
  13:   75 00                     jne    15 <_EIP+0x15> c0272463 <tcp_v6_get_port+1c3/2d4>


[-- Attachment #3: Type: TEXT/PLAIN, Size: 1593 bytes --]

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

const unsigned short bind_port = 4500;

int do_ipv4_bind(char *ip, const unsigned short port) {
	struct sockaddr_in addr;
	int sock;
	int ret;
	
	memset(&addr, 0x00, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	inet_pton(AF_INET, ip, &(addr.sin_addr));
	
	ret = socket(PF_INET, SOCK_STREAM, 0);
	if(ret == -1) {
		return ret;
	} else {
		sock = ret;
	}
	ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
	if(ret == -1) {
		return ret;
	} else {
		return sock;
	}
}

int do_ipv6_bind(char *ip, const unsigned short port) {
	struct sockaddr_in6 addr;
	int sock;
	int ret;
	
	memset(&addr, 0x00, sizeof(addr));
	addr.sin6_family = AF_INET6;
	addr.sin6_port = htons(port);
	inet_pton(AF_INET6, ip, &(addr.sin6_addr));
	
	ret = socket(PF_INET6, SOCK_STREAM, 0);
	if(ret == -1) {
		return ret;
	} else {
		sock = ret;
	}

	ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
	if(ret == -1) {
		return ret;
	} else {
		return sock;
	}
}

int main(void) {
	int ipv4_sock = 0;
	int ipv6_sock = 0;
	ipv4_sock = do_ipv4_bind("127.0.0.1", bind_port);
	ipv6_sock = do_ipv6_bind("::1", bind_port);
	if(ipv4_sock < 0) {
		printf("ipv4 bind failed\n");
	} else {
		printf("ipv4 bind succeeded\n");
		close(ipv4_sock);
	}
	if(ipv6_sock < 0) {
		printf("ipv6 bind failed\n");
	} else {
		printf("ipv6 bind succeeded\n");
		close(ipv6_sock);
	}
	return 0;
}

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2002-06-19  9:54 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-06-17 20:26 [PATCH][2.5.22] OOPS in tcp_v6_get_port Carl Ritson
2002-06-17 21:33 ` David S. Miller
     [not found] ` <20020617.143319.54623892.davem@redhat.com>
2002-06-18  0:57   ` Arnaldo Carvalho de Melo
2002-06-18  2:17     ` David S. Miller
     [not found]     ` <20020617.191726.55300824.davem@redhat.com>
2002-06-18  2:49       ` Arnaldo Carvalho de Melo
2002-06-18  3:58         ` [BKPATCH] " Arnaldo Carvalho de Melo
     [not found]         ` <20020618035804.GA18759@conectiva.com.br>
2002-06-18  4:15           ` Arnaldo Carvalho de Melo
     [not found]           ` <20020618041539.GB18759@conectiva.com.br>
2002-06-18  4:17             ` David S. Miller
2002-06-18  7:38     ` Carl Ritson
2002-06-18  9:43   ` kuznet
2002-06-18  9:58     ` David S. Miller
2002-06-19  9:54       ` Arnaldo Carvalho de Melo
2002-06-18 11:51 ` net/ipv6/exthdrs.c Andras Kis-Szabo
2002-06-18 12:00   ` net/ipv6/exthdrs.c Pekka Savola
2002-06-18 13:50     ` net/ipv6/exthdrs.c Andras Kis-Szabo
2002-06-18 14:00       ` [PATCH] net/ipv6/exthdrs.c Andras Kis-Szabo
2002-06-18 19:03   ` net/ipv6/exthdrs.c kuznet
     [not found]     ` <1024435482.1332.10.camel@arwen>
2002-06-19  9:30       ` net/ipv6/exthdrs.c Kis-Szabo Andras
2002-06-19  9:42         ` net/ipv6/exthdrs.c kuznet

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).