netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* ipv6 UDP MSG_MORE oops fix
@ 2003-08-08  5:34 David S. Miller
  2003-08-08  8:08 ` YOSHIFUJI Hideaki / 吉藤英明
  0 siblings, 1 reply; 7+ messages in thread
From: David S. Miller @ 2003-08-08  5:34 UTC (permalink / raw)
  To: yoshfuji; +Cc: kuznet, netdev


Yoshfuji-san, I found the MSG_MORE udp bug.

If "np->pending" is true, we call ip_dst_store() with uninitialized
dst, it could be any kind of garbage.  This is dereferenced and we
crash.

If np->pending, we have some 'dst' stored into the socket already.
So no need to relookup dst or anything like that.

This is the fix I am using, on top of Miyazawa-san's ah6_input
and authentication error patches.

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.1167  -> 1.1168 
#	net/ipv6/ip6_output.c	1.40    -> 1.41   
#	      net/ipv6/raw.c	1.38    -> 1.39   
#	      net/ipv6/udp.c	1.45    -> 1.46   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/08/07	davem@nuts.ninka.net	1.1168
# [IPV6]: Make sure errors propagate properly in {udp,raw} sendmsg.
# --------------------------------------------
#
diff -Nru a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
--- a/net/ipv6/ip6_output.c	Thu Aug  7 22:34:06 2003
+++ b/net/ipv6/ip6_output.c	Thu Aug  7 22:34:06 2003
@@ -209,7 +209,6 @@
 	int seg_len = skb->len;
 	int hlimit;
 	u32 mtu;
-	int err = 0;
 
 	if (opt) {
 		int head_room;
diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c	Thu Aug  7 22:34:06 2003
+++ b/net/ipv6/raw.c	Thu Aug  7 22:34:06 2003
@@ -659,7 +659,7 @@
 		fl.oif = np->mcast_oif;
 
 	dst = ip6_dst_lookup(sk, &fl);
-	if (dst->error)
+	if ((err = dst->error))
 		goto out;
 
 	if (hlimit < 0) {
diff -Nru a/net/ipv6/udp.c b/net/ipv6/udp.c
--- a/net/ipv6/udp.c	Thu Aug  7 22:34:06 2003
+++ b/net/ipv6/udp.c	Thu Aug  7 22:34:06 2003
@@ -811,8 +811,10 @@
 		 * The socket lock must be held while it's corked.
 		 */
 		lock_sock(sk);
-		if (likely(up->pending))
+		if (likely(up->pending)) {
+			dst = NULL;
 			goto do_append_data;
+		}
 		release_sock(sk);
 	}
 	ulen += sizeof(struct udphdr);
@@ -929,7 +931,7 @@
 		fl.oif = np->mcast_oif;
 
 	dst = ip6_dst_lookup(sk, &fl);
-	if (dst->error)
+	if ((err = dst->error))
 		goto out;
 
 	if (hlimit < 0) {
@@ -968,9 +970,10 @@
 	else if (!corkreq)
 		err = udp_v6_push_pending_frames(sk, up);
 
-	ip6_dst_store(sk, dst,
-		      !ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ?
-		      &np->daddr : NULL);
+	if (dst)
+		ip6_dst_store(sk, dst,
+			      !ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ?
+			      &np->daddr : NULL);
 	if (err > 0)
 		err = np->recverr ? net_xmit_errno(err) : 0;
 	release_sock(sk);

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

* Re: ipv6 UDP MSG_MORE oops fix
  2003-08-08  5:34 ipv6 UDP MSG_MORE oops fix David S. Miller
@ 2003-08-08  8:08 ` YOSHIFUJI Hideaki / 吉藤英明
  2003-10-26  9:50   ` YOSHIFUJI Hideaki / 吉藤英明
  0 siblings, 1 reply; 7+ messages in thread
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2003-08-08  8:08 UTC (permalink / raw)
  To: davem; +Cc: kuznet, netdev, yoshfuji

In article <20030807223421.70497d61.davem@redhat.com> (at Thu, 7 Aug 2003 22:34:21 -0700), "David S. Miller" <davem@redhat.com> says:

> Yoshfuji-san, I found the MSG_MORE udp bug.

Yes, thanks. This is what I told you before.
I'm going to test if problems go away with this patch.

--yoshfuji

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

* Re: ipv6 UDP MSG_MORE oops fix
  2003-08-08  8:08 ` YOSHIFUJI Hideaki / 吉藤英明
@ 2003-10-26  9:50   ` YOSHIFUJI Hideaki / 吉藤英明
  2003-10-26  9:54     ` [PATCH 1/3] IPv6: Fix odd IPv6 header in UDPv6 packets when sending MSG_MORE flag YOSHIFUJI Hideaki / 吉藤英明
                       ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2003-10-26  9:50 UTC (permalink / raw)
  To: davem; +Cc: kuznet, netdev, yoshfuji, miyazawa

Hello.

This thread would be too old but anyway...

In article <20030808.170839.90822982.yoshfuji@linux-ipv6.org> (at Fri, 08 Aug 2003 17:08:39 +0900 (JST)), YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org> says:

> In article <20030807223421.70497d61.davem@redhat.com> (at Thu, 7 Aug 2003 22:34:21 -0700), "David S. Miller" <davem@redhat.com> says:
> 
> > Yoshfuji-san, I found the MSG_MORE udp bug.
> 
> Yes, thanks. This is what I told you before.
> I'm going to test if problems go away with this patch.

This fixes oops, but there remains several issues.
I'm about to send 3 patches to fix them.

[1/3] IPv6: Odd IPv6 header in UDPv6 packets when sending MSG_MORE flag
[2/3] NET: store cork'ing flow information in common storage in inet_opt
[3/3] IPv6: breakage of sendmsg to IPv4-mapped address via UDPv6 socket

Thanks in advance.

-- 
Hideaki YOSHIFUJI @ USAGI Project <yoshfuji@linux-ipv6.org>
GPG FP: 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA

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

* [PATCH 1/3] IPv6: Fix odd IPv6 header in UDPv6 packets when sending MSG_MORE flag
  2003-10-26  9:50   ` YOSHIFUJI Hideaki / 吉藤英明
@ 2003-10-26  9:54     ` YOSHIFUJI Hideaki / 吉藤英明
  2003-10-26  9:54     ` [PATCH 2/3] NET: store cork'ing flow information in common storage YOSHIFUJI Hideaki / 吉藤英明
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2003-10-26  9:54 UTC (permalink / raw)
  To: davem; +Cc: netdev, miyazawa, yoshfuji

Hello.

> I'm about to send 3 patches to fix them.
>
> [1/3] IPv6: Odd IPv6 header in UDPv6 packets when sending MSG_MORE flag
> [2/3] NET: store cork'ing flow information in common storage in inet_opt
> [3/3] IPv6: breakage of sendmsg to IPv4-mapped address via UDPv6 socket

[1/3] IPv6: Odd IPv6 header in UDPv6 packets when sending MSG_MORE flag

D: Broken IPv6 header for UDPv6 was generated with MSG_MORE flag.
D: Remember cork'ed flow information in real storage.

===== include/linux/ipv6.h 1.12 vs edited =====
--- 1.12/include/linux/ipv6.h	Sat Sep 13 09:25:13 2003
+++ edited/include/linux/ipv6.h	Sun Oct 26 14:56:16 2003
@@ -174,6 +174,7 @@
 #include <net/if_inet6.h>       /* struct ipv6_mc_socklist */
 #include <linux/tcp.h>
 #include <linux/udp.h>
+#include <net/flow.h>
 
 /* 
    This structure contains results of exthdrs parsing
@@ -234,7 +235,7 @@
 	struct {
 		struct ipv6_txoptions *opt;
 		struct rt6_info	*rt;
-		struct flowi *fl;
+		struct flowi fl;
 		int hop_limit;
 	} cork;
 };
===== net/ipv6/ip6_output.c 1.44 vs edited =====
--- 1.44/net/ipv6/ip6_output.c	Mon Sep  1 17:44:26 2003
+++ edited/net/ipv6/ip6_output.c	Sun Oct 26 14:56:16 2003
@@ -1239,7 +1239,7 @@
 		}
 		dst_hold(&rt->u.dst);
 		np->cork.rt = rt;
-		np->cork.fl = fl;
+		np->cork.fl = *fl;
 		np->cork.hop_limit = hlimit;
 		inet->cork.fragsize = mtu = dst_pmtu(&rt->u.dst);
 		inet->cork.length = 0;
@@ -1423,7 +1423,7 @@
 	struct ipv6hdr *hdr;
 	struct ipv6_txoptions *opt = np->cork.opt;
 	struct rt6_info *rt = np->cork.rt;
-	struct flowi *fl = np->cork.fl;
+	struct flowi *fl = &np->cork.fl;
 	unsigned char proto = fl->proto;
 	int err = 0;
 
@@ -1487,9 +1487,7 @@
 		dst_release(&np->cork.rt->u.dst);
 		np->cork.rt = NULL;
 	}
-	if (np->cork.fl) {
-		np->cork.fl = NULL;
-	}
+	memset(&np->cork.fl, 0, sizeof(np->cork.fl));
 	return err;
 error:
 	goto out;
@@ -1514,7 +1512,5 @@
 		dst_release(&np->cork.rt->u.dst);
 		np->cork.rt = NULL;
 	}
-	if (np->cork.fl) {
-		np->cork.fl = NULL;
-	}
+	memset(&np->cork.fl, 0, sizeof(np->cork.fl));
 }
===== net/ipv6/udp.c 1.50 vs edited =====
--- 1.50/net/ipv6/udp.c	Thu Oct  9 00:27:40 2003
+++ edited/net/ipv6/udp.c	Sun Oct 26 14:56:16 2003
@@ -721,7 +721,7 @@
 	struct sk_buff *skb;
 	struct udphdr *uh;
 	struct ipv6_pinfo *np = inet6_sk(sk);
-	struct flowi *fl = np->cork.fl;
+	struct flowi *fl = &np->cork.fl;
 	int err = 0;
 
 	/* Grab the skbuff where UDP header space exists. */
@@ -783,7 +783,7 @@
 	struct in6_addr *daddr;
 	struct ipv6_txoptions *opt = NULL;
 	struct ip6_flowlabel *flowlabel = NULL;
-	struct flowi fl;
+	struct flowi *fl = &np->cork.fl;
 	struct dst_entry *dst;
 	int addr_len = msg->msg_namelen;
 	int ulen = len;
@@ -812,7 +812,7 @@
 	}
 	ulen += sizeof(struct udphdr);
 
-	memset(&fl, 0, sizeof(fl));
+	memset(fl, 0, sizeof(*fl));
 
 	if (sin6) {
 		if (sin6->sin6_family == AF_INET) {
@@ -834,9 +834,9 @@
 		daddr = &sin6->sin6_addr;
 
 		if (np->sndflow) {
-			fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK;
-			if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) {
-				flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
+			fl->fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK;
+			if (fl->fl6_flowlabel&IPV6_FLOWLABEL_MASK) {
+				flowlabel = fl6_sock_lookup(sk, fl->fl6_flowlabel);
 				if (flowlabel == NULL)
 					return -EINVAL;
 				daddr = &flowlabel->dst;
@@ -854,14 +854,14 @@
 		if (addr_len >= sizeof(struct sockaddr_in6) &&
 		    sin6->sin6_scope_id &&
 		    ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL)
-			fl.oif = sin6->sin6_scope_id;
+			fl->oif = sin6->sin6_scope_id;
 	} else {
 		if (sk->sk_state != TCP_ESTABLISHED)
 			return -EDESTADDRREQ;
 
 		up->dport = inet->dport;
 		daddr = &np->daddr;
-		fl.fl6_flowlabel = np->flow_label;
+		fl->fl6_flowlabel = np->flow_label;
 	}
 
 	addr_type = ipv6_addr_type(daddr);
@@ -882,20 +882,20 @@
 		return udp_sendmsg(iocb, sk, msg, len);
 	}
 
-	if (!fl.oif)
-		fl.oif = sk->sk_bound_dev_if;
+	if (!fl->oif)
+		fl->oif = sk->sk_bound_dev_if;
 
 	if (msg->msg_controllen) {
 		opt = &opt_space;
 		memset(opt, 0, sizeof(struct ipv6_txoptions));
 
-		err = datagram_send_ctl(msg, &fl, opt, &hlimit);
+		err = datagram_send_ctl(msg, fl, opt, &hlimit);
 		if (err < 0) {
 			fl6_sock_release(flowlabel);
 			return err;
 		}
-		if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) {
-			flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
+		if ((fl->fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) {
+			flowlabel = fl6_sock_lookup(sk, fl->fl6_flowlabel);
 			if (flowlabel == NULL)
 				return -EINVAL;
 		}
@@ -907,28 +907,28 @@
 	if (flowlabel)
 		opt = fl6_merge_options(&opt_space, flowlabel, opt);
 
-	fl.proto = IPPROTO_UDP;
-	ipv6_addr_copy(&fl.fl6_dst, daddr);
-	if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
-		ipv6_addr_copy(&fl.fl6_src, &np->saddr);
-	fl.fl_ip_dport = up->dport;
-	fl.fl_ip_sport = inet->sport;
+	fl->proto = IPPROTO_UDP;
+	ipv6_addr_copy(&fl->fl6_dst, daddr);
+	if (ipv6_addr_any(&fl->fl6_src) && !ipv6_addr_any(&np->saddr))
+		ipv6_addr_copy(&fl->fl6_src, &np->saddr);
+	fl->fl_ip_dport = up->dport;
+	fl->fl_ip_sport = inet->sport;
 	
 	/* merge ip6_build_xmit from ip6_output */
 	if (opt && opt->srcrt) {
 		struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+		ipv6_addr_copy(&fl->fl6_dst, rt0->addr);
 	}
 
-	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
-		fl.oif = np->mcast_oif;
+	if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst))
+		fl->oif = np->mcast_oif;
 
-	err = ip6_dst_lookup(sk, &dst, &fl);
+	err = ip6_dst_lookup(sk, &dst, fl);
 	if (err)
 		goto out;
 
 	if (hlimit < 0) {
-		if (ipv6_addr_is_multicast(&fl.fl6_dst))
+		if (ipv6_addr_is_multicast(&fl->fl6_dst))
 			hlimit = np->mcast_hops;
 		else
 			hlimit = np->hop_limit;
@@ -956,7 +956,7 @@
 do_append_data:
 	up->len += ulen;
 	err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, sizeof(struct udphdr),
-			      hlimit, opt, &fl, (struct rt6_info*)dst,
+			      hlimit, opt, fl, (struct rt6_info*)dst,
 			      corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
 	if (err)
 		udp_v6_flush_pending_frames(sk);
@@ -965,7 +965,7 @@
 
 	if (dst)
 		ip6_dst_store(sk, dst,
-			      !ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ?
+			      !ipv6_addr_cmp(&fl->fl6_dst, &np->daddr) ?
 			      &np->daddr : NULL);
 	if (err > 0)
 		err = np->recverr ? net_xmit_errno(err) : 0;

-- 
Hideaki YOSHIFUJI @ USAGI Project <yoshfuji@linux-ipv6.org>
GPG FP: 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA

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

* [PATCH 2/3] NET: store cork'ing flow information in common storage
  2003-10-26  9:50   ` YOSHIFUJI Hideaki / 吉藤英明
  2003-10-26  9:54     ` [PATCH 1/3] IPv6: Fix odd IPv6 header in UDPv6 packets when sending MSG_MORE flag YOSHIFUJI Hideaki / 吉藤英明
@ 2003-10-26  9:54     ` YOSHIFUJI Hideaki / 吉藤英明
  2003-10-26  9:54     ` [PATCH 3/3] IPv6: breakage of sendmsg to IPv4-mapped address via UDPv6 socket YOSHIFUJI Hideaki / 吉藤英明
  2003-10-27  7:56     ` ipv6 UDP MSG_MORE oops fix David S. Miller
  3 siblings, 0 replies; 7+ messages in thread
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2003-10-26  9:54 UTC (permalink / raw)
  To: davem; +Cc: netdev, miyazawa, yoshfuji

Hello.

> I'm about to send 3 patches to fix them.
>
> [1/3] IPv6: Odd IPv6 header in UDPv6 packets when sending MSG_MORE flag
> [2/3] NET: store cork'ing flow information in common storage in inet_opt
> [3/3] IPv6: breakage of sendmsg to IPv4-mapped address via UDPv6 socket

[2/3] NET: store cork'ing flow information in common storage in inet_opt.

--- linux-2.5-net/include/linux/ip.h	Sun Oct 19 01:10:46 2003
+++ linux-2.5-udp6_append_data/include/linux/ip.h	Sun Oct 26 16:19:58 2003
@@ -83,6 +83,7 @@
 #include <linux/types.h>
 #include <net/sock.h>
 #include <linux/igmp.h>
+#include <net/flow.h>
 
 struct ip_options {
   __u32		faddr;				/* Saved first hop address */
@@ -141,6 +142,7 @@
 		struct rtable		*rt;
 		int			length; /* Total length of all frames */
 		u32			addr;
+		struct flowi		fl;
 	} cork;
 };
 
--- linux-2.5-net/include/linux/ipv6.h	Sun Oct 26 16:19:19 2003
+++ linux-2.5-udp6_append_data/include/linux/ipv6.h	Sun Oct 26 16:19:58 2003
@@ -174,7 +174,6 @@
 #include <net/if_inet6.h>       /* struct ipv6_mc_socklist */
 #include <linux/tcp.h>
 #include <linux/udp.h>
-#include <net/flow.h>
 
 /* 
    This structure contains results of exthdrs parsing
@@ -235,7 +234,6 @@
 	struct {
 		struct ipv6_txoptions *opt;
 		struct rt6_info	*rt;
-		struct flowi fl;
 		int hop_limit;
 	} cork;
 };
--- linux-2.5-net/include/linux/udp.h	Sun Oct 19 01:10:47 2003
+++ linux-2.5-udp6_append_data/include/linux/udp.h	Sun Oct 26 16:20:00 2003
@@ -44,13 +44,9 @@
 	unsigned int	corkflag;	/* Cork is required */
   	__u16		encap_type;	/* Is this an Encapsulation socket? */
 	/*
-	 * Following members retains the infomation to create a UDP header
+	 * Following member retains the infomation to create a UDP header
 	 * when the socket is uncorked.
 	 */
-	u32		saddr;		/* source address */
-	u32		daddr;		/* destination address */
-	__u16		sport;		/* source port */
-	__u16		dport;		/* destination port */
 	__u16		len;		/* total length of pending frames */
 };
 
--- linux-2.5-net/net/ipv4/udp.c	Sun Oct 19 01:10:53 2003
+++ linux-2.5-udp6_append_data/net/ipv4/udp.c	Sun Oct 26 16:20:04 2003
@@ -398,6 +398,8 @@
  */
 static int udp_push_pending_frames(struct sock *sk, struct udp_opt *up)
 {
+	struct inet_opt *inet = inet_sk(sk);
+	struct flowi *fl = &inet->cork.fl;
 	struct sk_buff *skb;
 	struct udphdr *uh;
 	int err = 0;
@@ -410,8 +412,8 @@
 	 * Create a UDP header
 	 */
 	uh = skb->h.uh;
-	uh->source = up->sport;
-	uh->dest = up->dport;
+	uh->source = fl->fl_ip_sport;
+	uh->dest = fl->fl_ip_dport;
 	uh->len = htons(up->len);
 	uh->check = 0;
 
@@ -426,12 +428,12 @@
 		 */
 		if (skb->ip_summed == CHECKSUM_HW) {
 			skb->csum = offsetof(struct udphdr, check);
-			uh->check = ~csum_tcpudp_magic(up->saddr, up->daddr,
+			uh->check = ~csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst,
 					up->len, IPPROTO_UDP, 0);
 		} else {
 			skb->csum = csum_partial((char *)uh,
 					sizeof(struct udphdr), skb->csum);
-			uh->check = csum_tcpudp_magic(up->saddr, up->daddr,
+			uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst,
 					up->len, IPPROTO_UDP, skb->csum);
 			if (uh->check == 0)
 				uh->check = -1;
@@ -456,7 +458,7 @@
 		skb_queue_walk(&sk->sk_write_queue, skb) {
 			csum = csum_add(csum, skb->csum);
 		}
-		uh->check = csum_tcpudp_magic(up->saddr, up->daddr,
+		uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst,
 				up->len, IPPROTO_UDP, csum);
 		if (uh->check == 0)
 			uh->check = -1;
@@ -636,10 +638,10 @@
 	/*
 	 *	Now cork the socket to pend data.
 	 */
-	up->daddr = daddr;
-	up->dport = dport;
-	up->saddr = saddr;
-	up->sport = inet->sport;
+	inet->cork.fl.fl4_dst = daddr;
+	inet->cork.fl.fl_ip_dport = dport;
+	inet->cork.fl.fl4_src = saddr;
+	inet->cork.fl.fl_ip_sport = inet->sport;
 	up->pending = 1;
 
 do_append_data:
--- linux-2.5-net/net/ipv6/udp.c	Sun Oct 26 16:19:19 2003
+++ linux-2.5-udp6_append_data/net/ipv6/udp.c	Sun Oct 26 16:20:00 2003
@@ -720,8 +720,8 @@
 {
 	struct sk_buff *skb;
 	struct udphdr *uh;
-	struct ipv6_pinfo *np = inet6_sk(sk);
-	struct flowi *fl = &np->cork.fl;
+	struct inet_opt *inet = inet_sk(sk);
+	struct flowi *fl = &inet->cork.fl;
 	int err = 0;
 
 	/* Grab the skbuff where UDP header space exists. */
@@ -783,7 +783,7 @@
 	struct in6_addr *daddr;
 	struct ipv6_txoptions *opt = NULL;
 	struct ip6_flowlabel *flowlabel = NULL;
-	struct flowi *fl = &np->cork.fl;
+	struct flowi *fl = &inet->cork.fl;
 	struct dst_entry *dst;
 	int addr_len = msg->msg_namelen;
 	int ulen = len;
@@ -830,7 +830,7 @@
 		if (sin6->sin6_port == 0)
 			return -EINVAL;
 
-		up->dport = sin6->sin6_port;
+		fl->fl_ip_dport = sin6->sin6_port;
 		daddr = &sin6->sin6_addr;
 
 		if (np->sndflow) {
@@ -859,7 +859,7 @@
 		if (sk->sk_state != TCP_ESTABLISHED)
 			return -EDESTADDRREQ;
 
-		up->dport = inet->dport;
+		fl->fl_ip_dport = inet->dport;
 		daddr = &np->daddr;
 		fl->fl6_flowlabel = np->flow_label;
 	}
@@ -874,7 +874,7 @@
 
 		sin.sin_family = AF_INET;
 		sin.sin_addr.s_addr = daddr->s6_addr32[3];
-		sin.sin_port = up->dport;
+		sin.sin_port = inet->cork.fl.fl_ip_dport;
 		msg->msg_name = (struct sockaddr *)(&sin);
 		msg->msg_namelen = sizeof(sin);
 		fl6_sock_release(flowlabel);
@@ -911,7 +911,6 @@
 	ipv6_addr_copy(&fl->fl6_dst, daddr);
 	if (ipv6_addr_any(&fl->fl6_src) && !ipv6_addr_any(&np->saddr))
 		ipv6_addr_copy(&fl->fl6_src, &np->saddr);
-	fl->fl_ip_dport = up->dport;
 	fl->fl_ip_sport = inet->sport;
 	
 	/* merge ip6_build_xmit from ip6_output */
--- linux-2.5-net/net/ipv6/ip6_output.c	Sun Oct 26 16:19:19 2003
+++ linux-2.5-udp6_append_data/net/ipv6/ip6_output.c	Sun Oct 26 16:20:00 2003
@@ -1239,7 +1239,7 @@
 		}
 		dst_hold(&rt->u.dst);
 		np->cork.rt = rt;
-		np->cork.fl = *fl;
+		inet->cork.fl = *fl;
 		np->cork.hop_limit = hlimit;
 		inet->cork.fragsize = mtu = dst_pmtu(&rt->u.dst);
 		inet->cork.length = 0;
@@ -1250,6 +1250,7 @@
 		transhdrlen += exthdrlen;
 	} else {
 		rt = np->cork.rt;
+		fl = &inet->cork.fl;
 		if (inet->cork.flags & IPCORK_OPT)
 			opt = np->cork.opt;
 		transhdrlen = 0;
@@ -1423,7 +1424,7 @@
 	struct ipv6hdr *hdr;
 	struct ipv6_txoptions *opt = np->cork.opt;
 	struct rt6_info *rt = np->cork.rt;
-	struct flowi *fl = &np->cork.fl;
+	struct flowi *fl = &inet->cork.fl;
 	unsigned char proto = fl->proto;
 	int err = 0;
 
@@ -1487,7 +1488,7 @@
 		dst_release(&np->cork.rt->u.dst);
 		np->cork.rt = NULL;
 	}
-	memset(&np->cork.fl, 0, sizeof(np->cork.fl));
+	memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
 	return err;
 error:
 	goto out;
@@ -1512,5 +1513,5 @@
 		dst_release(&np->cork.rt->u.dst);
 		np->cork.rt = NULL;
 	}
-	memset(&np->cork.fl, 0, sizeof(np->cork.fl));
+	memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
 }

-- 
Hideaki YOSHIFUJI @ USAGI Project <yoshfuji@linux-ipv6.org>
GPG FP: 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA

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

* [PATCH 3/3] IPv6: breakage of sendmsg to IPv4-mapped address via UDPv6 socket
  2003-10-26  9:50   ` YOSHIFUJI Hideaki / 吉藤英明
  2003-10-26  9:54     ` [PATCH 1/3] IPv6: Fix odd IPv6 header in UDPv6 packets when sending MSG_MORE flag YOSHIFUJI Hideaki / 吉藤英明
  2003-10-26  9:54     ` [PATCH 2/3] NET: store cork'ing flow information in common storage YOSHIFUJI Hideaki / 吉藤英明
@ 2003-10-26  9:54     ` YOSHIFUJI Hideaki / 吉藤英明
  2003-10-27  7:56     ` ipv6 UDP MSG_MORE oops fix David S. Miller
  3 siblings, 0 replies; 7+ messages in thread
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2003-10-26  9:54 UTC (permalink / raw)
  To: davem; +Cc: netdev, miyazawa, yoshfuji

Hello.

> I'm about to send 3 patches to fix them.
>
> [1/3] IPv6: Odd IPv6 header in UDPv6 packets when sending MSG_MORE flag
> [2/3] NET: store cork'ing flow information in common storage in inet_opt
> [3/3] IPv6: breakage of sendmsg to IPv4-mapped address via UDPv6 socket

[3/3] IPv6: breakage of sendmsg to IPv4-mapped address via UDPv6 socket

D: Fixing breakage of sendmsg to IPv4-mapped address via UDPv6 socket;
D: check destination address before checking cork flag to process
D: appropriately.

--- linux-2.5-net/net/ipv4/udp.c	Sun Oct 26 16:23:36 2003
+++ linux-2.5-udp6_append_data/net/ipv4/udp.c	Sun Oct 26 16:23:55 2003
@@ -522,8 +522,13 @@
 	 	 * The socket lock must be held while it's corked.
 		 */
 		lock_sock(sk);
-		if (likely(up->pending))
+		if (likely(up->pending)) {
+			if (unlikely(up->pending != AF_INET)) {
+				release_sock(sk);
+				return -EINVAL;
+			}
  			goto do_append_data;
+		}
 		release_sock(sk);
 	}
 	ulen += sizeof(struct udphdr);
@@ -642,7 +647,7 @@
 	inet->cork.fl.fl_ip_dport = dport;
 	inet->cork.fl.fl4_src = saddr;
 	inet->cork.fl.fl_ip_sport = inet->sport;
-	up->pending = 1;
+	up->pending = AF_INET;
 
 do_append_data:
 	up->len += ulen;
--- linux-2.5-net/net/ipv6/udp.c	Sun Oct 26 16:23:36 2003
+++ linux-2.5-udp6_append_data/net/ipv6/udp.c	Sun Oct 26 16:23:55 2003
@@ -787,11 +787,56 @@
 	struct dst_entry *dst;
 	int addr_len = msg->msg_namelen;
 	int ulen = len;
-	int addr_type;
 	int hlimit = -1;
 	int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
 	int err;
-	
+
+	/* destination address check */
+	if (sin6) {
+		if (addr_len < offsetof(struct sockaddr, sa_data))
+			return -EINVAL;
+
+		switch (sin6->sin6_family) {
+		case AF_INET6:
+			if (addr_len < SIN6_LEN_RFC2133)
+				return -EINVAL;
+			daddr = &sin6->sin6_addr;
+			break;
+		case AF_INET:
+			goto do_udp_sendmsg;
+		case AF_UNSPEC:
+			msg->msg_name = sin6 = NULL;
+			msg->msg_namelen = addr_len = 0;
+			daddr = NULL;
+			break;
+		default:
+			return -EINVAL;
+		}
+	} else if (!up->pending) {
+		if (sk->sk_state != TCP_ESTABLISHED)
+			return -EDESTADDRREQ;
+		daddr = &np->daddr;
+	} else 
+		daddr = NULL;
+
+	if (daddr) {
+		if (ipv6_addr_type(daddr) == IPV6_ADDR_MAPPED) {
+			struct sockaddr_in sin;
+			sin.sin_family = AF_INET;
+			sin.sin_port = sin6 ? sin6->sin6_port : inet->dport;
+			sin.sin_addr.s_addr = daddr->s6_addr[3];
+			msg->msg_name = &sin;
+			msg->msg_namelen = sizeof(sin);
+do_udp_sendmsg:
+			if (__ipv6_only_sock(sk))
+				return -ENETUNREACH;
+			return udp_sendmsg(iocb, sk, msg, len);
+		}
+	}
+
+	if (up->pending == AF_INET)
+		return udp_sendmsg(iocb, sk, msg, len);
+
 	/* Rough check on arithmetic overflow,
 	   better check is made in ip6_build_xmit
 	   */
@@ -805,6 +850,10 @@
 		 */
 		lock_sock(sk);
 		if (likely(up->pending)) {
+			if (unlikely(up->pending != AF_INET6)) {
+				release_sock(sk);
+				return -EINVAL;
+			}
 			dst = NULL;
 			goto do_append_data;
 		}
@@ -815,18 +864,6 @@
 	memset(fl, 0, sizeof(*fl));
 
 	if (sin6) {
-		if (sin6->sin6_family == AF_INET) {
-			if (__ipv6_only_sock(sk))
-				return -ENETUNREACH;
-			return udp_sendmsg(iocb, sk, msg, len);
-		}
-
-		if (addr_len < SIN6_LEN_RFC2133)
-			return -EINVAL;
-
-		if (sin6->sin6_family && sin6->sin6_family != AF_INET6)
-			return -EINVAL;
-
 		if (sin6->sin6_port == 0)
 			return -EINVAL;
 
@@ -864,24 +901,6 @@
 		fl->fl6_flowlabel = np->flow_label;
 	}
 
-	addr_type = ipv6_addr_type(daddr);
-
-	if (addr_type == IPV6_ADDR_MAPPED) {
-		struct sockaddr_in sin;
-
-		if (__ipv6_only_sock(sk))
-			return -ENETUNREACH;
-
-		sin.sin_family = AF_INET;
-		sin.sin_addr.s_addr = daddr->s6_addr32[3];
-		sin.sin_port = inet->cork.fl.fl_ip_dport;
-		msg->msg_name = (struct sockaddr *)(&sin);
-		msg->msg_namelen = sizeof(sin);
-		fl6_sock_release(flowlabel);
-
-		return udp_sendmsg(iocb, sk, msg, len);
-	}
-
 	if (!fl->oif)
 		fl->oif = sk->sk_bound_dev_if;
 
@@ -950,7 +969,7 @@
 		goto out;
 	}
 
-	up->pending = 1;
+	up->pending = AF_INET6;
 
 do_append_data:
 	up->len += ulen;

-- 
Hideaki YOSHIFUJI @ USAGI Project <yoshfuji@linux-ipv6.org>
GPG FP: 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA

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

* Re: ipv6 UDP MSG_MORE oops fix
  2003-10-26  9:50   ` YOSHIFUJI Hideaki / 吉藤英明
                       ` (2 preceding siblings ...)
  2003-10-26  9:54     ` [PATCH 3/3] IPv6: breakage of sendmsg to IPv4-mapped address via UDPv6 socket YOSHIFUJI Hideaki / 吉藤英明
@ 2003-10-27  7:56     ` David S. Miller
  3 siblings, 0 replies; 7+ messages in thread
From: David S. Miller @ 2003-10-27  7:56 UTC (permalink / raw)
  To: YOSHIFUJI Hideaki / _$B5HF#1QL@; +Cc: kuznet, netdev, yoshfuji, miyazawa

On Sun, 26 Oct 2003 18:50:23 +0900 (JST)
YOSHIFUJI Hideaki / _$B5HF#1QL@ <yoshfuji@linux-ipv6.org> wrote:

> [1/3] IPv6: Odd IPv6 header in UDPv6 packets when sending MSG_MORE flag
> [2/3] NET: store cork'ing flow information in common storage in inet_opt
> [3/3] IPv6: breakage of sendmsg to IPv4-mapped address via UDPv6 socket

All three patches applied, thanks Yoshfuji.

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

end of thread, other threads:[~2003-10-27  7:56 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-08-08  5:34 ipv6 UDP MSG_MORE oops fix David S. Miller
2003-08-08  8:08 ` YOSHIFUJI Hideaki / 吉藤英明
2003-10-26  9:50   ` YOSHIFUJI Hideaki / 吉藤英明
2003-10-26  9:54     ` [PATCH 1/3] IPv6: Fix odd IPv6 header in UDPv6 packets when sending MSG_MORE flag YOSHIFUJI Hideaki / 吉藤英明
2003-10-26  9:54     ` [PATCH 2/3] NET: store cork'ing flow information in common storage YOSHIFUJI Hideaki / 吉藤英明
2003-10-26  9:54     ` [PATCH 3/3] IPv6: breakage of sendmsg to IPv4-mapped address via UDPv6 socket YOSHIFUJI Hideaki / 吉藤英明
2003-10-27  7:56     ` ipv6 UDP MSG_MORE oops fix David S. Miller

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).