stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/2] sctp: export sctp_endpoint_{hold,put}() and return incremented endpoint
@ 2021-12-17 13:46 Lee Jones
  2021-12-17 13:46 ` [PATCH v2 2/2] sctp: hold cached endpoints to prevent possible UAF Lee Jones
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Lee Jones @ 2021-12-17 13:46 UTC (permalink / raw)
  To: lee.jones
  Cc: linux-kernel, Vlad Yasevich, Neil Horman,
	Marcelo Ricardo Leitner, David S. Miller, Jakub Kicinski,
	lksctp developers, H.P. Yarroll, Karl Knutson, Jon Grimm,
	Xingang Guo, Hui Huang, Sridhar Samudrala, Daisy Chang,
	Ryan Layer, Kevin Gao, netdev, stable

net/sctp/diag.c for instance is built into its own separate module
(sctp_diag.ko) and requires the use of sctp_endpoint_{hold,put}() in
order to prevent a recently found use-after-free issue.

In order to prevent data corruption of the pointer used to take a
reference on a specific endpoint, between the time of calling
sctp_endpoint_hold() and it returning, the API now returns a pointer
to the exact endpoint that was incremented.

For example, in sctp_sock_dump(), we could have the following hunk:

	sctp_endpoint_hold(tsp->asoc->ep);
	ep = tsp->asoc->ep;
	sk = ep->base.sk
	lock_sock(ep->base.sk);

It is possible for this task to be swapped out immediately following
the call into sctp_endpoint_hold() that would change the address of
tsp->asoc->ep to point to a completely different endpoint.  This means
a reference could be taken to the old endpoint and the new one would
be processed without a reference taken, moreover the new endpoint
could then be freed whilst still processing as a result, causing a
use-after-free.

If we return the exact pointer that was held, we ensure this task
processes only the endpoint we have taken a reference to.  The
resultant hunk now looks like this:

        ep = sctp_endpoint_hold(tsp->asoc->ep);
	sk = ep->base.sk
	lock_sock(sk);

Cc: Vlad Yasevich <vyasevich@gmail.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: lksctp developers <linux-sctp@vger.kernel.org>
Cc: "H.P. Yarroll" <piggy@acm.org>
Cc: Karl Knutson <karl@athena.chicago.il.us>
Cc: Jon Grimm <jgrimm@us.ibm.com>
Cc: Xingang Guo <xingang.guo@intel.com>
Cc: Hui Huang <hui.huang@nokia.com>
Cc: Sridhar Samudrala <sri@us.ibm.com>
Cc: Daisy Chang <daisyc@us.ibm.com>
Cc: Ryan Layer <rmlayer@us.ibm.com>
Cc: Kevin Gao <kevin.gao@intel.com>
Cc: linux-sctp@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: stable@vger.kernel.org
Fixes: 8f840e47f190c ("sctp: add the sctp_diag.c file")
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 include/net/sctp/structs.h | 2 +-
 net/sctp/endpointola.c     | 5 ++++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 651bba654d77d..78d71ca56452b 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1380,7 +1380,7 @@ static inline struct sctp_endpoint *sctp_ep(struct sctp_ep_common *base)
 struct sctp_endpoint *sctp_endpoint_new(struct sock *, gfp_t);
 void sctp_endpoint_free(struct sctp_endpoint *);
 void sctp_endpoint_put(struct sctp_endpoint *);
-void sctp_endpoint_hold(struct sctp_endpoint *);
+struct sctp_endpoint *sctp_endpoint_hold(struct sctp_endpoint *);
 void sctp_endpoint_add_asoc(struct sctp_endpoint *, struct sctp_association *);
 struct sctp_association *sctp_endpoint_lookup_assoc(
 	const struct sctp_endpoint *ep,
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 48c9c2c7602f7..bdbf74fc7eb4c 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -222,10 +222,12 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
 }
 
 /* Hold a reference to an endpoint. */
-void sctp_endpoint_hold(struct sctp_endpoint *ep)
+struct sctp_endpoint *sctp_endpoint_hold(struct sctp_endpoint *ep)
 {
 	refcount_inc(&ep->base.refcnt);
+	return ep;
 }
+EXPORT_SYMBOL_GPL(sctp_endpoint_hold);
 
 /* Release a reference to an endpoint and clean up if there are
  * no more references.
@@ -235,6 +237,7 @@ void sctp_endpoint_put(struct sctp_endpoint *ep)
 	if (refcount_dec_and_test(&ep->base.refcnt))
 		sctp_endpoint_destroy(ep);
 }
+EXPORT_SYMBOL_GPL(sctp_endpoint_put);
 
 /* Is this the endpoint we are looking for?  */
 struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
-- 
2.34.1.173.g76aa8bc2d0-goog


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

end of thread, other threads:[~2021-12-19 14:04 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-17 13:46 [PATCH v2 1/2] sctp: export sctp_endpoint_{hold,put}() and return incremented endpoint Lee Jones
2021-12-17 13:46 ` [PATCH v2 2/2] sctp: hold cached endpoints to prevent possible UAF Lee Jones
2021-12-17 14:17 ` [PATCH v2 1/2] sctp: export sctp_endpoint_{hold,put}() and return incremented endpoint David Laight
2021-12-17 14:35   ` Lee Jones
2021-12-19 14:04     ` David Laight
2021-12-17 15:06 ` Jakub Kicinski

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