diff --git a/ciq/ciq_backports/kernel-rt-4.18.0-553.16.1.rt7.357.el8_10/fb7a0d33.failed b/ciq/ciq_backports/kernel-rt-4.18.0-553.16.1.rt7.357.el8_10/fb7a0d33.failed new file mode 100644 index 000000000000..fff1ef2eaaee --- /dev/null +++ b/ciq/ciq_backports/kernel-rt-4.18.0-553.16.1.rt7.357.el8_10/fb7a0d33.failed @@ -0,0 +1,234 @@ +mptcp: ensure snd_nxt is properly initialized on connect + +jira LE-1907 +cve CVE-2024-36889 +Rebuild_History Non-Buildable kernel-rt-4.18.0-553.16.1.rt7.357.el8_10 +commit-author Paolo Abeni +commit fb7a0d334894206ae35f023a82cad5a290fd7386 +Empty-Commit: Cherry-Pick Conflicts during history rebuild. +Will be included in final tarball splat. Ref for failed cherry-pick at: +ciq/ciq_backports/kernel-rt-4.18.0-553.16.1.rt7.357.el8_10/fb7a0d33.failed + +Christoph reported a splat hinting at a corrupted snd_una: + + WARNING: CPU: 1 PID: 38 at net/mptcp/protocol.c:1005 __mptcp_clean_una+0x4b3/0x620 net/mptcp/protocol.c:1005 + Modules linked in: + CPU: 1 PID: 38 Comm: kworker/1:1 Not tainted 6.9.0-rc1-gbbeac67456c9 #59 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2.el7 04/01/2014 + Workqueue: events mptcp_worker + RIP: 0010:__mptcp_clean_una+0x4b3/0x620 net/mptcp/protocol.c:1005 + Code: be 06 01 00 00 bf 06 01 00 00 e8 a8 12 e7 fe e9 00 fe ff ff e8 + 8e 1a e7 fe 0f b7 ab 3e 02 00 00 e9 d3 fd ff ff e8 7d 1a e7 fe + <0f> 0b 4c 8b bb e0 05 00 00 e9 74 fc ff ff e8 6a 1a e7 fe 0f 0b e9 + RSP: 0018:ffffc9000013fd48 EFLAGS: 00010293 + RAX: 0000000000000000 RBX: ffff8881029bd280 RCX: ffffffff82382fe4 + RDX: ffff8881003cbd00 RSI: ffffffff823833c3 RDI: 0000000000000001 + RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 + R10: 0000000000000000 R11: fefefefefefefeff R12: ffff888138ba8000 + R13: 0000000000000106 R14: ffff8881029bd908 R15: ffff888126560000 + FS: 0000000000000000(0000) GS:ffff88813bd00000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f604a5dae38 CR3: 0000000101dac002 CR4: 0000000000170ef0 + Call Trace: + + __mptcp_clean_una_wakeup net/mptcp/protocol.c:1055 [inline] + mptcp_clean_una_wakeup net/mptcp/protocol.c:1062 [inline] + __mptcp_retrans+0x7f/0x7e0 net/mptcp/protocol.c:2615 + mptcp_worker+0x434/0x740 net/mptcp/protocol.c:2767 + process_one_work+0x1e0/0x560 kernel/workqueue.c:3254 + process_scheduled_works kernel/workqueue.c:3335 [inline] + worker_thread+0x3c7/0x640 kernel/workqueue.c:3416 + kthread+0x121/0x170 kernel/kthread.c:388 + ret_from_fork+0x44/0x50 arch/x86/kernel/process.c:147 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:243 + + +When fallback to TCP happens early on a client socket, snd_nxt +is not yet initialized and any incoming ack will copy such value +into snd_una. If the mptcp worker (dumbly) tries mptcp-level +re-injection after such ack, that would unconditionally trigger a send +buffer cleanup using 'bad' snd_una values. + +We could easily disable re-injection for fallback sockets, but such +dumb behavior already helped catching a few subtle issues and a very +low to zero impact in practice. + +Instead address the issue always initializing snd_nxt (and write_seq, +for consistency) at connect time. + +Fixes: 8fd738049ac3 ("mptcp: fallback in case of simultaneous connect") + Cc: stable@vger.kernel.org + Reported-by: Christoph Paasch +Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/485 + Tested-by: Christoph Paasch + Signed-off-by: Paolo Abeni + Reviewed-by: Mat Martineau + Signed-off-by: Matthieu Baerts (NGI0) +Link: https://lore.kernel.org/r/20240429-upstream-net-20240429-mptcp-snd_nxt-init-connect-v1-1-59ceac0a7dcb@kernel.org + Signed-off-by: Jakub Kicinski +(cherry picked from commit fb7a0d334894206ae35f023a82cad5a290fd7386) + Signed-off-by: Jonathan Maple + +# Conflicts: +# net/mptcp/protocol.c +diff --cc net/mptcp/protocol.c +index 9a2b232a4c48,965eb69dc5de..000000000000 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@@ -3291,6 -3625,152 +3291,155 @@@ static void mptcp_shutdown(struct sock + __mptcp_wr_shutdown(sk); + } + +++<<<<<<< HEAD +++======= ++ static int mptcp_forward_alloc_get(const struct sock *sk) ++ { ++ return READ_ONCE(sk->sk_forward_alloc) + ++ READ_ONCE(mptcp_sk(sk)->rmem_fwd_alloc); ++ } ++ ++ static int mptcp_ioctl_outq(const struct mptcp_sock *msk, u64 v) ++ { ++ const struct sock *sk = (void *)msk; ++ u64 delta; ++ ++ if (sk->sk_state == TCP_LISTEN) ++ return -EINVAL; ++ ++ if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) ++ return 0; ++ ++ delta = msk->write_seq - v; ++ if (__mptcp_check_fallback(msk) && msk->first) { ++ struct tcp_sock *tp = tcp_sk(msk->first); ++ ++ /* the first subflow is disconnected after close - see ++ * __mptcp_close_ssk(). tcp_disconnect() moves the write_seq ++ * so ignore that status, too. ++ */ ++ if (!((1 << msk->first->sk_state) & ++ (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_CLOSE))) ++ delta += READ_ONCE(tp->write_seq) - tp->snd_una; ++ } ++ if (delta > INT_MAX) ++ delta = INT_MAX; ++ ++ return (int)delta; ++ } ++ ++ static int mptcp_ioctl(struct sock *sk, int cmd, int *karg) ++ { ++ struct mptcp_sock *msk = mptcp_sk(sk); ++ bool slow; ++ ++ switch (cmd) { ++ case SIOCINQ: ++ if (sk->sk_state == TCP_LISTEN) ++ return -EINVAL; ++ ++ lock_sock(sk); ++ __mptcp_move_skbs(msk); ++ *karg = mptcp_inq_hint(sk); ++ release_sock(sk); ++ break; ++ case SIOCOUTQ: ++ slow = lock_sock_fast(sk); ++ *karg = mptcp_ioctl_outq(msk, READ_ONCE(msk->snd_una)); ++ unlock_sock_fast(sk, slow); ++ break; ++ case SIOCOUTQNSD: ++ slow = lock_sock_fast(sk); ++ *karg = mptcp_ioctl_outq(msk, msk->snd_nxt); ++ unlock_sock_fast(sk, slow); ++ break; ++ default: ++ return -ENOIOCTLCMD; ++ } ++ ++ return 0; ++ } ++ ++ static void mptcp_subflow_early_fallback(struct mptcp_sock *msk, ++ struct mptcp_subflow_context *subflow) ++ { ++ subflow->request_mptcp = 0; ++ __mptcp_do_fallback(msk); ++ } ++ ++ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ++ { ++ struct mptcp_subflow_context *subflow; ++ struct mptcp_sock *msk = mptcp_sk(sk); ++ int err = -EINVAL; ++ struct sock *ssk; ++ ++ ssk = __mptcp_nmpc_sk(msk); ++ if (IS_ERR(ssk)) ++ return PTR_ERR(ssk); ++ ++ mptcp_set_state(sk, TCP_SYN_SENT); ++ subflow = mptcp_subflow_ctx(ssk); ++ #ifdef CONFIG_TCP_MD5SIG ++ /* no MPTCP if MD5SIG is enabled on this socket or we may run out of ++ * TCP option space. ++ */ ++ if (rcu_access_pointer(tcp_sk(ssk)->md5sig_info)) ++ mptcp_subflow_early_fallback(msk, subflow); ++ #endif ++ if (subflow->request_mptcp && mptcp_token_new_connect(ssk)) { ++ MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_TOKENFALLBACKINIT); ++ mptcp_subflow_early_fallback(msk, subflow); ++ } ++ ++ WRITE_ONCE(msk->write_seq, subflow->idsn); ++ WRITE_ONCE(msk->snd_nxt, subflow->idsn); ++ if (likely(!__mptcp_check_fallback(msk))) ++ MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEACTIVE); ++ ++ /* if reaching here via the fastopen/sendmsg path, the caller already ++ * acquired the subflow socket lock, too. ++ */ ++ if (!msk->fastopening) ++ lock_sock(ssk); ++ ++ /* the following mirrors closely a very small chunk of code from ++ * __inet_stream_connect() ++ */ ++ if (ssk->sk_state != TCP_CLOSE) ++ goto out; ++ ++ if (BPF_CGROUP_PRE_CONNECT_ENABLED(ssk)) { ++ err = ssk->sk_prot->pre_connect(ssk, uaddr, addr_len); ++ if (err) ++ goto out; ++ } ++ ++ err = ssk->sk_prot->connect(ssk, uaddr, addr_len); ++ if (err < 0) ++ goto out; ++ ++ inet_assign_bit(DEFER_CONNECT, sk, inet_test_bit(DEFER_CONNECT, ssk)); ++ ++ out: ++ if (!msk->fastopening) ++ release_sock(ssk); ++ ++ /* on successful connect, the msk state will be moved to established by ++ * subflow_finish_connect() ++ */ ++ if (unlikely(err)) { ++ /* avoid leaving a dangling token in an unconnected socket */ ++ mptcp_token_destroy(msk); ++ mptcp_set_state(sk, TCP_CLOSE); ++ return err; ++ } ++ ++ mptcp_copy_inaddrs(sk, ssk); ++ return 0; ++ } ++ +++>>>>>>> fb7a0d334894 (mptcp: ensure snd_nxt is properly initialized on connect) + static struct proto mptcp_prot = { + .name = "MPTCP", + .owner = THIS_MODULE, +* Unmerged path net/mptcp/protocol.c