netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 1/4] tcp: fix inet6_csk_route_req() for link-local addresses
@ 2012-06-28 22:34 Neal Cardwell
  2012-06-28 22:34 ` [PATCH net-next 2/4] tcp: pass fl6 to inet6_csk_route_req() Neal Cardwell
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Neal Cardwell @ 2012-06-28 22:34 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Eric Dumazet, Neal Cardwell

Fix inet6_csk_route_req() to use as the flowi6_oif the treq->iif,
which is correctly fixed up in tcp_v6_conn_request() to handle the
case of link-local addresses. This brings it in line with the
tcp_v6_send_synack() code, which is already correctly using the
treq->iif in this way.

Signed-off-by: Neal Cardwell <ncardwell@google.com>
---
 net/ipv6/inet6_connection_sock.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index e6cee52..e23d354 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -68,7 +68,7 @@ struct dst_entry *inet6_csk_route_req(struct sock *sk,
 	fl6.daddr = treq->rmt_addr;
 	final_p = fl6_update_dst(&fl6, np->opt, &final);
 	fl6.saddr = treq->loc_addr;
-	fl6.flowi6_oif = sk->sk_bound_dev_if;
+	fl6.flowi6_oif = treq->iif;
 	fl6.flowi6_mark = sk->sk_mark;
 	fl6.fl6_dport = inet_rsk(req)->rmt_port;
 	fl6.fl6_sport = inet_rsk(req)->loc_port;
-- 
1.7.4.1

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

* [PATCH net-next 2/4] tcp: pass fl6 to inet6_csk_route_req()
  2012-06-28 22:34 [PATCH net-next 1/4] tcp: fix inet6_csk_route_req() for link-local addresses Neal Cardwell
@ 2012-06-28 22:34 ` Neal Cardwell
  2012-06-29  0:55   ` David Miller
  2012-06-28 22:34 ` [PATCH net-next 3/4] tcp: use inet6_csk_route_req() in tcp_v6_send_synack() Neal Cardwell
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Neal Cardwell @ 2012-06-28 22:34 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Eric Dumazet, Neal Cardwell

This commit changes inet_csk_route_req() so that it uses a pointer to
a struct flowi6, rather than allocating its own on the stack. This
brings its behavior in line with its IPv4 cousin,
inet_csk_route_req(), and allows a follow-on patch to fix a dst leak.

Signed-off-by: Neal Cardwell <ncardwell@google.com>
---
 include/net/inet6_connection_sock.h |    1 +
 net/ipv6/inet6_connection_sock.c    |   24 ++++++++++++------------
 net/ipv6/tcp_ipv6.c                 |    9 ++++++---
 3 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h
index 1866a67..df2a857 100644
--- a/include/net/inet6_connection_sock.h
+++ b/include/net/inet6_connection_sock.h
@@ -26,6 +26,7 @@ extern int inet6_csk_bind_conflict(const struct sock *sk,
 				   const struct inet_bind_bucket *tb, bool relax);
 
 extern struct dst_entry* inet6_csk_route_req(struct sock *sk,
+					     struct flowi6 *fl6,
 					     const struct request_sock *req);
 
 extern struct request_sock *inet6_csk_search_req(const struct sock *sk,
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index e23d354..bceb144 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -55,26 +55,26 @@ int inet6_csk_bind_conflict(const struct sock *sk,
 EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict);
 
 struct dst_entry *inet6_csk_route_req(struct sock *sk,
+				      struct flowi6 *fl6,
 				      const struct request_sock *req)
 {
 	struct inet6_request_sock *treq = inet6_rsk(req);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct in6_addr *final_p, final;
 	struct dst_entry *dst;
-	struct flowi6 fl6;
-
-	memset(&fl6, 0, sizeof(fl6));
-	fl6.flowi6_proto = IPPROTO_TCP;
-	fl6.daddr = treq->rmt_addr;
-	final_p = fl6_update_dst(&fl6, np->opt, &final);
-	fl6.saddr = treq->loc_addr;
-	fl6.flowi6_oif = treq->iif;
-	fl6.flowi6_mark = sk->sk_mark;
-	fl6.fl6_dport = inet_rsk(req)->rmt_port;
-	fl6.fl6_sport = inet_rsk(req)->loc_port;
-	security_req_classify_flow(req, flowi6_to_flowi(&fl6));
 
-	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
+	memset(fl6, 0, sizeof(*fl6));
+	fl6->flowi6_proto = IPPROTO_TCP;
+	fl6->daddr = treq->rmt_addr;
+	final_p = fl6_update_dst(fl6, np->opt, &final);
+	fl6->saddr = treq->loc_addr;
+	fl6->flowi6_oif = treq->iif;
+	fl6->flowi6_mark = sk->sk_mark;
+	fl6->fl6_dport = inet_rsk(req)->rmt_port;
+	fl6->fl6_sport = inet_rsk(req)->loc_port;
+	security_req_classify_flow(req, flowi6_to_flowi(fl6));
+
+	dst = ip6_dst_lookup_flow(sk, fl6, final_p, false);
 	if (IS_ERR(dst))
 		return NULL;
 
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 26a8862..3b79e94 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -477,7 +477,8 @@ out:
 }
 
 
-static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
+static int tcp_v6_send_synack(struct sock *sk,
+			      struct request_sock *req,
 			      struct request_values *rvp,
 			      u16 queue_mapping)
 {
@@ -1058,6 +1059,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 	struct tcp_sock *tp = tcp_sk(sk);
 	__u32 isn = TCP_SKB_CB(skb)->when;
 	struct dst_entry *dst = NULL;
+	struct flowi6 fl6;
 	bool want_cookie = false;
 
 	if (skb->protocol == htons(ETH_P_IP))
@@ -1177,7 +1179,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 		 */
 		if (tmp_opt.saw_tstamp &&
 		    tcp_death_row.sysctl_tw_recycle &&
-		    (dst = inet6_csk_route_req(sk, req)) != NULL &&
+		    (dst = inet6_csk_route_req(sk, &fl6, req)) != NULL &&
 		    (peer = rt6_get_peer((struct rt6_info *)dst)) != NULL &&
 		    ipv6_addr_equal((struct in6_addr *)peer->daddr.addr.a6,
 				    &treq->rmt_addr)) {
@@ -1246,6 +1248,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 #ifdef CONFIG_TCP_MD5SIG
 	struct tcp_md5sig_key *key;
 #endif
+	struct flowi6 fl6;
 
 	if (skb->protocol == htons(ETH_P_IP)) {
 		/*
@@ -1308,7 +1311,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 		goto out_overflow;
 
 	if (!dst) {
-		dst = inet6_csk_route_req(sk, req);
+		dst = inet6_csk_route_req(sk, &fl6, req);
 		if (!dst)
 			goto out;
 	}
-- 
1.7.4.1

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

* [PATCH net-next 3/4] tcp: use inet6_csk_route_req() in tcp_v6_send_synack()
  2012-06-28 22:34 [PATCH net-next 1/4] tcp: fix inet6_csk_route_req() for link-local addresses Neal Cardwell
  2012-06-28 22:34 ` [PATCH net-next 2/4] tcp: pass fl6 to inet6_csk_route_req() Neal Cardwell
@ 2012-06-28 22:34 ` Neal Cardwell
  2012-06-29  0:55   ` David Miller
  2012-06-28 22:34 ` [PATCH net-next 4/4] tcp: plug dst leak in tcp_v6_conn_request() Neal Cardwell
  2012-06-29  0:55 ` [PATCH net-next 1/4] tcp: fix inet6_csk_route_req() for link-local addresses David Miller
  3 siblings, 1 reply; 8+ messages in thread
From: Neal Cardwell @ 2012-06-28 22:34 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Eric Dumazet, Neal Cardwell

With the recent change (earlier in this patch series) to set
flowi6_oif to treq->iif in inet6_csk_route_req(), the dst lookup in
these two functions is now identical, so tcp_v6_send_synack() can now
just call inet6_csk_route_req(), to reduce code duplication and keep
things closer to the IPv4 side, which is structured this way.

Signed-off-by: Neal Cardwell <ncardwell@google.com>
---
 net/ipv6/tcp_ipv6.c |   29 ++++++-----------------------
 1 files changed, 6 insertions(+), 23 deletions(-)

diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 3b79e94..c221086 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -485,34 +485,17 @@ static int tcp_v6_send_synack(struct sock *sk,
 	struct inet6_request_sock *treq = inet6_rsk(req);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct sk_buff * skb;
-	struct ipv6_txoptions *opt = NULL;
-	struct in6_addr * final_p, final;
+	struct ipv6_txoptions *opt = np->opt;
 	struct flowi6 fl6;
 	struct dst_entry *dst;
-	int err;
-
-	memset(&fl6, 0, sizeof(fl6));
-	fl6.flowi6_proto = IPPROTO_TCP;
-	fl6.daddr = treq->rmt_addr;
-	fl6.saddr = treq->loc_addr;
-	fl6.flowlabel = 0;
-	fl6.flowi6_oif = treq->iif;
-	fl6.flowi6_mark = sk->sk_mark;
-	fl6.fl6_dport = inet_rsk(req)->rmt_port;
-	fl6.fl6_sport = inet_rsk(req)->loc_port;
-	security_req_classify_flow(req, flowi6_to_flowi(&fl6));
-
-	opt = np->opt;
-	final_p = fl6_update_dst(&fl6, opt, &final);
+	int err = -ENOMEM;
 
-	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
-	if (IS_ERR(dst)) {
-		err = PTR_ERR(dst);
-		dst = NULL;
+	dst = inet6_csk_route_req(sk, &fl6, req);
+	if (!dst)
 		goto done;
-	}
+
 	skb = tcp_make_synack(sk, dst, req, rvp);
-	err = -ENOMEM;
+
 	if (skb) {
 		__tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
 
-- 
1.7.4.1

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

* [PATCH net-next 4/4] tcp: plug dst leak in tcp_v6_conn_request()
  2012-06-28 22:34 [PATCH net-next 1/4] tcp: fix inet6_csk_route_req() for link-local addresses Neal Cardwell
  2012-06-28 22:34 ` [PATCH net-next 2/4] tcp: pass fl6 to inet6_csk_route_req() Neal Cardwell
  2012-06-28 22:34 ` [PATCH net-next 3/4] tcp: use inet6_csk_route_req() in tcp_v6_send_synack() Neal Cardwell
@ 2012-06-28 22:34 ` Neal Cardwell
  2012-06-29  0:55   ` David Miller
  2012-06-29  0:55 ` [PATCH net-next 1/4] tcp: fix inet6_csk_route_req() for link-local addresses David Miller
  3 siblings, 1 reply; 8+ messages in thread
From: Neal Cardwell @ 2012-06-28 22:34 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Eric Dumazet, Neal Cardwell

The code in tcp_v6_conn_request() was implicitly assuming that
tcp_v6_send_synack() would take care of dst_release(), much as
tcp_v4_send_synack() already does. This resulted in
tcp_v6_conn_request() leaking a dst if sysctl_tw_recycle is enabled.

This commit restructures tcp_v6_send_synack() so that it accepts a dst
pointer and takes care of releasing the dst that is passed in, to plug
the leak and avoid future surprises by bringing the IPv6 behavior in
line with the IPv4 side.

Signed-off-by: Neal Cardwell <ncardwell@google.com>
---
 net/ipv6/tcp_ipv6.c |   19 ++++++++++---------
 1 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index c221086..5edabf6 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -477,7 +477,8 @@ out:
 }
 
 
-static int tcp_v6_send_synack(struct sock *sk,
+static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst,
+			      struct flowi6 *fl6,
 			      struct request_sock *req,
 			      struct request_values *rvp,
 			      u16 queue_mapping)
@@ -486,12 +487,10 @@ static int tcp_v6_send_synack(struct sock *sk,
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct sk_buff * skb;
 	struct ipv6_txoptions *opt = np->opt;
-	struct flowi6 fl6;
-	struct dst_entry *dst;
 	int err = -ENOMEM;
 
-	dst = inet6_csk_route_req(sk, &fl6, req);
-	if (!dst)
+	/* First, grab a route. */
+	if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL)
 		goto done;
 
 	skb = tcp_make_synack(sk, dst, req, rvp);
@@ -499,9 +498,9 @@ static int tcp_v6_send_synack(struct sock *sk,
 	if (skb) {
 		__tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
 
-		fl6.daddr = treq->rmt_addr;
+		fl6->daddr = treq->rmt_addr;
 		skb_set_queue_mapping(skb, queue_mapping);
-		err = ip6_xmit(sk, skb, &fl6, opt, np->tclass);
+		err = ip6_xmit(sk, skb, fl6, opt, np->tclass);
 		err = net_xmit_eval(err);
 	}
 
@@ -514,8 +513,10 @@ done:
 static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req,
 			     struct request_values *rvp)
 {
+	struct flowi6 fl6;
+
 	TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
-	return tcp_v6_send_synack(sk, req, rvp, 0);
+	return tcp_v6_send_synack(sk, NULL, &fl6, req, rvp, 0);
 }
 
 static void tcp_v6_reqsk_destructor(struct request_sock *req)
@@ -1200,7 +1201,7 @@ have_isn:
 
 	security_inet_conn_request(sk, skb, req);
 
-	if (tcp_v6_send_synack(sk, req,
+	if (tcp_v6_send_synack(sk, dst, &fl6, req,
 			       (struct request_values *)&tmp_ext,
 			       skb_get_queue_mapping(skb)) ||
 	    want_cookie)
-- 
1.7.4.1

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

* Re: [PATCH net-next 1/4] tcp: fix inet6_csk_route_req() for link-local addresses
  2012-06-28 22:34 [PATCH net-next 1/4] tcp: fix inet6_csk_route_req() for link-local addresses Neal Cardwell
                   ` (2 preceding siblings ...)
  2012-06-28 22:34 ` [PATCH net-next 4/4] tcp: plug dst leak in tcp_v6_conn_request() Neal Cardwell
@ 2012-06-29  0:55 ` David Miller
  3 siblings, 0 replies; 8+ messages in thread
From: David Miller @ 2012-06-29  0:55 UTC (permalink / raw)
  To: ncardwell; +Cc: netdev, edumazet

From: Neal Cardwell <ncardwell@google.com>
Date: Thu, 28 Jun 2012 15:34:18 -0700

> Fix inet6_csk_route_req() to use as the flowi6_oif the treq->iif,
> which is correctly fixed up in tcp_v6_conn_request() to handle the
> case of link-local addresses. This brings it in line with the
> tcp_v6_send_synack() code, which is already correctly using the
> treq->iif in this way.
> 
> Signed-off-by: Neal Cardwell <ncardwell@google.com>

Applied.

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

* Re: [PATCH net-next 2/4] tcp: pass fl6 to inet6_csk_route_req()
  2012-06-28 22:34 ` [PATCH net-next 2/4] tcp: pass fl6 to inet6_csk_route_req() Neal Cardwell
@ 2012-06-29  0:55   ` David Miller
  0 siblings, 0 replies; 8+ messages in thread
From: David Miller @ 2012-06-29  0:55 UTC (permalink / raw)
  To: ncardwell; +Cc: netdev, edumazet

From: Neal Cardwell <ncardwell@google.com>
Date: Thu, 28 Jun 2012 15:34:19 -0700

> This commit changes inet_csk_route_req() so that it uses a pointer to
> a struct flowi6, rather than allocating its own on the stack. This
> brings its behavior in line with its IPv4 cousin,
> inet_csk_route_req(), and allows a follow-on patch to fix a dst leak.
> 
> Signed-off-by: Neal Cardwell <ncardwell@google.com>

Applied.

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

* Re: [PATCH net-next 3/4] tcp: use inet6_csk_route_req() in tcp_v6_send_synack()
  2012-06-28 22:34 ` [PATCH net-next 3/4] tcp: use inet6_csk_route_req() in tcp_v6_send_synack() Neal Cardwell
@ 2012-06-29  0:55   ` David Miller
  0 siblings, 0 replies; 8+ messages in thread
From: David Miller @ 2012-06-29  0:55 UTC (permalink / raw)
  To: ncardwell; +Cc: netdev, edumazet

From: Neal Cardwell <ncardwell@google.com>
Date: Thu, 28 Jun 2012 15:34:20 -0700

> With the recent change (earlier in this patch series) to set
> flowi6_oif to treq->iif in inet6_csk_route_req(), the dst lookup in
> these two functions is now identical, so tcp_v6_send_synack() can now
> just call inet6_csk_route_req(), to reduce code duplication and keep
> things closer to the IPv4 side, which is structured this way.
> 
> Signed-off-by: Neal Cardwell <ncardwell@google.com>

Applied.

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

* Re: [PATCH net-next 4/4] tcp: plug dst leak in tcp_v6_conn_request()
  2012-06-28 22:34 ` [PATCH net-next 4/4] tcp: plug dst leak in tcp_v6_conn_request() Neal Cardwell
@ 2012-06-29  0:55   ` David Miller
  0 siblings, 0 replies; 8+ messages in thread
From: David Miller @ 2012-06-29  0:55 UTC (permalink / raw)
  To: ncardwell; +Cc: netdev, edumazet

From: Neal Cardwell <ncardwell@google.com>
Date: Thu, 28 Jun 2012 15:34:21 -0700

> The code in tcp_v6_conn_request() was implicitly assuming that
> tcp_v6_send_synack() would take care of dst_release(), much as
> tcp_v4_send_synack() already does. This resulted in
> tcp_v6_conn_request() leaking a dst if sysctl_tw_recycle is enabled.
> 
> This commit restructures tcp_v6_send_synack() so that it accepts a dst
> pointer and takes care of releasing the dst that is passed in, to plug
> the leak and avoid future surprises by bringing the IPv6 behavior in
> line with the IPv4 side.
> 
> Signed-off-by: Neal Cardwell <ncardwell@google.com>

Applied.

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

end of thread, other threads:[~2012-06-29  0:55 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-06-28 22:34 [PATCH net-next 1/4] tcp: fix inet6_csk_route_req() for link-local addresses Neal Cardwell
2012-06-28 22:34 ` [PATCH net-next 2/4] tcp: pass fl6 to inet6_csk_route_req() Neal Cardwell
2012-06-29  0:55   ` David Miller
2012-06-28 22:34 ` [PATCH net-next 3/4] tcp: use inet6_csk_route_req() in tcp_v6_send_synack() Neal Cardwell
2012-06-29  0:55   ` David Miller
2012-06-28 22:34 ` [PATCH net-next 4/4] tcp: plug dst leak in tcp_v6_conn_request() Neal Cardwell
2012-06-29  0:55   ` David Miller
2012-06-29  0:55 ` [PATCH net-next 1/4] tcp: fix inet6_csk_route_req() for link-local addresses David 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).