* [PATCH][IPV6] fixed authentication error with TCP
@ 2003-08-06 7:44 Kazunori Miyazawa
2003-08-08 5:05 ` David S. Miller
0 siblings, 1 reply; 9+ messages in thread
From: Kazunori Miyazawa @ 2003-08-06 7:44 UTC (permalink / raw)
To: davem, kuznet; +Cc: netdev, usagi, latten
Hello,
Miss Joy (@IBM) and I investigated the bug that "authentication error" occured with
using TCP and AH in IPv6. This patch fixes the bug. This patch makes the kernel consider
extension header length in a dst.
This pach works with my previous patch which fixes zero-clear in ah6_input.
Please append the name "Joy Latten" into the log.
#I'm in summer holidays until 10th August. I will response very slowly because I only have
dial-up line with 30kbps :-p
Best regards,
diff -ruN a/include/net/ipv6.h b/include/net/ipv6.h
--- a/include/net/ipv6.h 2003-07-28 02:07:24.000000000 +0900
+++ b/include/net/ipv6.h 2003-08-06 14:10:36.000000000 +0900
@@ -353,9 +353,7 @@
extern void ip6_flush_pending_frames(struct sock *sk);
-extern int ip6_dst_lookup(struct sock *sk,
- struct dst_entry **dst,
- struct flowi *fl);
+extern struct dst_entry * ip6_dst_lookup(struct sock *sk, struct flowi *fl);
/*
* skb processing functions
diff -ruN a/net/ipv6/icmp.c b/net/ipv6/icmp.c
--- a/net/ipv6/icmp.c 2003-07-28 01:59:40.000000000 +0900
+++ b/net/ipv6/icmp.c 2003-08-06 14:20:29.000000000 +0900
@@ -355,8 +355,8 @@
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif;
- err = ip6_dst_lookup(sk, &dst, &fl);
- if (err) goto out;
+ dst = ip6_dst_lookup(sk, &fl);
+ if (dst->error) goto out;
if (hlimit < 0) {
if (ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -434,9 +434,9 @@
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif;
- err = ip6_dst_lookup(sk, &dst, &fl);
+ dst = ip6_dst_lookup(sk, &fl);
- if (err) goto out;
+ if (dst->error) goto out;
if (hlimit < 0) {
if (ipv6_addr_is_multicast(&fl.fl6_dst))
diff -ruN a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
--- a/net/ipv6/ip6_output.c 2003-07-28 01:57:01.000000000 +0900
+++ b/net/ipv6/ip6_output.c 2003-08-06 15:35:23.000000000 +0900
@@ -211,10 +211,6 @@
u32 mtu;
int err = 0;
- if ((err = xfrm_lookup(&skb->dst, fl, sk, 0)) < 0) {
- return err;
- }
-
if (opt) {
int head_room;
@@ -1141,72 +1137,73 @@
return err;
}
-int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
+struct dst_entry *ip6_dst_lookup(struct sock *sk, struct flowi *fl)
{
- struct ipv6_pinfo *np = inet6_sk(sk);
+ struct dst_entry *dst = NULL;
int err = 0;
- *dst = __sk_dst_check(sk, np->dst_cookie);
- if (*dst) {
- struct rt6_info *rt = (struct rt6_info*)*dst;
-
- /* Yes, checking route validity in not connected
- case is not very simple. Take into account,
- that we do not support routing by source, TOS,
- and MSG_DONTROUTE --ANK (980726)
-
- 1. If route was host route, check that
- cached destination is current.
- If it is network route, we still may
- check its validity using saved pointer
- to the last used address: daddr_cache.
- We do not want to save whole address now,
- (because main consumer of this service
- is tcp, which has not this problem),
- so that the last trick works only on connected
- sockets.
- 2. oif also should be the same.
- */
-
- if (((rt->rt6i_dst.plen != 128 ||
- ipv6_addr_cmp(&fl->fl6_dst, &rt->rt6i_dst.addr))
- && (np->daddr_cache == NULL ||
- ipv6_addr_cmp(&fl->fl6_dst, np->daddr_cache)))
- || (fl->oif && fl->oif != (*dst)->dev->ifindex)) {
- *dst = NULL;
- } else
- dst_hold(*dst);
+ if (sk) {
+ struct ipv6_pinfo *np = inet6_sk(sk);
+
+ dst = __sk_dst_check(sk, np->dst_cookie);
+ if (dst) {
+ struct rt6_info *rt = (struct rt6_info*)dst;
+
+ /* Yes, checking route validity in not connected
+ case is not very simple. Take into account,
+ that we do not support routing by source, TOS,
+ and MSG_DONTROUTE --ANK (980726)
+
+ 1. If route was host route, check that
+ cached destination is current.
+ If it is network route, we still may
+ check its validity using saved pointer
+ to the last used address: daddr_cache.
+ We do not want to save whole address now,
+ (because main consumer of this service
+ is tcp, which has not this problem),
+ so that the last trick works only on connected
+ sockets.
+ 2. oif also should be the same.
+ */
+
+ if (((rt->rt6i_dst.plen != 128 ||
+ ipv6_addr_cmp(&fl->fl6_dst, &rt->rt6i_dst.addr))
+ && (np->daddr_cache == NULL ||
+ ipv6_addr_cmp(&fl->fl6_dst, np->daddr_cache)))
+ || (fl->oif && fl->oif != dst->dev->ifindex)) {
+ dst = NULL;
+ } else
+ dst_hold(dst);
+ }
}
- if (*dst == NULL)
- *dst = ip6_route_output(sk, fl);
+ if (dst == NULL)
+ dst = ip6_route_output(sk, fl);
- if ((*dst)->error) {
- IP6_INC_STATS(Ip6OutNoRoutes);
- dst_release(*dst);
- return -ENETUNREACH;
- }
+ if (dst->error)
+ return dst;
if (ipv6_addr_any(&fl->fl6_src)) {
- err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src);
+ err = ipv6_get_saddr(dst, &fl->fl6_dst, &fl->fl6_src);
if (err) {
#if IP6_DEBUG >= 2
printk(KERN_DEBUG "ip6_build_xmit: "
"no available source address\n");
#endif
- return err;
+ dst->error = err;
+ return dst;
}
}
- if (*dst) {
- if ((err = xfrm_lookup(dst, fl, sk, 0)) < 0) {
- dst_release(*dst);
- return -ENETUNREACH;
+ if (dst) {
+ if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) {
+ dst->error = -ENETUNREACH;
}
}
- return 0;
+ return dst;
}
int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb),
diff -ruN a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c 2003-07-28 02:00:40.000000000 +0900
+++ b/net/ipv6/raw.c 2003-08-06 14:19:32.000000000 +0900
@@ -658,8 +658,8 @@
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif;
- err = ip6_dst_lookup(sk, &dst, &fl);
- if (err)
+ dst = ip6_dst_lookup(sk, &fl);
+ if (dst->error)
goto out;
if (hlimit < 0) {
diff -ruN a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
--- a/net/ipv6/tcp_ipv6.c 2003-07-28 02:03:09.000000000 +0900
+++ b/net/ipv6/tcp_ipv6.c 2003-08-06 16:13:21.000000000 +0900
@@ -663,7 +663,7 @@
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
}
- dst = ip6_route_output(sk, &fl);
+ dst = ip6_dst_lookup(sk, &fl);
if ((err = dst->error) != 0) {
dst_release(dst);
@@ -691,6 +691,8 @@
tp->ext_header_len = 0;
if (np->opt)
tp->ext_header_len = np->opt->opt_flen + np->opt->opt_nflen;
+ tp->ext2_header_len = dst->header_len;
+
tp->mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
inet->dport = usin->sin6_port;
@@ -788,7 +790,7 @@
fl.fl_ip_dport = inet->dport;
fl.fl_ip_sport = inet->sport;
- dst = ip6_route_output(sk, &fl);
+ dst = ip6_dst_lookup(sk, &fl);
} else
dst_hold(dst);
@@ -889,7 +891,7 @@
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
}
- dst = ip6_route_output(sk, &fl);
+ dst = ip6_dst_lookup(sk, &fl);
if (dst->error)
goto done;
}
@@ -1018,7 +1020,7 @@
fl.fl_ip_sport = t1->source;
/* sk = NULL, but it is safe for now. RST socket required. */
- buff->dst = ip6_route_output(NULL, &fl);
+ buff->dst = ip6_dst_lookup(NULL, &fl);
if (buff->dst->error == 0) {
ip6_xmit(NULL, buff, &fl, NULL, 0);
@@ -1081,7 +1083,7 @@
fl.fl_ip_dport = t1->dest;
fl.fl_ip_sport = t1->source;
- buff->dst = ip6_route_output(NULL, &fl);
+ buff->dst = ip6_dst_lookup(NULL, &fl);
if (buff->dst->error == 0) {
ip6_xmit(NULL, buff, &fl, NULL, 0);
@@ -1329,7 +1331,7 @@
fl.fl_ip_dport = req->rmt_port;
fl.fl_ip_sport = inet_sk(sk)->sport;
- dst = ip6_route_output(sk, &fl);
+ dst = ip6_dst_lookup(sk, &fl);
}
if (dst->error)
@@ -1401,6 +1403,7 @@
if (newnp->opt)
newtp->ext_header_len = newnp->opt->opt_nflen +
newnp->opt->opt_flen;
+ newtp->ext2_header_len = dst->header_len;
tcp_sync_mss(newsk, dst_pmtu(dst));
newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
@@ -1727,7 +1730,7 @@
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
}
- dst = ip6_route_output(sk, &fl);
+ dst = ip6_dst_lookup(sk, &fl);
if (dst->error) {
err = dst->error;
@@ -1770,7 +1773,7 @@
dst = __sk_dst_check(sk, np->dst_cookie);
if (dst == NULL) {
- dst = ip6_route_output(sk, &fl);
+ dst = ip6_dst_lookup(sk, &fl);
if (dst->error) {
sk->sk_err_soft = -dst->error;
diff -ruN a/net/ipv6/udp.c b/net/ipv6/udp.c
--- a/net/ipv6/udp.c 2003-07-28 02:07:29.000000000 +0900
+++ b/net/ipv6/udp.c 2003-08-06 14:19:23.000000000 +0900
@@ -928,8 +928,8 @@
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif;
- err = ip6_dst_lookup(sk, &dst, &fl);
- if (err)
+ dst = ip6_dst_lookup(sk, &fl);
+ if (dst->error)
goto out;
if (hlimit < 0) {
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH][IPV6] fixed authentication error with TCP 2003-08-06 7:44 [PATCH][IPV6] fixed authentication error with TCP Kazunori Miyazawa @ 2003-08-08 5:05 ` David S. Miller 2003-08-17 23:29 ` kuznet 0 siblings, 1 reply; 9+ messages in thread From: David S. Miller @ 2003-08-08 5:05 UTC (permalink / raw) To: Kazunori Miyazawa; +Cc: kuznet, netdev, usagi, latten On Wed, 6 Aug 2003 16:44:13 +0900 Kazunori Miyazawa <kazunori@miyazawa.org> wrote: > Miss Joy (@IBM) and I investigated the bug that "authentication > error" occured with using TCP and AH in IPv6. This patch fixes the > bug. This patch makes the kernel consider extension header length in > a dst. > > This pach works with my previous patch which fixes zero-clear in ah6_input. > > Please append the name "Joy Latten" into the log. I have applied this patch, thank you. But I see a small area for improvement. Look at the place inside of ip6_dst_lookup() where we do source address selection. If this fails, we mark error to dst->error. Is it correct? This 'dst' route might otherwise be perfectly fine. But now that dst->error is set, it is poisoned for other users and they are not able to use it. A similar case occurs further down after the xfrm_lookup() call, but this one I think is correct. It seems to me that it is only OK for dst->error to be set on routes that may not be used validly for anything. Alexey, do I understand this stuff correctly? ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH][IPV6] fixed authentication error with TCP 2003-08-08 5:05 ` David S. Miller @ 2003-08-17 23:29 ` kuznet 2003-08-18 7:45 ` Ville Nuorvala 0 siblings, 1 reply; 9+ messages in thread From: kuznet @ 2003-08-17 23:29 UTC (permalink / raw) To: David S. Miller; +Cc: kazunori, netdev, usagi, latten Hello! > But I see a small area for improvement. Look at the place inside > of ip6_dst_lookup() where we do source address selection. If this > fails, we mark error to dst->error. ..... > It seems to me that it is only OK for dst->error to be set on routes > that may not be used validly for anything. > > Alexey, do I understand this stuff correctly? I think you do. And this is rather severe bug than area for improvement. It definitely corrupts routing table. Well, I think switching from function returning error code to a function returning dst is not a very good idea. This never was convenient. In the case of error, IPv6 used to return to caller a dummy reject route, which is always -ENETRUNREACH. So, to do this we have to hold a route for each errno. Returning int was just better. Alexey ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH][IPV6] fixed authentication error with TCP 2003-08-17 23:29 ` kuznet @ 2003-08-18 7:45 ` Ville Nuorvala 2003-08-18 7:45 ` David S. Miller ` (3 more replies) 0 siblings, 4 replies; 9+ messages in thread From: Ville Nuorvala @ 2003-08-18 7:45 UTC (permalink / raw) To: kuznet, David S. Miller, kazunori; +Cc: netdev, usagi, latten [-- Attachment #1: Type: TEXT/PLAIN, Size: 1540 bytes --] On Mon, 18 Aug 2003 kuznet@ms2.inr.ac.ru wrote: > Hello! > > > But I see a small area for improvement. Look at the place inside > > of ip6_dst_lookup() where we do source address selection. If this > > fails, we mark error to dst->error. > ..... > > It seems to me that it is only OK for dst->error to be set on routes > > that may not be used validly for anything. > > > > Alexey, do I understand this stuff correctly? > > I think you do. And this is rather severe bug than area for improvement. > It definitely corrupts routing table. Besides this, the patch also introduced dst_entry leaks in at least icmp.c, raw.c and udp.c. > > Well, I think switching from function returning error code to a function > returning dst is not a very good idea. This never was convenient. > In the case of error, IPv6 used to return to caller a dummy reject route, > which is always -ENETRUNREACH. So, to do this we have to hold a route > for each errno. Returning int was just better. The attached patch reverts to the old ip6_dst_lookup() interface and and makes tcp_ipv6.c use that instead. As an added bonus neither tcp_v6_connect() nor udpv6_connect() needs to do source address selection anymore, since ip6_dst_lookup() already does this for them. > > Alexey I've tested the patch a bit and everything seems to work normally, so its probably safe to apply it :) Thanks, Ville -- Ville Nuorvala Research Assistant, Institute of Digital Communications, Helsinki University of Technology email: vnuorval@tcs.hut.fi, phone: +358 (0)9 451 5257 [-- Attachment #2: Type: TEXT/PLAIN, Size: 8608 bytes --] diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5.OLD/include/net/ipv6.h linux-2.5/include/net/ipv6.h --- linux-2.5.OLD/include/net/ipv6.h Mon Aug 18 10:04:07 2003 +++ linux-2.5/include/net/ipv6.h Fri Aug 15 13:29:00 2003 @@ -353,7 +353,9 @@ extern void ip6_flush_pending_frames(struct sock *sk); -extern struct dst_entry * ip6_dst_lookup(struct sock *sk, struct flowi *fl); +extern int ip6_dst_lookup(struct sock *sk, + struct dst_entry **dst, + struct flowi *fl); /* * skb processing functions diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5.OLD/net/ipv6/icmp.c linux-2.5/net/ipv6/icmp.c --- linux-2.5.OLD/net/ipv6/icmp.c Mon Aug 18 10:04:23 2003 +++ linux-2.5/net/ipv6/icmp.c Fri Aug 15 13:29:03 2003 @@ -355,8 +355,8 @@ if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) fl.oif = np->mcast_oif; - dst = ip6_dst_lookup(sk, &fl); - if (dst->error) goto out; + err = ip6_dst_lookup(sk, &dst, &fl); + if (err) goto out; if (hlimit < 0) { if (ipv6_addr_is_multicast(&fl.fl6_dst)) @@ -434,9 +434,9 @@ if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) fl.oif = np->mcast_oif; - dst = ip6_dst_lookup(sk, &fl); + err = ip6_dst_lookup(sk, &dst, &fl); - if (dst->error) goto out; + if (err) goto out; if (hlimit < 0) { if (ipv6_addr_is_multicast(&fl.fl6_dst)) diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5.OLD/net/ipv6/ip6_output.c linux-2.5/net/ipv6/ip6_output.c --- linux-2.5.OLD/net/ipv6/ip6_output.c Mon Aug 18 10:04:23 2003 +++ linux-2.5/net/ipv6/ip6_output.c Fri Aug 15 13:51:11 2003 @@ -1136,17 +1136,16 @@ return err; } -struct dst_entry *ip6_dst_lookup(struct sock *sk, struct flowi *fl) +int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) { - struct dst_entry *dst = NULL; int err = 0; if (sk) { struct ipv6_pinfo *np = inet6_sk(sk); - dst = __sk_dst_check(sk, np->dst_cookie); - if (dst) { - struct rt6_info *rt = (struct rt6_info*)dst; + *dst = __sk_dst_check(sk, np->dst_cookie); + if (*dst) { + struct rt6_info *rt = (struct rt6_info*)*dst; /* Yes, checking route validity in not connected case is not very simple. Take into account, @@ -1170,39 +1169,38 @@ ipv6_addr_cmp(&fl->fl6_dst, &rt->rt6i_dst.addr)) && (np->daddr_cache == NULL || ipv6_addr_cmp(&fl->fl6_dst, np->daddr_cache))) - || (fl->oif && fl->oif != dst->dev->ifindex)) { - dst = NULL; + || (fl->oif && fl->oif != (*dst)->dev->ifindex)) { + *dst = NULL; } else - dst_hold(dst); + dst_hold(*dst); } } - if (dst == NULL) - dst = ip6_route_output(sk, fl); - - if (dst->error) - return dst; + if (*dst == NULL) + *dst = ip6_route_output(sk, fl); + if ((err = (*dst)->error)) { + dst_release(*dst); + return err; + } if (ipv6_addr_any(&fl->fl6_src)) { - err = ipv6_get_saddr(dst, &fl->fl6_dst, &fl->fl6_src); + err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src); if (err) { #if IP6_DEBUG >= 2 - printk(KERN_DEBUG "ip6_build_xmit: " + printk(KERN_DEBUG "ip6_dst_lookup: " "no available source address\n"); #endif - dst->error = err; - return dst; + dst_release(*dst); + return err; } } - - if (dst) { - if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) { - dst->error = -ENETUNREACH; - } + if ((err = xfrm_lookup(dst, fl, sk, 0)) < 0) { + dst_release(*dst); + return -ENETUNREACH; } - return dst; + return 0; } int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5.OLD/net/ipv6/raw.c linux-2.5/net/ipv6/raw.c --- linux-2.5.OLD/net/ipv6/raw.c Mon Aug 18 10:04:24 2003 +++ linux-2.5/net/ipv6/raw.c Fri Aug 15 13:33:14 2003 @@ -658,8 +658,8 @@ if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) fl.oif = np->mcast_oif; - dst = ip6_dst_lookup(sk, &fl); - if ((err = dst->error)) + err = ip6_dst_lookup(sk, &dst, &fl); + if (err) goto out; if (hlimit < 0) { diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5.OLD/net/ipv6/tcp_ipv6.c linux-2.5/net/ipv6/tcp_ipv6.c --- linux-2.5.OLD/net/ipv6/tcp_ipv6.c Mon Aug 18 10:04:24 2003 +++ linux-2.5/net/ipv6/tcp_ipv6.c Fri Aug 15 17:24:06 2003 @@ -663,19 +663,12 @@ ipv6_addr_copy(&fl.fl6_dst, rt0->addr); } - dst = ip6_dst_lookup(sk, &fl); + err = ip6_dst_lookup(sk, &dst, &fl); - if ((err = dst->error) != 0) { - dst_release(dst); + if (err) goto failure; - } if (saddr == NULL) { - err = ipv6_get_saddr(dst, &np->daddr, &fl.fl6_src); - if (err) { - dst_release(dst); - goto failure; - } saddr = &fl.fl6_src; ipv6_addr_copy(&np->rcv_saddr, saddr); } @@ -790,13 +783,14 @@ fl.fl_ip_dport = inet->dport; fl.fl_ip_sport = inet->sport; - dst = ip6_dst_lookup(sk, &fl); + if ((err = ip6_dst_lookup(sk, &dst, &fl))) { + sk->sk_err_soft = -err; + goto out; + } } else dst_hold(dst); - if (dst->error) { - sk->sk_err_soft = -dst->error; - } else if (tp->pmtu_cookie > dst_pmtu(dst)) { + if (tp->pmtu_cookie > dst_pmtu(dst)) { tcp_sync_mss(sk, dst_pmtu(dst)); tcp_simple_retransmit(sk); } /* else let the usual retransmit timer handle it */ @@ -891,8 +885,8 @@ ipv6_addr_copy(&fl.fl6_dst, rt0->addr); } - dst = ip6_dst_lookup(sk, &fl); - if (dst->error) + err = ip6_dst_lookup(sk, &dst, &fl); + if (err) goto done; } @@ -1020,9 +1014,7 @@ fl.fl_ip_sport = t1->source; /* sk = NULL, but it is safe for now. RST socket required. */ - buff->dst = ip6_dst_lookup(NULL, &fl); - - if (buff->dst->error == 0) { + if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { ip6_xmit(NULL, buff, &fl, NULL, 0); TCP_INC_STATS_BH(TcpOutSegs); TCP_INC_STATS_BH(TcpOutRsts); @@ -1083,9 +1075,7 @@ fl.fl_ip_dport = t1->dest; fl.fl_ip_sport = t1->source; - buff->dst = ip6_dst_lookup(NULL, &fl); - - if (buff->dst->error == 0) { + if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { ip6_xmit(NULL, buff, &fl, NULL, 0); TCP_INC_STATS_BH(TcpOutSegs); return; @@ -1331,11 +1321,9 @@ fl.fl_ip_dport = req->rmt_port; fl.fl_ip_sport = inet_sk(sk)->sport; - dst = ip6_dst_lookup(sk, &fl); - } - - if (dst->error) - goto out; + if (ip6_dst_lookup(sk, &dst, &fl)) + goto out; + } newsk = tcp_create_openreq_child(sk, req, skb); if (newsk == NULL) @@ -1730,11 +1718,9 @@ ipv6_addr_copy(&fl.fl6_dst, rt0->addr); } - dst = ip6_dst_lookup(sk, &fl); + err = ip6_dst_lookup(sk, &dst, &fl); - if (dst->error) { - err = dst->error; - dst_release(dst); + if (err) { sk->sk_route_caps = 0; return err; } @@ -1773,12 +1759,11 @@ dst = __sk_dst_check(sk, np->dst_cookie); if (dst == NULL) { - dst = ip6_dst_lookup(sk, &fl); + int err = ip6_dst_lookup(sk, &dst, &fl); - if (dst->error) { - sk->sk_err_soft = -dst->error; - dst_release(dst); - return -sk->sk_err_soft; + if (err) { + sk->sk_err_soft = -err; + return err; } ip6_dst_store(sk, dst, NULL); diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet linux-2.5.OLD/net/ipv6/udp.c linux-2.5/net/ipv6/udp.c --- linux-2.5.OLD/net/ipv6/udp.c Mon Aug 18 10:04:24 2003 +++ linux-2.5/net/ipv6/udp.c Fri Aug 15 13:34:28 2003 @@ -330,21 +330,11 @@ ipv6_addr_copy(&fl.fl6_dst, rt0->addr); } - dst = ip6_route_output(sk, &fl); - - if ((err = dst->error) != 0) { - dst_release(dst); + err = ip6_dst_lookup(sk, &dst, &fl); + if (err) goto out; - } - - /* get the source address used in the appropriate device */ - err = ipv6_get_saddr(dst, daddr, &fl.fl6_src); - - if (err) { - dst_release(dst); - goto out; - } + /* source address lookup done in ip6_dst_lookup */ if (ipv6_addr_any(&np->saddr)) ipv6_addr_copy(&np->saddr, &fl.fl6_src); @@ -930,8 +920,8 @@ if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) fl.oif = np->mcast_oif; - dst = ip6_dst_lookup(sk, &fl); - if ((err = dst->error)) + err = ip6_dst_lookup(sk, &dst, &fl); + if (err) goto out; if (hlimit < 0) { ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH][IPV6] fixed authentication error with TCP 2003-08-18 7:45 ` Ville Nuorvala @ 2003-08-18 7:45 ` David S. Miller 2003-08-18 9:32 ` Kazunori Miyazawa ` (2 subsequent siblings) 3 siblings, 0 replies; 9+ messages in thread From: David S. Miller @ 2003-08-18 7:45 UTC (permalink / raw) To: Ville Nuorvala; +Cc: kuznet, kazunori, netdev, usagi, latten On Mon, 18 Aug 2003 10:45:41 +0300 (EEST) Ville Nuorvala <vnuorval@tcs.hut.fi> wrote: > The attached patch reverts to the old ip6_dst_lookup() interface and and > makes tcp_ipv6.c use that instead. > > As an added bonus neither tcp_v6_connect() nor udpv6_connect() needs to do > source address selection anymore, since ip6_dst_lookup() already does this > for them. Thanks a lot for doing this work, I'll review and apply your patch. I was about to code this up myself :) ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH][IPV6] fixed authentication error with TCP 2003-08-18 7:45 ` Ville Nuorvala 2003-08-18 7:45 ` David S. Miller @ 2003-08-18 9:32 ` Kazunori Miyazawa 2003-08-18 9:48 ` David S. Miller 2003-08-18 10:11 ` David S. Miller 3 siblings, 0 replies; 9+ messages in thread From: Kazunori Miyazawa @ 2003-08-18 9:32 UTC (permalink / raw) To: Ville Nuorvala; +Cc: kuznet, davem, netdev, usagi, latten I don't stick to chenge the interface. I think his/her patch is better than mine. I checked and it seems to work well. Please apply his/her patch. On Mon, 18 Aug 2003 10:45:41 +0300 (EEST) Ville Nuorvala <vnuorval@tcs.hut.fi> wrote: > On Mon, 18 Aug 2003 kuznet@ms2.inr.ac.ru wrote: > > > Hello! > > > > > But I see a small area for improvement. Look at the place inside > > > of ip6_dst_lookup() where we do source address selection. If this > > > fails, we mark error to dst->error. > > ..... > > > It seems to me that it is only OK for dst->error to be set on routes > > > that may not be used validly for anything. > > > > > > Alexey, do I understand this stuff correctly? > > > > I think you do. And this is rather severe bug than area for improvement. > > It definitely corrupts routing table. > > Besides this, the patch also introduced dst_entry leaks in at least > icmp.c, raw.c and udp.c. > > > > Well, I think switching from function returning error code to a function > > returning dst is not a very good idea. This never was convenient. > > In the case of error, IPv6 used to return to caller a dummy reject route, > > which is always -ENETRUNREACH. So, to do this we have to hold a route > > for each errno. Returning int was just better. > > The attached patch reverts to the old ip6_dst_lookup() interface and and > makes tcp_ipv6.c use that instead. > > As an added bonus neither tcp_v6_connect() nor udpv6_connect() needs to do > source address selection anymore, since ip6_dst_lookup() already does this > for them. > > > > > Alexey > > I've tested the patch a bit and everything seems to work normally, so its > probably safe to apply it :) > > Thanks, > Ville > -- > Ville Nuorvala > Research Assistant, Institute of Digital Communications, > Helsinki University of Technology > email: vnuorval@tcs.hut.fi, phone: +358 (0)9 451 5257 > --Kazunori Miyazawa ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH][IPV6] fixed authentication error with TCP 2003-08-18 7:45 ` Ville Nuorvala 2003-08-18 7:45 ` David S. Miller 2003-08-18 9:32 ` Kazunori Miyazawa @ 2003-08-18 9:48 ` David S. Miller 2003-08-18 10:36 ` David S. Miller 2003-08-18 10:11 ` David S. Miller 3 siblings, 1 reply; 9+ messages in thread From: David S. Miller @ 2003-08-18 9:48 UTC (permalink / raw) To: Ville Nuorvala; +Cc: kuznet, kazunori, netdev, usagi, latten On Mon, 18 Aug 2003 10:45:41 +0300 (EEST) Ville Nuorvala <vnuorval@tcs.hut.fi> wrote: > The attached patch reverts to the old ip6_dst_lookup() interface and and > makes tcp_ipv6.c use that instead. > > As an added bonus neither tcp_v6_connect() nor udpv6_connect() needs to do > source address selection anymore, since ip6_dst_lookup() already does this > for them. While verifying this patch, I discovered some new dst leaks. For example: 1) In icmpv6_send(), who releases the DST? 2) Similarly, for icmpv6_echo_reply()? In these two cases, ip6_append_data() grabs one reference each time it attaches 'rt' to the np->cort.rt, but we still have the singular reference in those two icmpv6_*() routines referenced above and they leak. 3) ip6_push_pending_frames(), it gets a new reference to np->cork.rt to attach the 'dst' to skb->dst on output. Then it sets np->cork.rt to NULL, 1 reference is lost as a result. 4) Similarly in ip6_flush_pending_frames(). I don't want to check any more places, because every place where I look in ipv6 I find a new DST leak :( ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH][IPV6] fixed authentication error with TCP 2003-08-18 9:48 ` David S. Miller @ 2003-08-18 10:36 ` David S. Miller 0 siblings, 0 replies; 9+ messages in thread From: David S. Miller @ 2003-08-18 10:36 UTC (permalink / raw) To: David S. Miller; +Cc: vnuorval, kuznet, kazunori, netdev, usagi, latten On Mon, 18 Aug 2003 02:48:37 -0700 "David S. Miller" <davem@redhat.com> wrote: > While verifying this patch, I discovered some new dst leaks. This patch fixes them up. # 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.1209 -> 1.1210 # net/ipv6/ip6_output.c 1.42 -> 1.43 # net/ipv6/icmp.c 1.39 -> 1.40 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/08/18 davem@nuts.ninka.net 1.1210 # [IPV6]: Fix some dst cache leaks. # 1) icmpv6_send() and icmpv6_echo_reply() never release dst. # 2) ip6_{push,flush}_pending_frames() leak np->cork.rt. # -------------------------------------------- # diff -Nru a/net/ipv6/icmp.c b/net/ipv6/icmp.c --- a/net/ipv6/icmp.c Mon Aug 18 03:39:55 2003 +++ b/net/ipv6/icmp.c Mon Aug 18 03:39:55 2003 @@ -356,7 +356,8 @@ fl.oif = np->mcast_oif; err = ip6_dst_lookup(sk, &dst, &fl); - if (err) goto out; + if (err) + goto out; if (hlimit < 0) { if (ipv6_addr_is_multicast(&fl.fl6_dst)) @@ -375,7 +376,7 @@ if (net_ratelimit()) printk(KERN_DEBUG "icmp: len problem\n"); __skb_push(skb, plen); - goto out; + goto out_dst_release; } idev = in6_dev_get(skb->dev); @@ -396,6 +397,8 @@ out_put: if (likely(idev != NULL)) in6_dev_put(idev); +out_dst_release: + dst_release(dst); out: icmpv6_xmit_unlock(); } @@ -435,8 +438,8 @@ fl.oif = np->mcast_oif; err = ip6_dst_lookup(sk, &dst, &fl); - - if (err) goto out; + if (err) + goto out; if (hlimit < 0) { if (ipv6_addr_is_multicast(&fl.fl6_dst)) @@ -465,6 +468,7 @@ out_put: if (likely(idev != NULL)) in6_dev_put(idev); + dst_release(dst); out: icmpv6_xmit_unlock(); } diff -Nru a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c --- a/net/ipv6/ip6_output.c Mon Aug 18 03:39:55 2003 +++ b/net/ipv6/ip6_output.c Mon Aug 18 03:39:55 2003 @@ -1484,6 +1484,7 @@ np->cork.opt = NULL; } if (np->cork.rt) { + dst_release(&np->cork.rt->u.dst); np->cork.rt = NULL; } if (np->cork.fl) { @@ -1510,6 +1511,7 @@ np->cork.opt = NULL; } if (np->cork.rt) { + dst_release(&np->cork.rt->u.dst); np->cork.rt = NULL; } if (np->cork.fl) { ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH][IPV6] fixed authentication error with TCP 2003-08-18 7:45 ` Ville Nuorvala ` (2 preceding siblings ...) 2003-08-18 9:48 ` David S. Miller @ 2003-08-18 10:11 ` David S. Miller 3 siblings, 0 replies; 9+ messages in thread From: David S. Miller @ 2003-08-18 10:11 UTC (permalink / raw) To: Ville Nuorvala; +Cc: kuznet, kazunori, netdev, usagi, latten On Mon, 18 Aug 2003 10:45:41 +0300 (EEST) Ville Nuorvala <vnuorval@tcs.hut.fi> wrote: > The attached patch reverts to the old ip6_dst_lookup() interface and and > makes tcp_ipv6.c use that instead. I applied your patch with a small change, I made it so that *dst is set to NULL in every case that ip6_dst_lookup() returned an error. In particular, there were some error paths still in tcp_ipv6.c that would dst_release() in the error path which only works if dst is set to NULL in ip6_dst_lookup() error cases. ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2003-08-18 10:36 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2003-08-06 7:44 [PATCH][IPV6] fixed authentication error with TCP Kazunori Miyazawa 2003-08-08 5:05 ` David S. Miller 2003-08-17 23:29 ` kuznet 2003-08-18 7:45 ` Ville Nuorvala 2003-08-18 7:45 ` David S. Miller 2003-08-18 9:32 ` Kazunori Miyazawa 2003-08-18 9:48 ` David S. Miller 2003-08-18 10:36 ` David S. Miller 2003-08-18 10:11 ` 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).