OSDN Git Service

mptcp: hold mptcp socket before calling tcp_done
authorFlorian Westphal <fw@strlen.de>
Thu, 10 Dec 2020 22:25:02 +0000 (14:25 -0800)
committerJakub Kicinski <kuba@kernel.org>
Tue, 15 Dec 2020 01:30:06 +0000 (17:30 -0800)
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>
net/mptcp/subflow.c

index bf808f1..73e66a4 100644 (file)
@@ -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)