All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net 0/3]  sctp: a bunch of fixes by holding transport
@ 2016-10-28 10:10 ` Xin Long
  0 siblings, 0 replies; 24+ messages in thread
From: Xin Long @ 2016-10-28 10:10 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: davem, Marcelo Ricardo Leitner, Vlad Yasevich, daniel

There are several places where it holds assoc after getting transport by
searching from transport rhashtable, it may cause use-after- free issue.

This patchset is to fix them by holding transport instead.

Xin Long (3):
  sctp: hold transport instead of assoc in sctp_diag
  sctp: return back transport in __sctp_rcv_init_lookup
  sctp: hold transport instead of assoc when lookup assoc in rx path

 include/net/sctp/sctp.h |  2 +-
 net/sctp/input.c        | 35 +++++++++++++++++------------------
 net/sctp/ipv6.c         |  2 +-
 net/sctp/socket.c       |  5 +----
 4 files changed, 20 insertions(+), 24 deletions(-)

-- 
2.1.0

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

* [PATCH net 0/3]  sctp: a bunch of fixes by holding transport
@ 2016-10-28 10:10 ` Xin Long
  0 siblings, 0 replies; 24+ messages in thread
From: Xin Long @ 2016-10-28 10:10 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: davem, Marcelo Ricardo Leitner, Vlad Yasevich, daniel

There are several places where it holds assoc after getting transport by
searching from transport rhashtable, it may cause use-after- free issue.

This patchset is to fix them by holding transport instead.

Xin Long (3):
  sctp: hold transport instead of assoc in sctp_diag
  sctp: return back transport in __sctp_rcv_init_lookup
  sctp: hold transport instead of assoc when lookup assoc in rx path

 include/net/sctp/sctp.h |  2 +-
 net/sctp/input.c        | 35 +++++++++++++++++------------------
 net/sctp/ipv6.c         |  2 +-
 net/sctp/socket.c       |  5 +----
 4 files changed, 20 insertions(+), 24 deletions(-)

-- 
2.1.0


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

* [PATCH net 1/3] sctp: hold transport instead of assoc in sctp_diag
  2016-10-28 10:10 ` Xin Long
@ 2016-10-28 10:10   ` Xin Long
  -1 siblings, 0 replies; 24+ messages in thread
From: Xin Long @ 2016-10-28 10:10 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: davem, Marcelo Ricardo Leitner, Vlad Yasevich, daniel

In sctp_transport_lookup_process(), Commit 1cceda784980 ("sctp: fix
the issue sctp_diag uses lock_sock in rcu_read_lock") moved cb() out
of rcu lock, but it put transport and hold assoc instead, and ignore
that cb() still uses transport. It may cause a use-after-free issue.

This patch is to hold transport instead of assoc there.

Fixes: 1cceda784980 ("sctp: fix the issue sctp_diag uses lock_sock in rcu_read_lock")
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 net/sctp/socket.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 9fbb6fe..71b75f9 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4480,12 +4480,9 @@ int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *),
 	if (!transport || !sctp_transport_hold(transport))
 		goto out;
 
-	sctp_association_hold(transport->asoc);
-	sctp_transport_put(transport);
-
 	rcu_read_unlock();
 	err = cb(transport, p);
-	sctp_association_put(transport->asoc);
+	sctp_transport_put(transport);
 
 out:
 	return err;
-- 
2.1.0

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

* [PATCH net 1/3] sctp: hold transport instead of assoc in sctp_diag
@ 2016-10-28 10:10   ` Xin Long
  0 siblings, 0 replies; 24+ messages in thread
From: Xin Long @ 2016-10-28 10:10 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: davem, Marcelo Ricardo Leitner, Vlad Yasevich, daniel

In sctp_transport_lookup_process(), Commit 1cceda784980 ("sctp: fix
the issue sctp_diag uses lock_sock in rcu_read_lock") moved cb() out
of rcu lock, but it put transport and hold assoc instead, and ignore
that cb() still uses transport. It may cause a use-after-free issue.

This patch is to hold transport instead of assoc there.

Fixes: 1cceda784980 ("sctp: fix the issue sctp_diag uses lock_sock in rcu_read_lock")
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 net/sctp/socket.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 9fbb6fe..71b75f9 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4480,12 +4480,9 @@ int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *),
 	if (!transport || !sctp_transport_hold(transport))
 		goto out;
 
-	sctp_association_hold(transport->asoc);
-	sctp_transport_put(transport);
-
 	rcu_read_unlock();
 	err = cb(transport, p);
-	sctp_association_put(transport->asoc);
+	sctp_transport_put(transport);
 
 out:
 	return err;
-- 
2.1.0


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

* [PATCH net 2/3] sctp: return back transport in __sctp_rcv_init_lookup
  2016-10-28 10:10   ` Xin Long
@ 2016-10-28 10:10     ` Xin Long
  -1 siblings, 0 replies; 24+ messages in thread
From: Xin Long @ 2016-10-28 10:10 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: davem, Marcelo Ricardo Leitner, Vlad Yasevich, daniel

Prior to this patch, it used a local variable to save the transport that is
looked up by __sctp_lookup_association(), and didn't return it back. But in
sctp_rcv, it is used to initialize chunk->transport. So when hitting this
code, it was initializing chunk->transport with some random stack value
instead.

This patch is to return the transport back through transport pointer
that is from __sctp_rcv_lookup_harder().

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 net/sctp/input.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/net/sctp/input.c b/net/sctp/input.c
index a2ea1d1..8e0bc58 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -1021,7 +1021,6 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
 	struct sctphdr *sh = sctp_hdr(skb);
 	union sctp_params params;
 	sctp_init_chunk_t *init;
-	struct sctp_transport *transport;
 	struct sctp_af *af;
 
 	/*
@@ -1052,7 +1051,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
 
 		af->from_addr_param(paddr, params.addr, sh->source, 0);
 
-		asoc = __sctp_lookup_association(net, laddr, paddr, &transport);
+		asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
 		if (asoc)
 			return asoc;
 	}
-- 
2.1.0

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

* [PATCH net 2/3] sctp: return back transport in __sctp_rcv_init_lookup
@ 2016-10-28 10:10     ` Xin Long
  0 siblings, 0 replies; 24+ messages in thread
From: Xin Long @ 2016-10-28 10:10 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: davem, Marcelo Ricardo Leitner, Vlad Yasevich, daniel

Prior to this patch, it used a local variable to save the transport that is
looked up by __sctp_lookup_association(), and didn't return it back. But in
sctp_rcv, it is used to initialize chunk->transport. So when hitting this
code, it was initializing chunk->transport with some random stack value
instead.

This patch is to return the transport back through transport pointer
that is from __sctp_rcv_lookup_harder().

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 net/sctp/input.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/net/sctp/input.c b/net/sctp/input.c
index a2ea1d1..8e0bc58 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -1021,7 +1021,6 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
 	struct sctphdr *sh = sctp_hdr(skb);
 	union sctp_params params;
 	sctp_init_chunk_t *init;
-	struct sctp_transport *transport;
 	struct sctp_af *af;
 
 	/*
@@ -1052,7 +1051,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
 
 		af->from_addr_param(paddr, params.addr, sh->source, 0);
 
-		asoc = __sctp_lookup_association(net, laddr, paddr, &transport);
+		asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
 		if (asoc)
 			return asoc;
 	}
-- 
2.1.0


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

* [PATCH net 3/3] sctp: hold transport instead of assoc when lookup assoc in rx path
  2016-10-28 10:10     ` Xin Long
@ 2016-10-28 10:10       ` Xin Long
  -1 siblings, 0 replies; 24+ messages in thread
From: Xin Long @ 2016-10-28 10:10 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: davem, Marcelo Ricardo Leitner, Vlad Yasevich, daniel

Prior to this patch, in rx path, before calling lock_sock, it needed to
hold assoc when got it by __sctp_lookup_association, in case other place
would free/put assoc.

But in __sctp_lookup_association, it lookup and hold transport, then got
assoc by transport->assoc, then hold assoc and put transport. It means
it didn't hold transport, yet it was returned and later on directly
assigned to chunk->transport.

Without the protection of sock lock, the transport may be freed/put by
other places, which would cause a use-after-free issue.

This patch is to fix this issue by holding transport instead of assoc.
As holding transport can make sure to access assoc is also safe, and
actually it looks up assoc by searching transport rhashtable, to hold
transport here makes more sense.

Note that the function will be renamed later on on another patch.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sctp.h |  2 +-
 net/sctp/input.c        | 32 ++++++++++++++++----------------
 net/sctp/ipv6.c         |  2 +-
 3 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 87a7f42..31acc3f 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -152,7 +152,7 @@ void sctp_unhash_endpoint(struct sctp_endpoint *);
 struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *,
 			     struct sctphdr *, struct sctp_association **,
 			     struct sctp_transport **);
-void sctp_err_finish(struct sock *, struct sctp_association *);
+void sctp_err_finish(struct sock *, struct sctp_transport *);
 void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
 			   struct sctp_transport *t, __u32 pmtu);
 void sctp_icmp_redirect(struct sock *, struct sctp_transport *,
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 8e0bc58..a01a56e 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -181,9 +181,10 @@ int sctp_rcv(struct sk_buff *skb)
 	 * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB
 	 */
 	if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb))) {
-		if (asoc) {
-			sctp_association_put(asoc);
+		if (transport) {
+			sctp_transport_put(transport);
 			asoc = NULL;
+			transport = NULL;
 		} else {
 			sctp_endpoint_put(ep);
 			ep = NULL;
@@ -269,8 +270,8 @@ int sctp_rcv(struct sk_buff *skb)
 	bh_unlock_sock(sk);
 
 	/* Release the asoc/ep ref we took in the lookup calls. */
-	if (asoc)
-		sctp_association_put(asoc);
+	if (transport)
+		sctp_transport_put(transport);
 	else
 		sctp_endpoint_put(ep);
 
@@ -283,8 +284,8 @@ int sctp_rcv(struct sk_buff *skb)
 
 discard_release:
 	/* Release the asoc/ep ref we took in the lookup calls. */
-	if (asoc)
-		sctp_association_put(asoc);
+	if (transport)
+		sctp_transport_put(transport);
 	else
 		sctp_endpoint_put(ep);
 
@@ -300,6 +301,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 {
 	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
 	struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
+	struct sctp_transport *t = chunk->transport;
 	struct sctp_ep_common *rcvr = NULL;
 	int backloged = 0;
 
@@ -351,7 +353,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 done:
 	/* Release the refs we took in sctp_add_backlog */
 	if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
-		sctp_association_put(sctp_assoc(rcvr));
+		sctp_transport_put(t);
 	else if (SCTP_EP_TYPE_SOCKET == rcvr->type)
 		sctp_endpoint_put(sctp_ep(rcvr));
 	else
@@ -363,6 +365,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
 {
 	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
+	struct sctp_transport *t = chunk->transport;
 	struct sctp_ep_common *rcvr = chunk->rcvr;
 	int ret;
 
@@ -373,7 +376,7 @@ static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
 		 * from us
 		 */
 		if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
-			sctp_association_hold(sctp_assoc(rcvr));
+			sctp_transport_hold(t);
 		else if (SCTP_EP_TYPE_SOCKET == rcvr->type)
 			sctp_endpoint_hold(sctp_ep(rcvr));
 		else
@@ -537,15 +540,15 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
 	return sk;
 
 out:
-	sctp_association_put(asoc);
+	sctp_transport_put(transport);
 	return NULL;
 }
 
 /* Common cleanup code for icmp/icmpv6 error handler. */
-void sctp_err_finish(struct sock *sk, struct sctp_association *asoc)
+void sctp_err_finish(struct sock *sk, struct sctp_transport *t)
 {
 	bh_unlock_sock(sk);
-	sctp_association_put(asoc);
+	sctp_transport_put(t);
 }
 
 /*
@@ -641,7 +644,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
 	}
 
 out_unlock:
-	sctp_err_finish(sk, asoc);
+	sctp_err_finish(sk, transport);
 }
 
 /*
@@ -952,11 +955,8 @@ static struct sctp_association *__sctp_lookup_association(
 		goto out;
 
 	asoc = t->asoc;
-	sctp_association_hold(asoc);
 	*pt = t;
 
-	sctp_transport_put(t);
-
 out:
 	return asoc;
 }
@@ -986,7 +986,7 @@ int sctp_has_association(struct net *net,
 	struct sctp_transport *transport;
 
 	if ((asoc = sctp_lookup_association(net, laddr, paddr, &transport))) {
-		sctp_association_put(asoc);
+		sctp_transport_put(transport);
 		return 1;
 	}
 
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index f473779..176af30 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -198,7 +198,7 @@ static void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	}
 
 out_unlock:
-	sctp_err_finish(sk, asoc);
+	sctp_err_finish(sk, transport);
 out:
 	if (likely(idev != NULL))
 		in6_dev_put(idev);
-- 
2.1.0

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

* [PATCH net 3/3] sctp: hold transport instead of assoc when lookup assoc in rx path
@ 2016-10-28 10:10       ` Xin Long
  0 siblings, 0 replies; 24+ messages in thread
From: Xin Long @ 2016-10-28 10:10 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: davem, Marcelo Ricardo Leitner, Vlad Yasevich, daniel

Prior to this patch, in rx path, before calling lock_sock, it needed to
hold assoc when got it by __sctp_lookup_association, in case other place
would free/put assoc.

But in __sctp_lookup_association, it lookup and hold transport, then got
assoc by transport->assoc, then hold assoc and put transport. It means
it didn't hold transport, yet it was returned and later on directly
assigned to chunk->transport.

Without the protection of sock lock, the transport may be freed/put by
other places, which would cause a use-after-free issue.

This patch is to fix this issue by holding transport instead of assoc.
As holding transport can make sure to access assoc is also safe, and
actually it looks up assoc by searching transport rhashtable, to hold
transport here makes more sense.

Note that the function will be renamed later on on another patch.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sctp.h |  2 +-
 net/sctp/input.c        | 32 ++++++++++++++++----------------
 net/sctp/ipv6.c         |  2 +-
 3 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 87a7f42..31acc3f 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -152,7 +152,7 @@ void sctp_unhash_endpoint(struct sctp_endpoint *);
 struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *,
 			     struct sctphdr *, struct sctp_association **,
 			     struct sctp_transport **);
-void sctp_err_finish(struct sock *, struct sctp_association *);
+void sctp_err_finish(struct sock *, struct sctp_transport *);
 void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
 			   struct sctp_transport *t, __u32 pmtu);
 void sctp_icmp_redirect(struct sock *, struct sctp_transport *,
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 8e0bc58..a01a56e 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -181,9 +181,10 @@ int sctp_rcv(struct sk_buff *skb)
 	 * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB
 	 */
 	if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb))) {
-		if (asoc) {
-			sctp_association_put(asoc);
+		if (transport) {
+			sctp_transport_put(transport);
 			asoc = NULL;
+			transport = NULL;
 		} else {
 			sctp_endpoint_put(ep);
 			ep = NULL;
@@ -269,8 +270,8 @@ int sctp_rcv(struct sk_buff *skb)
 	bh_unlock_sock(sk);
 
 	/* Release the asoc/ep ref we took in the lookup calls. */
-	if (asoc)
-		sctp_association_put(asoc);
+	if (transport)
+		sctp_transport_put(transport);
 	else
 		sctp_endpoint_put(ep);
 
@@ -283,8 +284,8 @@ int sctp_rcv(struct sk_buff *skb)
 
 discard_release:
 	/* Release the asoc/ep ref we took in the lookup calls. */
-	if (asoc)
-		sctp_association_put(asoc);
+	if (transport)
+		sctp_transport_put(transport);
 	else
 		sctp_endpoint_put(ep);
 
@@ -300,6 +301,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 {
 	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
 	struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
+	struct sctp_transport *t = chunk->transport;
 	struct sctp_ep_common *rcvr = NULL;
 	int backloged = 0;
 
@@ -351,7 +353,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 done:
 	/* Release the refs we took in sctp_add_backlog */
 	if (SCTP_EP_TYPE_ASSOCIATION = rcvr->type)
-		sctp_association_put(sctp_assoc(rcvr));
+		sctp_transport_put(t);
 	else if (SCTP_EP_TYPE_SOCKET = rcvr->type)
 		sctp_endpoint_put(sctp_ep(rcvr));
 	else
@@ -363,6 +365,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
 {
 	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
+	struct sctp_transport *t = chunk->transport;
 	struct sctp_ep_common *rcvr = chunk->rcvr;
 	int ret;
 
@@ -373,7 +376,7 @@ static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
 		 * from us
 		 */
 		if (SCTP_EP_TYPE_ASSOCIATION = rcvr->type)
-			sctp_association_hold(sctp_assoc(rcvr));
+			sctp_transport_hold(t);
 		else if (SCTP_EP_TYPE_SOCKET = rcvr->type)
 			sctp_endpoint_hold(sctp_ep(rcvr));
 		else
@@ -537,15 +540,15 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
 	return sk;
 
 out:
-	sctp_association_put(asoc);
+	sctp_transport_put(transport);
 	return NULL;
 }
 
 /* Common cleanup code for icmp/icmpv6 error handler. */
-void sctp_err_finish(struct sock *sk, struct sctp_association *asoc)
+void sctp_err_finish(struct sock *sk, struct sctp_transport *t)
 {
 	bh_unlock_sock(sk);
-	sctp_association_put(asoc);
+	sctp_transport_put(t);
 }
 
 /*
@@ -641,7 +644,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
 	}
 
 out_unlock:
-	sctp_err_finish(sk, asoc);
+	sctp_err_finish(sk, transport);
 }
 
 /*
@@ -952,11 +955,8 @@ static struct sctp_association *__sctp_lookup_association(
 		goto out;
 
 	asoc = t->asoc;
-	sctp_association_hold(asoc);
 	*pt = t;
 
-	sctp_transport_put(t);
-
 out:
 	return asoc;
 }
@@ -986,7 +986,7 @@ int sctp_has_association(struct net *net,
 	struct sctp_transport *transport;
 
 	if ((asoc = sctp_lookup_association(net, laddr, paddr, &transport))) {
-		sctp_association_put(asoc);
+		sctp_transport_put(transport);
 		return 1;
 	}
 
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index f473779..176af30 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -198,7 +198,7 @@ static void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	}
 
 out_unlock:
-	sctp_err_finish(sk, asoc);
+	sctp_err_finish(sk, transport);
 out:
 	if (likely(idev != NULL))
 		in6_dev_put(idev);
-- 
2.1.0


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

* Re: [PATCH net 1/3] sctp: hold transport instead of assoc in sctp_diag
  2016-10-28 10:10   ` Xin Long
@ 2016-10-28 14:01     ` Neil Horman
  -1 siblings, 0 replies; 24+ messages in thread
From: Neil Horman @ 2016-10-28 14:01 UTC (permalink / raw)
  To: Xin Long
  Cc: network dev, linux-sctp, davem, Marcelo Ricardo Leitner,
	Vlad Yasevich, daniel

On Fri, Oct 28, 2016 at 06:10:52PM +0800, Xin Long wrote:
> In sctp_transport_lookup_process(), Commit 1cceda784980 ("sctp: fix
> the issue sctp_diag uses lock_sock in rcu_read_lock") moved cb() out
> of rcu lock, but it put transport and hold assoc instead, and ignore
> that cb() still uses transport. It may cause a use-after-free issue.
> 
> This patch is to hold transport instead of assoc there.
> 
> Fixes: 1cceda784980 ("sctp: fix the issue sctp_diag uses lock_sock in rcu_read_lock")
> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> ---
>  net/sctp/socket.c | 5 +----
>  1 file changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 9fbb6fe..71b75f9 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -4480,12 +4480,9 @@ int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *),
>  	if (!transport || !sctp_transport_hold(transport))
>  		goto out;
>  
> -	sctp_association_hold(transport->asoc);
> -	sctp_transport_put(transport);
> -
>  	rcu_read_unlock();
>  	err = cb(transport, p);
> -	sctp_association_put(transport->asoc);
> +	sctp_transport_put(transport);
>  
>  out:
>  	return err;
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>

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

* Re: [PATCH net 1/3] sctp: hold transport instead of assoc in sctp_diag
@ 2016-10-28 14:01     ` Neil Horman
  0 siblings, 0 replies; 24+ messages in thread
From: Neil Horman @ 2016-10-28 14:01 UTC (permalink / raw)
  To: Xin Long
  Cc: network dev, linux-sctp, davem, Marcelo Ricardo Leitner,
	Vlad Yasevich, daniel

On Fri, Oct 28, 2016 at 06:10:52PM +0800, Xin Long wrote:
> In sctp_transport_lookup_process(), Commit 1cceda784980 ("sctp: fix
> the issue sctp_diag uses lock_sock in rcu_read_lock") moved cb() out
> of rcu lock, but it put transport and hold assoc instead, and ignore
> that cb() still uses transport. It may cause a use-after-free issue.
> 
> This patch is to hold transport instead of assoc there.
> 
> Fixes: 1cceda784980 ("sctp: fix the issue sctp_diag uses lock_sock in rcu_read_lock")
> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> ---
>  net/sctp/socket.c | 5 +----
>  1 file changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 9fbb6fe..71b75f9 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -4480,12 +4480,9 @@ int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *),
>  	if (!transport || !sctp_transport_hold(transport))
>  		goto out;
>  
> -	sctp_association_hold(transport->asoc);
> -	sctp_transport_put(transport);
> -
>  	rcu_read_unlock();
>  	err = cb(transport, p);
> -	sctp_association_put(transport->asoc);
> +	sctp_transport_put(transport);
>  
>  out:
>  	return err;
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>


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

* Re: [PATCH net 2/3] sctp: return back transport in __sctp_rcv_init_lookup
  2016-10-28 10:10     ` Xin Long
@ 2016-10-28 14:03       ` Neil Horman
  -1 siblings, 0 replies; 24+ messages in thread
From: Neil Horman @ 2016-10-28 14:03 UTC (permalink / raw)
  To: Xin Long
  Cc: network dev, linux-sctp, davem, Marcelo Ricardo Leitner,
	Vlad Yasevich, daniel

On Fri, Oct 28, 2016 at 06:10:53PM +0800, Xin Long wrote:
> Prior to this patch, it used a local variable to save the transport that is
> looked up by __sctp_lookup_association(), and didn't return it back. But in
> sctp_rcv, it is used to initialize chunk->transport. So when hitting this
> code, it was initializing chunk->transport with some random stack value
> instead.
> 
> This patch is to return the transport back through transport pointer
> that is from __sctp_rcv_lookup_harder().
> 
> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> ---
>  net/sctp/input.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index a2ea1d1..8e0bc58 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -1021,7 +1021,6 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
>  	struct sctphdr *sh = sctp_hdr(skb);
>  	union sctp_params params;
>  	sctp_init_chunk_t *init;
> -	struct sctp_transport *transport;
>  	struct sctp_af *af;
>  
>  	/*
> @@ -1052,7 +1051,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
>  
>  		af->from_addr_param(paddr, params.addr, sh->source, 0);
>  
> -		asoc = __sctp_lookup_association(net, laddr, paddr, &transport);
> +		asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
>  		if (asoc)
>  			return asoc;
>  	}
> -- 
> 2.1.0
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>

> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH net 2/3] sctp: return back transport in __sctp_rcv_init_lookup
@ 2016-10-28 14:03       ` Neil Horman
  0 siblings, 0 replies; 24+ messages in thread
From: Neil Horman @ 2016-10-28 14:03 UTC (permalink / raw)
  To: Xin Long
  Cc: network dev, linux-sctp, davem, Marcelo Ricardo Leitner,
	Vlad Yasevich, daniel

On Fri, Oct 28, 2016 at 06:10:53PM +0800, Xin Long wrote:
> Prior to this patch, it used a local variable to save the transport that is
> looked up by __sctp_lookup_association(), and didn't return it back. But in
> sctp_rcv, it is used to initialize chunk->transport. So when hitting this
> code, it was initializing chunk->transport with some random stack value
> instead.
> 
> This patch is to return the transport back through transport pointer
> that is from __sctp_rcv_lookup_harder().
> 
> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> ---
>  net/sctp/input.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index a2ea1d1..8e0bc58 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -1021,7 +1021,6 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
>  	struct sctphdr *sh = sctp_hdr(skb);
>  	union sctp_params params;
>  	sctp_init_chunk_t *init;
> -	struct sctp_transport *transport;
>  	struct sctp_af *af;
>  
>  	/*
> @@ -1052,7 +1051,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
>  
>  		af->from_addr_param(paddr, params.addr, sh->source, 0);
>  
> -		asoc = __sctp_lookup_association(net, laddr, paddr, &transport);
> +		asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
>  		if (asoc)
>  			return asoc;
>  	}
> -- 
> 2.1.0
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>

> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH net 3/3] sctp: hold transport instead of assoc when lookup assoc in rx path
  2016-10-28 10:10       ` Xin Long
@ 2016-10-28 14:13         ` Neil Horman
  -1 siblings, 0 replies; 24+ messages in thread
From: Neil Horman @ 2016-10-28 14:13 UTC (permalink / raw)
  To: Xin Long
  Cc: network dev, linux-sctp, davem, Marcelo Ricardo Leitner,
	Vlad Yasevich, daniel

On Fri, Oct 28, 2016 at 06:10:54PM +0800, Xin Long wrote:
> Prior to this patch, in rx path, before calling lock_sock, it needed to
> hold assoc when got it by __sctp_lookup_association, in case other place
> would free/put assoc.
> 
> But in __sctp_lookup_association, it lookup and hold transport, then got
> assoc by transport->assoc, then hold assoc and put transport. It means
> it didn't hold transport, yet it was returned and later on directly
> assigned to chunk->transport.
> 
> Without the protection of sock lock, the transport may be freed/put by
> other places, which would cause a use-after-free issue.
> 
> This patch is to fix this issue by holding transport instead of assoc.
> As holding transport can make sure to access assoc is also safe, and
> actually it looks up assoc by searching transport rhashtable, to hold
> transport here makes more sense.
> 
> Note that the function will be renamed later on on another patch.
> 
> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> ---
>  include/net/sctp/sctp.h |  2 +-
>  net/sctp/input.c        | 32 ++++++++++++++++----------------
>  net/sctp/ipv6.c         |  2 +-
>  3 files changed, 18 insertions(+), 18 deletions(-)
> 
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 87a7f42..31acc3f 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -152,7 +152,7 @@ void sctp_unhash_endpoint(struct sctp_endpoint *);
>  struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *,
>  			     struct sctphdr *, struct sctp_association **,
>  			     struct sctp_transport **);
> -void sctp_err_finish(struct sock *, struct sctp_association *);
> +void sctp_err_finish(struct sock *, struct sctp_transport *);
>  void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
>  			   struct sctp_transport *t, __u32 pmtu);
>  void sctp_icmp_redirect(struct sock *, struct sctp_transport *,
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index 8e0bc58..a01a56e 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -181,9 +181,10 @@ int sctp_rcv(struct sk_buff *skb)
>  	 * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB
>  	 */
>  	if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb))) {
> -		if (asoc) {
> -			sctp_association_put(asoc);
> +		if (transport) {
> +			sctp_transport_put(transport);
>  			asoc = NULL;
> +			transport = NULL;
>  		} else {
>  			sctp_endpoint_put(ep);
>  			ep = NULL;
> @@ -269,8 +270,8 @@ int sctp_rcv(struct sk_buff *skb)
>  	bh_unlock_sock(sk);
>  
>  	/* Release the asoc/ep ref we took in the lookup calls. */
> -	if (asoc)
> -		sctp_association_put(asoc);
> +	if (transport)
> +		sctp_transport_put(transport);
>  	else
>  		sctp_endpoint_put(ep);
>  
> @@ -283,8 +284,8 @@ int sctp_rcv(struct sk_buff *skb)
>  
>  discard_release:
>  	/* Release the asoc/ep ref we took in the lookup calls. */
> -	if (asoc)
> -		sctp_association_put(asoc);
> +	if (transport)
> +		sctp_transport_put(transport);
>  	else
>  		sctp_endpoint_put(ep);
>  
> @@ -300,6 +301,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
>  {
>  	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
>  	struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
> +	struct sctp_transport *t = chunk->transport;
>  	struct sctp_ep_common *rcvr = NULL;
>  	int backloged = 0;
>  
> @@ -351,7 +353,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
>  done:
>  	/* Release the refs we took in sctp_add_backlog */
>  	if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
> -		sctp_association_put(sctp_assoc(rcvr));
> +		sctp_transport_put(t);
>  	else if (SCTP_EP_TYPE_SOCKET == rcvr->type)
>  		sctp_endpoint_put(sctp_ep(rcvr));
>  	else
> @@ -363,6 +365,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
>  static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
>  {
>  	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
> +	struct sctp_transport *t = chunk->transport;
>  	struct sctp_ep_common *rcvr = chunk->rcvr;
>  	int ret;
>  
> @@ -373,7 +376,7 @@ static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
>  		 * from us
>  		 */
>  		if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
> -			sctp_association_hold(sctp_assoc(rcvr));
> +			sctp_transport_hold(t);
>  		else if (SCTP_EP_TYPE_SOCKET == rcvr->type)
>  			sctp_endpoint_hold(sctp_ep(rcvr));
>  		else
> @@ -537,15 +540,15 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
>  	return sk;
>  
>  out:
> -	sctp_association_put(asoc);
> +	sctp_transport_put(transport);
>  	return NULL;
>  }
>  
>  /* Common cleanup code for icmp/icmpv6 error handler. */
> -void sctp_err_finish(struct sock *sk, struct sctp_association *asoc)
> +void sctp_err_finish(struct sock *sk, struct sctp_transport *t)
>  {
>  	bh_unlock_sock(sk);
> -	sctp_association_put(asoc);
> +	sctp_transport_put(t);
>  }
>  
>  /*
> @@ -641,7 +644,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
>  	}
>  
>  out_unlock:
> -	sctp_err_finish(sk, asoc);
> +	sctp_err_finish(sk, transport);
>  }
>  
>  /*
> @@ -952,11 +955,8 @@ static struct sctp_association *__sctp_lookup_association(
>  		goto out;
>  
>  	asoc = t->asoc;
> -	sctp_association_hold(asoc);
>  	*pt = t;
>  
> -	sctp_transport_put(t);
> -
>  out:
>  	return asoc;
>  }
> @@ -986,7 +986,7 @@ int sctp_has_association(struct net *net,
>  	struct sctp_transport *transport;
>  
>  	if ((asoc = sctp_lookup_association(net, laddr, paddr, &transport))) {
> -		sctp_association_put(asoc);
> +		sctp_transport_put(transport);
>  		return 1;
>  	}
>  
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index f473779..176af30 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -198,7 +198,7 @@ static void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
>  	}
>  
>  out_unlock:
> -	sctp_err_finish(sk, asoc);
> +	sctp_err_finish(sk, transport);
>  out:
>  	if (likely(idev != NULL))
>  		in6_dev_put(idev);
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>

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

* Re: [PATCH net 3/3] sctp: hold transport instead of assoc when lookup assoc in rx path
@ 2016-10-28 14:13         ` Neil Horman
  0 siblings, 0 replies; 24+ messages in thread
From: Neil Horman @ 2016-10-28 14:13 UTC (permalink / raw)
  To: Xin Long
  Cc: network dev, linux-sctp, davem, Marcelo Ricardo Leitner,
	Vlad Yasevich, daniel

On Fri, Oct 28, 2016 at 06:10:54PM +0800, Xin Long wrote:
> Prior to this patch, in rx path, before calling lock_sock, it needed to
> hold assoc when got it by __sctp_lookup_association, in case other place
> would free/put assoc.
> 
> But in __sctp_lookup_association, it lookup and hold transport, then got
> assoc by transport->assoc, then hold assoc and put transport. It means
> it didn't hold transport, yet it was returned and later on directly
> assigned to chunk->transport.
> 
> Without the protection of sock lock, the transport may be freed/put by
> other places, which would cause a use-after-free issue.
> 
> This patch is to fix this issue by holding transport instead of assoc.
> As holding transport can make sure to access assoc is also safe, and
> actually it looks up assoc by searching transport rhashtable, to hold
> transport here makes more sense.
> 
> Note that the function will be renamed later on on another patch.
> 
> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> ---
>  include/net/sctp/sctp.h |  2 +-
>  net/sctp/input.c        | 32 ++++++++++++++++----------------
>  net/sctp/ipv6.c         |  2 +-
>  3 files changed, 18 insertions(+), 18 deletions(-)
> 
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 87a7f42..31acc3f 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -152,7 +152,7 @@ void sctp_unhash_endpoint(struct sctp_endpoint *);
>  struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *,
>  			     struct sctphdr *, struct sctp_association **,
>  			     struct sctp_transport **);
> -void sctp_err_finish(struct sock *, struct sctp_association *);
> +void sctp_err_finish(struct sock *, struct sctp_transport *);
>  void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
>  			   struct sctp_transport *t, __u32 pmtu);
>  void sctp_icmp_redirect(struct sock *, struct sctp_transport *,
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index 8e0bc58..a01a56e 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -181,9 +181,10 @@ int sctp_rcv(struct sk_buff *skb)
>  	 * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB
>  	 */
>  	if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb))) {
> -		if (asoc) {
> -			sctp_association_put(asoc);
> +		if (transport) {
> +			sctp_transport_put(transport);
>  			asoc = NULL;
> +			transport = NULL;
>  		} else {
>  			sctp_endpoint_put(ep);
>  			ep = NULL;
> @@ -269,8 +270,8 @@ int sctp_rcv(struct sk_buff *skb)
>  	bh_unlock_sock(sk);
>  
>  	/* Release the asoc/ep ref we took in the lookup calls. */
> -	if (asoc)
> -		sctp_association_put(asoc);
> +	if (transport)
> +		sctp_transport_put(transport);
>  	else
>  		sctp_endpoint_put(ep);
>  
> @@ -283,8 +284,8 @@ int sctp_rcv(struct sk_buff *skb)
>  
>  discard_release:
>  	/* Release the asoc/ep ref we took in the lookup calls. */
> -	if (asoc)
> -		sctp_association_put(asoc);
> +	if (transport)
> +		sctp_transport_put(transport);
>  	else
>  		sctp_endpoint_put(ep);
>  
> @@ -300,6 +301,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
>  {
>  	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
>  	struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
> +	struct sctp_transport *t = chunk->transport;
>  	struct sctp_ep_common *rcvr = NULL;
>  	int backloged = 0;
>  
> @@ -351,7 +353,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
>  done:
>  	/* Release the refs we took in sctp_add_backlog */
>  	if (SCTP_EP_TYPE_ASSOCIATION = rcvr->type)
> -		sctp_association_put(sctp_assoc(rcvr));
> +		sctp_transport_put(t);
>  	else if (SCTP_EP_TYPE_SOCKET = rcvr->type)
>  		sctp_endpoint_put(sctp_ep(rcvr));
>  	else
> @@ -363,6 +365,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
>  static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
>  {
>  	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
> +	struct sctp_transport *t = chunk->transport;
>  	struct sctp_ep_common *rcvr = chunk->rcvr;
>  	int ret;
>  
> @@ -373,7 +376,7 @@ static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
>  		 * from us
>  		 */
>  		if (SCTP_EP_TYPE_ASSOCIATION = rcvr->type)
> -			sctp_association_hold(sctp_assoc(rcvr));
> +			sctp_transport_hold(t);
>  		else if (SCTP_EP_TYPE_SOCKET = rcvr->type)
>  			sctp_endpoint_hold(sctp_ep(rcvr));
>  		else
> @@ -537,15 +540,15 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
>  	return sk;
>  
>  out:
> -	sctp_association_put(asoc);
> +	sctp_transport_put(transport);
>  	return NULL;
>  }
>  
>  /* Common cleanup code for icmp/icmpv6 error handler. */
> -void sctp_err_finish(struct sock *sk, struct sctp_association *asoc)
> +void sctp_err_finish(struct sock *sk, struct sctp_transport *t)
>  {
>  	bh_unlock_sock(sk);
> -	sctp_association_put(asoc);
> +	sctp_transport_put(t);
>  }
>  
>  /*
> @@ -641,7 +644,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
>  	}
>  
>  out_unlock:
> -	sctp_err_finish(sk, asoc);
> +	sctp_err_finish(sk, transport);
>  }
>  
>  /*
> @@ -952,11 +955,8 @@ static struct sctp_association *__sctp_lookup_association(
>  		goto out;
>  
>  	asoc = t->asoc;
> -	sctp_association_hold(asoc);
>  	*pt = t;
>  
> -	sctp_transport_put(t);
> -
>  out:
>  	return asoc;
>  }
> @@ -986,7 +986,7 @@ int sctp_has_association(struct net *net,
>  	struct sctp_transport *transport;
>  
>  	if ((asoc = sctp_lookup_association(net, laddr, paddr, &transport))) {
> -		sctp_association_put(asoc);
> +		sctp_transport_put(transport);
>  		return 1;
>  	}
>  
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index f473779..176af30 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -198,7 +198,7 @@ static void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
>  	}
>  
>  out_unlock:
> -	sctp_err_finish(sk, asoc);
> +	sctp_err_finish(sk, transport);
>  out:
>  	if (likely(idev != NULL))
>  		in6_dev_put(idev);
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>


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

* Re: [PATCH net 1/3] sctp: hold transport instead of assoc in sctp_diag
  2016-10-28 10:10   ` Xin Long
@ 2016-10-28 19:25     ` Marcelo Ricardo Leitner
  -1 siblings, 0 replies; 24+ messages in thread
From: Marcelo Ricardo Leitner @ 2016-10-28 19:25 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev, linux-sctp, davem, Vlad Yasevich, daniel

On Fri, Oct 28, 2016 at 06:10:52PM +0800, Xin Long wrote:
> In sctp_transport_lookup_process(), Commit 1cceda784980 ("sctp: fix
> the issue sctp_diag uses lock_sock in rcu_read_lock") moved cb() out
> of rcu lock, but it put transport and hold assoc instead, and ignore
> that cb() still uses transport. It may cause a use-after-free issue.
> 
> This patch is to hold transport instead of assoc there.
> 
> Fixes: 1cceda784980 ("sctp: fix the issue sctp_diag uses lock_sock in rcu_read_lock")
> Signed-off-by: Xin Long <lucien.xin@gmail.com>

Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>

> ---
>  net/sctp/socket.c | 5 +----
>  1 file changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 9fbb6fe..71b75f9 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -4480,12 +4480,9 @@ int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *),
>  	if (!transport || !sctp_transport_hold(transport))
>  		goto out;
>  
> -	sctp_association_hold(transport->asoc);
> -	sctp_transport_put(transport);
> -
>  	rcu_read_unlock();
>  	err = cb(transport, p);
> -	sctp_association_put(transport->asoc);
> +	sctp_transport_put(transport);
>  
>  out:
>  	return err;
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH net 1/3] sctp: hold transport instead of assoc in sctp_diag
@ 2016-10-28 19:25     ` Marcelo Ricardo Leitner
  0 siblings, 0 replies; 24+ messages in thread
From: Marcelo Ricardo Leitner @ 2016-10-28 19:25 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev, linux-sctp, davem, Vlad Yasevich, daniel

On Fri, Oct 28, 2016 at 06:10:52PM +0800, Xin Long wrote:
> In sctp_transport_lookup_process(), Commit 1cceda784980 ("sctp: fix
> the issue sctp_diag uses lock_sock in rcu_read_lock") moved cb() out
> of rcu lock, but it put transport and hold assoc instead, and ignore
> that cb() still uses transport. It may cause a use-after-free issue.
> 
> This patch is to hold transport instead of assoc there.
> 
> Fixes: 1cceda784980 ("sctp: fix the issue sctp_diag uses lock_sock in rcu_read_lock")
> Signed-off-by: Xin Long <lucien.xin@gmail.com>

Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>

> ---
>  net/sctp/socket.c | 5 +----
>  1 file changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 9fbb6fe..71b75f9 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -4480,12 +4480,9 @@ int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *),
>  	if (!transport || !sctp_transport_hold(transport))
>  		goto out;
>  
> -	sctp_association_hold(transport->asoc);
> -	sctp_transport_put(transport);
> -
>  	rcu_read_unlock();
>  	err = cb(transport, p);
> -	sctp_association_put(transport->asoc);
> +	sctp_transport_put(transport);
>  
>  out:
>  	return err;
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH net 2/3] sctp: return back transport in __sctp_rcv_init_lookup
  2016-10-28 10:10     ` Xin Long
@ 2016-10-28 19:42       ` Marcelo Ricardo Leitner
  -1 siblings, 0 replies; 24+ messages in thread
From: Marcelo Ricardo Leitner @ 2016-10-28 19:42 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev, linux-sctp, davem, Vlad Yasevich, daniel

On Fri, Oct 28, 2016 at 06:10:53PM +0800, Xin Long wrote:
> Prior to this patch, it used a local variable to save the transport that is
> looked up by __sctp_lookup_association(), and didn't return it back. But in
> sctp_rcv, it is used to initialize chunk->transport. So when hitting this
> code, it was initializing chunk->transport with some random stack value
> instead.
> 
> This patch is to return the transport back through transport pointer
> that is from __sctp_rcv_lookup_harder().
> 
> Signed-off-by: Xin Long <lucien.xin@gmail.com>

Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>

transport pointer in sctp_rcv() is initialized to null and there are
checks for it after this path, so this shouldn't be exploitable, just
malfunction.

> ---
>  net/sctp/input.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index a2ea1d1..8e0bc58 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -1021,7 +1021,6 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
>  	struct sctphdr *sh = sctp_hdr(skb);
>  	union sctp_params params;
>  	sctp_init_chunk_t *init;
> -	struct sctp_transport *transport;
>  	struct sctp_af *af;
>  
>  	/*
> @@ -1052,7 +1051,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
>  
>  		af->from_addr_param(paddr, params.addr, sh->source, 0);
>  
> -		asoc = __sctp_lookup_association(net, laddr, paddr, &transport);
> +		asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
>  		if (asoc)
>  			return asoc;
>  	}
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH net 2/3] sctp: return back transport in __sctp_rcv_init_lookup
@ 2016-10-28 19:42       ` Marcelo Ricardo Leitner
  0 siblings, 0 replies; 24+ messages in thread
From: Marcelo Ricardo Leitner @ 2016-10-28 19:42 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev, linux-sctp, davem, Vlad Yasevich, daniel

On Fri, Oct 28, 2016 at 06:10:53PM +0800, Xin Long wrote:
> Prior to this patch, it used a local variable to save the transport that is
> looked up by __sctp_lookup_association(), and didn't return it back. But in
> sctp_rcv, it is used to initialize chunk->transport. So when hitting this
> code, it was initializing chunk->transport with some random stack value
> instead.
> 
> This patch is to return the transport back through transport pointer
> that is from __sctp_rcv_lookup_harder().
> 
> Signed-off-by: Xin Long <lucien.xin@gmail.com>

Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>

transport pointer in sctp_rcv() is initialized to null and there are
checks for it after this path, so this shouldn't be exploitable, just
malfunction.

> ---
>  net/sctp/input.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index a2ea1d1..8e0bc58 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -1021,7 +1021,6 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
>  	struct sctphdr *sh = sctp_hdr(skb);
>  	union sctp_params params;
>  	sctp_init_chunk_t *init;
> -	struct sctp_transport *transport;
>  	struct sctp_af *af;
>  
>  	/*
> @@ -1052,7 +1051,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
>  
>  		af->from_addr_param(paddr, params.addr, sh->source, 0);
>  
> -		asoc = __sctp_lookup_association(net, laddr, paddr, &transport);
> +		asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
>  		if (asoc)
>  			return asoc;
>  	}
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH net 3/3] sctp: hold transport instead of assoc when lookup assoc in rx path
  2016-10-28 10:10       ` Xin Long
@ 2016-10-28 19:57         ` Marcelo Ricardo Leitner
  -1 siblings, 0 replies; 24+ messages in thread
From: Marcelo Ricardo Leitner @ 2016-10-28 19:57 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev, linux-sctp, davem, Vlad Yasevich, daniel

On Fri, Oct 28, 2016 at 06:10:54PM +0800, Xin Long wrote:
> Prior to this patch, in rx path, before calling lock_sock, it needed to
> hold assoc when got it by __sctp_lookup_association, in case other place
> would free/put assoc.
> 
> But in __sctp_lookup_association, it lookup and hold transport, then got
> assoc by transport->assoc, then hold assoc and put transport. It means
> it didn't hold transport, yet it was returned and later on directly
> assigned to chunk->transport.
> 
> Without the protection of sock lock, the transport may be freed/put by
> other places, which would cause a use-after-free issue.
> 
> This patch is to fix this issue by holding transport instead of assoc.
> As holding transport can make sure to access assoc is also safe, and
> actually it looks up assoc by searching transport rhashtable, to hold
> transport here makes more sense.
> 
> Note that the function will be renamed later on on another patch.
> 
> Signed-off-by: Xin Long <lucien.xin@gmail.com>

Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>

> ---
>  include/net/sctp/sctp.h |  2 +-
>  net/sctp/input.c        | 32 ++++++++++++++++----------------
>  net/sctp/ipv6.c         |  2 +-
>  3 files changed, 18 insertions(+), 18 deletions(-)
> 
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 87a7f42..31acc3f 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -152,7 +152,7 @@ void sctp_unhash_endpoint(struct sctp_endpoint *);
>  struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *,
>  			     struct sctphdr *, struct sctp_association **,
>  			     struct sctp_transport **);
> -void sctp_err_finish(struct sock *, struct sctp_association *);
> +void sctp_err_finish(struct sock *, struct sctp_transport *);
>  void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
>  			   struct sctp_transport *t, __u32 pmtu);
>  void sctp_icmp_redirect(struct sock *, struct sctp_transport *,
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index 8e0bc58..a01a56e 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -181,9 +181,10 @@ int sctp_rcv(struct sk_buff *skb)
>  	 * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB
>  	 */
>  	if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb))) {
> -		if (asoc) {
> -			sctp_association_put(asoc);
> +		if (transport) {
> +			sctp_transport_put(transport);
>  			asoc = NULL;
> +			transport = NULL;
>  		} else {
>  			sctp_endpoint_put(ep);
>  			ep = NULL;
> @@ -269,8 +270,8 @@ int sctp_rcv(struct sk_buff *skb)
>  	bh_unlock_sock(sk);
>  
>  	/* Release the asoc/ep ref we took in the lookup calls. */
> -	if (asoc)
> -		sctp_association_put(asoc);
> +	if (transport)
> +		sctp_transport_put(transport);
>  	else
>  		sctp_endpoint_put(ep);
>  
> @@ -283,8 +284,8 @@ int sctp_rcv(struct sk_buff *skb)
>  
>  discard_release:
>  	/* Release the asoc/ep ref we took in the lookup calls. */
> -	if (asoc)
> -		sctp_association_put(asoc);
> +	if (transport)
> +		sctp_transport_put(transport);
>  	else
>  		sctp_endpoint_put(ep);
>  
> @@ -300,6 +301,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
>  {
>  	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
>  	struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
> +	struct sctp_transport *t = chunk->transport;
>  	struct sctp_ep_common *rcvr = NULL;
>  	int backloged = 0;
>  
> @@ -351,7 +353,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
>  done:
>  	/* Release the refs we took in sctp_add_backlog */
>  	if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
> -		sctp_association_put(sctp_assoc(rcvr));
> +		sctp_transport_put(t);
>  	else if (SCTP_EP_TYPE_SOCKET == rcvr->type)
>  		sctp_endpoint_put(sctp_ep(rcvr));
>  	else
> @@ -363,6 +365,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
>  static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
>  {
>  	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
> +	struct sctp_transport *t = chunk->transport;
>  	struct sctp_ep_common *rcvr = chunk->rcvr;
>  	int ret;
>  
> @@ -373,7 +376,7 @@ static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
>  		 * from us
>  		 */
>  		if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
> -			sctp_association_hold(sctp_assoc(rcvr));
> +			sctp_transport_hold(t);
>  		else if (SCTP_EP_TYPE_SOCKET == rcvr->type)
>  			sctp_endpoint_hold(sctp_ep(rcvr));
>  		else
> @@ -537,15 +540,15 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
>  	return sk;
>  
>  out:
> -	sctp_association_put(asoc);
> +	sctp_transport_put(transport);
>  	return NULL;
>  }
>  
>  /* Common cleanup code for icmp/icmpv6 error handler. */
> -void sctp_err_finish(struct sock *sk, struct sctp_association *asoc)
> +void sctp_err_finish(struct sock *sk, struct sctp_transport *t)
>  {
>  	bh_unlock_sock(sk);
> -	sctp_association_put(asoc);
> +	sctp_transport_put(t);
>  }
>  
>  /*
> @@ -641,7 +644,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
>  	}
>  
>  out_unlock:
> -	sctp_err_finish(sk, asoc);
> +	sctp_err_finish(sk, transport);
>  }
>  
>  /*
> @@ -952,11 +955,8 @@ static struct sctp_association *__sctp_lookup_association(
>  		goto out;
>  
>  	asoc = t->asoc;
> -	sctp_association_hold(asoc);
>  	*pt = t;
>  
> -	sctp_transport_put(t);
> -
>  out:
>  	return asoc;
>  }
> @@ -986,7 +986,7 @@ int sctp_has_association(struct net *net,
>  	struct sctp_transport *transport;
>  
>  	if ((asoc = sctp_lookup_association(net, laddr, paddr, &transport))) {
> -		sctp_association_put(asoc);
> +		sctp_transport_put(transport);
>  		return 1;
>  	}
>  
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index f473779..176af30 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -198,7 +198,7 @@ static void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
>  	}
>  
>  out_unlock:
> -	sctp_err_finish(sk, asoc);
> +	sctp_err_finish(sk, transport);
>  out:
>  	if (likely(idev != NULL))
>  		in6_dev_put(idev);
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH net 3/3] sctp: hold transport instead of assoc when lookup assoc in rx path
@ 2016-10-28 19:57         ` Marcelo Ricardo Leitner
  0 siblings, 0 replies; 24+ messages in thread
From: Marcelo Ricardo Leitner @ 2016-10-28 19:57 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev, linux-sctp, davem, Vlad Yasevich, daniel

On Fri, Oct 28, 2016 at 06:10:54PM +0800, Xin Long wrote:
> Prior to this patch, in rx path, before calling lock_sock, it needed to
> hold assoc when got it by __sctp_lookup_association, in case other place
> would free/put assoc.
> 
> But in __sctp_lookup_association, it lookup and hold transport, then got
> assoc by transport->assoc, then hold assoc and put transport. It means
> it didn't hold transport, yet it was returned and later on directly
> assigned to chunk->transport.
> 
> Without the protection of sock lock, the transport may be freed/put by
> other places, which would cause a use-after-free issue.
> 
> This patch is to fix this issue by holding transport instead of assoc.
> As holding transport can make sure to access assoc is also safe, and
> actually it looks up assoc by searching transport rhashtable, to hold
> transport here makes more sense.
> 
> Note that the function will be renamed later on on another patch.
> 
> Signed-off-by: Xin Long <lucien.xin@gmail.com>

Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>

> ---
>  include/net/sctp/sctp.h |  2 +-
>  net/sctp/input.c        | 32 ++++++++++++++++----------------
>  net/sctp/ipv6.c         |  2 +-
>  3 files changed, 18 insertions(+), 18 deletions(-)
> 
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 87a7f42..31acc3f 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -152,7 +152,7 @@ void sctp_unhash_endpoint(struct sctp_endpoint *);
>  struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *,
>  			     struct sctphdr *, struct sctp_association **,
>  			     struct sctp_transport **);
> -void sctp_err_finish(struct sock *, struct sctp_association *);
> +void sctp_err_finish(struct sock *, struct sctp_transport *);
>  void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
>  			   struct sctp_transport *t, __u32 pmtu);
>  void sctp_icmp_redirect(struct sock *, struct sctp_transport *,
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index 8e0bc58..a01a56e 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -181,9 +181,10 @@ int sctp_rcv(struct sk_buff *skb)
>  	 * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB
>  	 */
>  	if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb))) {
> -		if (asoc) {
> -			sctp_association_put(asoc);
> +		if (transport) {
> +			sctp_transport_put(transport);
>  			asoc = NULL;
> +			transport = NULL;
>  		} else {
>  			sctp_endpoint_put(ep);
>  			ep = NULL;
> @@ -269,8 +270,8 @@ int sctp_rcv(struct sk_buff *skb)
>  	bh_unlock_sock(sk);
>  
>  	/* Release the asoc/ep ref we took in the lookup calls. */
> -	if (asoc)
> -		sctp_association_put(asoc);
> +	if (transport)
> +		sctp_transport_put(transport);
>  	else
>  		sctp_endpoint_put(ep);
>  
> @@ -283,8 +284,8 @@ int sctp_rcv(struct sk_buff *skb)
>  
>  discard_release:
>  	/* Release the asoc/ep ref we took in the lookup calls. */
> -	if (asoc)
> -		sctp_association_put(asoc);
> +	if (transport)
> +		sctp_transport_put(transport);
>  	else
>  		sctp_endpoint_put(ep);
>  
> @@ -300,6 +301,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
>  {
>  	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
>  	struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
> +	struct sctp_transport *t = chunk->transport;
>  	struct sctp_ep_common *rcvr = NULL;
>  	int backloged = 0;
>  
> @@ -351,7 +353,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
>  done:
>  	/* Release the refs we took in sctp_add_backlog */
>  	if (SCTP_EP_TYPE_ASSOCIATION = rcvr->type)
> -		sctp_association_put(sctp_assoc(rcvr));
> +		sctp_transport_put(t);
>  	else if (SCTP_EP_TYPE_SOCKET = rcvr->type)
>  		sctp_endpoint_put(sctp_ep(rcvr));
>  	else
> @@ -363,6 +365,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
>  static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
>  {
>  	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
> +	struct sctp_transport *t = chunk->transport;
>  	struct sctp_ep_common *rcvr = chunk->rcvr;
>  	int ret;
>  
> @@ -373,7 +376,7 @@ static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
>  		 * from us
>  		 */
>  		if (SCTP_EP_TYPE_ASSOCIATION = rcvr->type)
> -			sctp_association_hold(sctp_assoc(rcvr));
> +			sctp_transport_hold(t);
>  		else if (SCTP_EP_TYPE_SOCKET = rcvr->type)
>  			sctp_endpoint_hold(sctp_ep(rcvr));
>  		else
> @@ -537,15 +540,15 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
>  	return sk;
>  
>  out:
> -	sctp_association_put(asoc);
> +	sctp_transport_put(transport);
>  	return NULL;
>  }
>  
>  /* Common cleanup code for icmp/icmpv6 error handler. */
> -void sctp_err_finish(struct sock *sk, struct sctp_association *asoc)
> +void sctp_err_finish(struct sock *sk, struct sctp_transport *t)
>  {
>  	bh_unlock_sock(sk);
> -	sctp_association_put(asoc);
> +	sctp_transport_put(t);
>  }
>  
>  /*
> @@ -641,7 +644,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
>  	}
>  
>  out_unlock:
> -	sctp_err_finish(sk, asoc);
> +	sctp_err_finish(sk, transport);
>  }
>  
>  /*
> @@ -952,11 +955,8 @@ static struct sctp_association *__sctp_lookup_association(
>  		goto out;
>  
>  	asoc = t->asoc;
> -	sctp_association_hold(asoc);
>  	*pt = t;
>  
> -	sctp_transport_put(t);
> -
>  out:
>  	return asoc;
>  }
> @@ -986,7 +986,7 @@ int sctp_has_association(struct net *net,
>  	struct sctp_transport *transport;
>  
>  	if ((asoc = sctp_lookup_association(net, laddr, paddr, &transport))) {
> -		sctp_association_put(asoc);
> +		sctp_transport_put(transport);
>  		return 1;
>  	}
>  
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index f473779..176af30 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -198,7 +198,7 @@ static void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
>  	}
>  
>  out_unlock:
> -	sctp_err_finish(sk, asoc);
> +	sctp_err_finish(sk, transport);
>  out:
>  	if (likely(idev != NULL))
>  		in6_dev_put(idev);
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH net 2/3] sctp: return back transport in __sctp_rcv_init_lookup
  2016-10-28 19:42       ` Marcelo Ricardo Leitner
@ 2016-10-28 21:39         ` Marcelo Ricardo Leitner
  -1 siblings, 0 replies; 24+ messages in thread
From: Marcelo Ricardo Leitner @ 2016-10-28 21:39 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev, linux-sctp, davem, Vlad Yasevich, daniel

On Fri, Oct 28, 2016 at 05:42:21PM -0200, Marcelo Ricardo Leitner wrote:
> On Fri, Oct 28, 2016 at 06:10:53PM +0800, Xin Long wrote:
> > Prior to this patch, it used a local variable to save the transport that is
> > looked up by __sctp_lookup_association(), and didn't return it back. But in
> > sctp_rcv, it is used to initialize chunk->transport. So when hitting this
> > code, it was initializing chunk->transport with some random stack value
> > instead.
> > 
> > This patch is to return the transport back through transport pointer
> > that is from __sctp_rcv_lookup_harder().
> > 
> > Signed-off-by: Xin Long <lucien.xin@gmail.com>
> 
> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> 
> transport pointer in sctp_rcv() is initialized to null and there are
> checks for it after this path, so this shouldn't be exploitable, just
> malfunction.

This actually sort of contradicts the changelog.

Xin, did I miss something here? Seems we need to update the changelog if
not.

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

* Re: [PATCH net 2/3] sctp: return back transport in __sctp_rcv_init_lookup
@ 2016-10-28 21:39         ` Marcelo Ricardo Leitner
  0 siblings, 0 replies; 24+ messages in thread
From: Marcelo Ricardo Leitner @ 2016-10-28 21:39 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev, linux-sctp, davem, Vlad Yasevich, daniel

On Fri, Oct 28, 2016 at 05:42:21PM -0200, Marcelo Ricardo Leitner wrote:
> On Fri, Oct 28, 2016 at 06:10:53PM +0800, Xin Long wrote:
> > Prior to this patch, it used a local variable to save the transport that is
> > looked up by __sctp_lookup_association(), and didn't return it back. But in
> > sctp_rcv, it is used to initialize chunk->transport. So when hitting this
> > code, it was initializing chunk->transport with some random stack value
> > instead.
> > 
> > This patch is to return the transport back through transport pointer
> > that is from __sctp_rcv_lookup_harder().
> > 
> > Signed-off-by: Xin Long <lucien.xin@gmail.com>
> 
> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> 
> transport pointer in sctp_rcv() is initialized to null and there are
> checks for it after this path, so this shouldn't be exploitable, just
> malfunction.

This actually sort of contradicts the changelog.

Xin, did I miss something here? Seems we need to update the changelog if
not.


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

* Re: [PATCH net 2/3] sctp: return back transport in __sctp_rcv_init_lookup
  2016-10-28 21:39         ` Marcelo Ricardo Leitner
@ 2016-10-29 17:29           ` Xin Long
  -1 siblings, 0 replies; 24+ messages in thread
From: Xin Long @ 2016-10-29 17:29 UTC (permalink / raw)
  To: Marcelo Ricardo Leitner
  Cc: network dev, linux-sctp, davem, Vlad Yasevich, Daniel Borkmann

On Sat, Oct 29, 2016 at 5:39 AM, Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
> On Fri, Oct 28, 2016 at 05:42:21PM -0200, Marcelo Ricardo Leitner wrote:
>> On Fri, Oct 28, 2016 at 06:10:53PM +0800, Xin Long wrote:
>> > Prior to this patch, it used a local variable to save the transport that is
>> > looked up by __sctp_lookup_association(), and didn't return it back. But in
>> > sctp_rcv, it is used to initialize chunk->transport. So when hitting this
>> > code, it was initializing chunk->transport with some random stack value
>> > instead.
here should be:
So when hitting this, even if it found the transport, it was still initializing
chunk->transport with null instead.

>> >
>> > This patch is to return the transport back through transport pointer
>> > that is from __sctp_rcv_lookup_harder().
>> >
>> > Signed-off-by: Xin Long <lucien.xin@gmail.com>
>>
>> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
>>
>> transport pointer in sctp_rcv() is initialized to null and there are
>> checks for it after this path, so this shouldn't be exploitable, just
>> malfunction.
>
> This actually sort of contradicts the changelog.
>
> Xin, did I miss something here? Seems we need to update the changelog if
> not.
>
You're right, thanks, will repost.

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

* Re: [PATCH net 2/3] sctp: return back transport in __sctp_rcv_init_lookup
@ 2016-10-29 17:29           ` Xin Long
  0 siblings, 0 replies; 24+ messages in thread
From: Xin Long @ 2016-10-29 17:29 UTC (permalink / raw)
  To: Marcelo Ricardo Leitner
  Cc: network dev, linux-sctp, davem, Vlad Yasevich, Daniel Borkmann

On Sat, Oct 29, 2016 at 5:39 AM, Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
> On Fri, Oct 28, 2016 at 05:42:21PM -0200, Marcelo Ricardo Leitner wrote:
>> On Fri, Oct 28, 2016 at 06:10:53PM +0800, Xin Long wrote:
>> > Prior to this patch, it used a local variable to save the transport that is
>> > looked up by __sctp_lookup_association(), and didn't return it back. But in
>> > sctp_rcv, it is used to initialize chunk->transport. So when hitting this
>> > code, it was initializing chunk->transport with some random stack value
>> > instead.
here should be:
So when hitting this, even if it found the transport, it was still initializing
chunk->transport with null instead.

>> >
>> > This patch is to return the transport back through transport pointer
>> > that is from __sctp_rcv_lookup_harder().
>> >
>> > Signed-off-by: Xin Long <lucien.xin@gmail.com>
>>
>> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
>>
>> transport pointer in sctp_rcv() is initialized to null and there are
>> checks for it after this path, so this shouldn't be exploitable, just
>> malfunction.
>
> This actually sort of contradicts the changelog.
>
> Xin, did I miss something here? Seems we need to update the changelog if
> not.
>
You're right, thanks, will repost.

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

end of thread, other threads:[~2016-10-29 17:29 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-28 10:10 [PATCH net 0/3] sctp: a bunch of fixes by holding transport Xin Long
2016-10-28 10:10 ` Xin Long
2016-10-28 10:10 ` [PATCH net 1/3] sctp: hold transport instead of assoc in sctp_diag Xin Long
2016-10-28 10:10   ` Xin Long
2016-10-28 10:10   ` [PATCH net 2/3] sctp: return back transport in __sctp_rcv_init_lookup Xin Long
2016-10-28 10:10     ` Xin Long
2016-10-28 10:10     ` [PATCH net 3/3] sctp: hold transport instead of assoc when lookup assoc in rx path Xin Long
2016-10-28 10:10       ` Xin Long
2016-10-28 14:13       ` Neil Horman
2016-10-28 14:13         ` Neil Horman
2016-10-28 19:57       ` Marcelo Ricardo Leitner
2016-10-28 19:57         ` Marcelo Ricardo Leitner
2016-10-28 14:03     ` [PATCH net 2/3] sctp: return back transport in __sctp_rcv_init_lookup Neil Horman
2016-10-28 14:03       ` Neil Horman
2016-10-28 19:42     ` Marcelo Ricardo Leitner
2016-10-28 19:42       ` Marcelo Ricardo Leitner
2016-10-28 21:39       ` Marcelo Ricardo Leitner
2016-10-28 21:39         ` Marcelo Ricardo Leitner
2016-10-29 17:29         ` Xin Long
2016-10-29 17:29           ` Xin Long
2016-10-28 14:01   ` [PATCH net 1/3] sctp: hold transport instead of assoc in sctp_diag Neil Horman
2016-10-28 14:01     ` Neil Horman
2016-10-28 19:25   ` Marcelo Ricardo Leitner
2016-10-28 19:25     ` Marcelo Ricardo Leitner

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.