Skip to content

Commit dee85ac

Browse files
committed
Merge branch 'mptcp-fixes-for-6-3'
Matthieu Baerts says: ==================== mptcp: fixes for 6.3 Patch 1 fixes a possible deadlock in subflow_error_report() reported by lockdep. The report was in fact a false positive but the modification makes sense and silences lockdep to allow syzkaller to find real issues. The regression has been introduced in v5.12. Patch 2 is a refactoring needed to be able to fix the two next issues. It improves the situation and can be backported up to v6.0. Patches 3 and 4 fix UaF reported by KASAN. It fixes issues potentially visible since v5.7 and v5.19 but only reproducible until recently (v6.0). These two patches depend on patch 2/7. Patch 5 fixes the order of the printed values: expected vs seen values. The regression has been introduced recently: v6.3-rc1. Patch 6 adds missing ro_after_init flags. A previous patch added them for other functions but these two have been missed. This previous patch has been backported to stable versions (up to v5.12) so probably better to do the same here. Patch 7 fixes tcp_set_state() being called twice in a row since v5.10. Patch 8 fixes another lockdep false positive issue but this time in MPTCP PM code. Same here, some modifications in the code has been made to silence this issue and help finding real ones later. This issue can be seen since v6.2. v1: https://lore.kernel.org/r/20230227-upstream-net-20230227-mptcp-fixes-v1-0-070e30ae4a8e@tessares.net ==================== Link: https://lore.kernel.org/r/20230227-upstream-net-20230227-mptcp-fixes-v2-0-47c2e95eada9@tessares.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 12508b3 + cee4034 commit dee85ac

File tree

5 files changed

+95
-121
lines changed

5 files changed

+95
-121
lines changed

net/mptcp/pm_netlink.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,9 +997,13 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
997997
return ret;
998998
}
999999

1000+
static struct lock_class_key mptcp_slock_keys[2];
1001+
static struct lock_class_key mptcp_keys[2];
1002+
10001003
static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
10011004
struct mptcp_pm_addr_entry *entry)
10021005
{
1006+
bool is_ipv6 = sk->sk_family == AF_INET6;
10031007
int addrlen = sizeof(struct sockaddr_in);
10041008
struct sockaddr_storage addr;
10051009
struct socket *ssock;
@@ -1016,6 +1020,18 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
10161020
if (!newsk)
10171021
return -EINVAL;
10181022

1023+
/* The subflow socket lock is acquired in a nested to the msk one
1024+
* in several places, even by the TCP stack, and this msk is a kernel
1025+
* socket: lockdep complains. Instead of propagating the _nested
1026+
* modifiers in several places, re-init the lock class for the msk
1027+
* socket to an mptcp specific one.
1028+
*/
1029+
sock_lock_init_class_and_name(newsk,
1030+
is_ipv6 ? "mlock-AF_INET6" : "mlock-AF_INET",
1031+
&mptcp_slock_keys[is_ipv6],
1032+
is_ipv6 ? "msk_lock-AF_INET6" : "msk_lock-AF_INET",
1033+
&mptcp_keys[is_ipv6]);
1034+
10191035
lock_sock(newsk);
10201036
ssock = __mptcp_nmpc_socket(mptcp_sk(newsk));
10211037
release_sock(newsk);

net/mptcp/protocol.c

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,6 @@ static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
825825
if (sk->sk_socket && !ssk->sk_socket)
826826
mptcp_sock_graft(ssk, sk->sk_socket);
827827

828-
mptcp_propagate_sndbuf((struct sock *)msk, ssk);
829828
mptcp_sockopt_sync_locked(msk, ssk);
830829
return true;
831830
}
@@ -2343,23 +2342,32 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
23432342
goto out;
23442343
}
23452344

2346-
sock_orphan(ssk);
23472345
subflow->disposable = 1;
23482346

23492347
/* if ssk hit tcp_done(), tcp_cleanup_ulp() cleared the related ops
23502348
* the ssk has been already destroyed, we just need to release the
23512349
* reference owned by msk;
23522350
*/
23532351
if (!inet_csk(ssk)->icsk_ulp_ops) {
2352+
WARN_ON_ONCE(!sock_flag(ssk, SOCK_DEAD));
23542353
kfree_rcu(subflow, rcu);
2354+
} else if (msk->in_accept_queue && msk->first == ssk) {
2355+
/* if the first subflow moved to a close state, e.g. due to
2356+
* incoming reset and we reach here before inet_child_forget()
2357+
* the TCP stack could later try to close it via
2358+
* inet_csk_listen_stop(), or deliver it to the user space via
2359+
* accept().
2360+
* We can't delete the subflow - or risk a double free - nor let
2361+
* the msk survive - or will be leaked in the non accept scenario:
2362+
* fallback and let TCP cope with the subflow cleanup.
2363+
*/
2364+
WARN_ON_ONCE(sock_flag(ssk, SOCK_DEAD));
2365+
mptcp_subflow_drop_ctx(ssk);
23552366
} else {
23562367
/* otherwise tcp will dispose of the ssk and subflow ctx */
2357-
if (ssk->sk_state == TCP_LISTEN) {
2358-
tcp_set_state(ssk, TCP_CLOSE);
2359-
mptcp_subflow_queue_clean(sk, ssk);
2360-
inet_csk_listen_stop(ssk);
2368+
if (ssk->sk_state == TCP_LISTEN)
23612369
mptcp_event_pm_listener(ssk, MPTCP_EVENT_LISTENER_CLOSED);
2362-
}
2370+
23632371
__tcp_close(ssk, 0);
23642372

23652373
/* close acquired an extra ref */
@@ -2399,9 +2407,10 @@ static unsigned int mptcp_sync_mss(struct sock *sk, u32 pmtu)
23992407
return 0;
24002408
}
24012409

2402-
static void __mptcp_close_subflow(struct mptcp_sock *msk)
2410+
static void __mptcp_close_subflow(struct sock *sk)
24032411
{
24042412
struct mptcp_subflow_context *subflow, *tmp;
2413+
struct mptcp_sock *msk = mptcp_sk(sk);
24052414

24062415
might_sleep();
24072416

@@ -2415,7 +2424,15 @@ static void __mptcp_close_subflow(struct mptcp_sock *msk)
24152424
if (!skb_queue_empty_lockless(&ssk->sk_receive_queue))
24162425
continue;
24172426

2418-
mptcp_close_ssk((struct sock *)msk, ssk, subflow);
2427+
mptcp_close_ssk(sk, ssk, subflow);
2428+
}
2429+
2430+
/* if the MPC subflow has been closed before the msk is accepted,
2431+
* msk will never be accept-ed, close it now
2432+
*/
2433+
if (!msk->first && msk->in_accept_queue) {
2434+
sock_set_flag(sk, SOCK_DEAD);
2435+
inet_sk_state_store(sk, TCP_CLOSE);
24192436
}
24202437
}
24212438

@@ -2624,6 +2641,9 @@ static void mptcp_worker(struct work_struct *work)
26242641
__mptcp_check_send_data_fin(sk);
26252642
mptcp_check_data_fin(sk);
26262643

2644+
if (test_and_clear_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
2645+
__mptcp_close_subflow(sk);
2646+
26272647
/* There is no point in keeping around an orphaned sk timedout or
26282648
* closed, but we need the msk around to reply to incoming DATA_FIN,
26292649
* even if it is orphaned and in FIN_WAIT2 state
@@ -2639,9 +2659,6 @@ static void mptcp_worker(struct work_struct *work)
26392659
}
26402660
}
26412661

2642-
if (test_and_clear_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
2643-
__mptcp_close_subflow(msk);
2644-
26452662
if (test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags))
26462663
__mptcp_retrans(sk);
26472664

@@ -3079,6 +3096,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
30793096
msk->local_key = subflow_req->local_key;
30803097
msk->token = subflow_req->token;
30813098
msk->subflow = NULL;
3099+
msk->in_accept_queue = 1;
30823100
WRITE_ONCE(msk->fully_established, false);
30833101
if (mp_opt->suboptions & OPTION_MPTCP_CSUMREQD)
30843102
WRITE_ONCE(msk->csum_enabled, true);
@@ -3096,8 +3114,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
30963114
security_inet_csk_clone(nsk, req);
30973115
bh_unlock_sock(nsk);
30983116

3099-
/* keep a single reference */
3100-
__sock_put(nsk);
3117+
/* note: the newly allocated socket refcount is 2 now */
31013118
return nsk;
31023119
}
31033120

@@ -3153,8 +3170,6 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
31533170
goto out;
31543171
}
31553172

3156-
/* acquire the 2nd reference for the owning socket */
3157-
sock_hold(new_mptcp_sock);
31583173
newsk = new_mptcp_sock;
31593174
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEPASSIVEACK);
31603175
} else {
@@ -3705,25 +3720,10 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
37053720
struct sock *newsk = newsock->sk;
37063721

37073722
set_bit(SOCK_CUSTOM_SOCKOPT, &newsock->flags);
3723+
msk->in_accept_queue = 0;
37083724

37093725
lock_sock(newsk);
37103726

3711-
/* PM/worker can now acquire the first subflow socket
3712-
* lock without racing with listener queue cleanup,
3713-
* we can notify it, if needed.
3714-
*
3715-
* Even if remote has reset the initial subflow by now
3716-
* the refcnt is still at least one.
3717-
*/
3718-
subflow = mptcp_subflow_ctx(msk->first);
3719-
list_add(&subflow->node, &msk->conn_list);
3720-
sock_hold(msk->first);
3721-
if (mptcp_is_fully_established(newsk))
3722-
mptcp_pm_fully_established(msk, msk->first, GFP_KERNEL);
3723-
3724-
mptcp_rcv_space_init(msk, msk->first);
3725-
mptcp_propagate_sndbuf(newsk, msk->first);
3726-
37273727
/* set ssk->sk_socket of accept()ed flows to mptcp socket.
37283728
* This is needed so NOSPACE flag can be set from tcp stack.
37293729
*/

net/mptcp/protocol.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,8 @@ struct mptcp_sock {
295295
u8 recvmsg_inq:1,
296296
cork:1,
297297
nodelay:1,
298-
fastopening:1;
298+
fastopening:1,
299+
in_accept_queue:1;
299300
int connect_flags;
300301
struct work_struct work;
301302
struct sk_buff *ooo_last_skb;
@@ -628,7 +629,6 @@ void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
628629
struct mptcp_subflow_context *subflow);
629630
void __mptcp_subflow_send_ack(struct sock *ssk);
630631
void mptcp_subflow_reset(struct sock *ssk);
631-
void mptcp_subflow_queue_clean(struct sock *sk, struct sock *ssk);
632632
void mptcp_sock_graft(struct sock *sk, struct socket *parent);
633633
struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk);
634634
bool __mptcp_close(struct sock *sk, long timeout);
@@ -666,6 +666,8 @@ void mptcp_subflow_set_active(struct mptcp_subflow_context *subflow);
666666

667667
bool mptcp_subflow_active(struct mptcp_subflow_context *subflow);
668668

669+
void mptcp_subflow_drop_ctx(struct sock *ssk);
670+
669671
static inline void mptcp_subflow_tcp_fallback(struct sock *sk,
670672
struct mptcp_subflow_context *ctx)
671673
{

0 commit comments

Comments
 (0)