diff options
author | Florian Westphal <fw@strlen.de> | 2020-12-10 14:25:02 -0800 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2020-12-14 17:30:06 -0800 |
commit | ab82e996a1fa1b9ae514fa357d9ce8df62321157 (patch) | |
tree | 5559cd85ee60dc779980c70a28e3f7aea64c6caf /net | |
parent | ba34c3de71ced1582dee55f2fae8638a3655d957 (diff) |
mptcp: hold mptcp socket before calling tcp_done
When processing options from tcp reset path its possible that
tcp_done(ssk) drops the last reference on the mptcp socket which
results in use-after-free.
Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/mptcp/subflow.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index bf808f1fabe5..73e66a406d99 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -313,12 +313,17 @@ void mptcp_subflow_reset(struct sock *ssk) struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); struct sock *sk = subflow->conn; + /* must hold: tcp_done() could drop last reference on parent */ + sock_hold(sk); + tcp_set_state(ssk, TCP_CLOSE); tcp_send_active_reset(ssk, GFP_ATOMIC); tcp_done(ssk); if (!test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &mptcp_sk(sk)->flags) && schedule_work(&mptcp_sk(sk)->work)) - sock_hold(sk); + return; /* worker will put sk for us */ + + sock_put(sk); } static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) |