Skip to content

Commit b3c0f66

Browse files
Paolo Abenijfvogel
authored andcommitted
mptcp: fix MSG_PEEK stream corruption
[ Upstream commit 8e04ce45a8db7a080220e86e249198fa676b83dc ] If a MSG_PEEK | MSG_WAITALL read operation consumes all the bytes in the receive queue and recvmsg() need to waits for more data - i.e. it's a blocking one - upon arrival of the next packet the MPTCP protocol will start again copying the oldest data present in the receive queue, corrupting the data stream. Address the issue explicitly tracking the peeked sequence number, restarting from the last peeked byte. Fixes: ca4fb89 ("mptcp: add MSG_PEEK support") Cc: stable@vger.kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com> Reviewed-by: Geliang Tang <geliang@kernel.org> Tested-by: Geliang Tang <geliang@kernel.org> Reviewed-by: Mat Martineau <martineau@kernel.org> Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> Link: https://patch.msgid.link/20251028-net-mptcp-send-timeout-v1-2-38ffff5a9ec8@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org> [ Adjust context ] Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit 0206a9341e652167c610dcd79f3d4e9e8153984c) Signed-off-by: Jack Vogel <jack.vogel@oracle.com>
1 parent 2af5611 commit b3c0f66

File tree

1 file changed

+25
-11
lines changed

1 file changed

+25
-11
lines changed

net/mptcp/protocol.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,19 +1977,35 @@ static void mptcp_rcv_space_adjust(struct mptcp_sock *msk, int copied);
19771977

19781978
static int __mptcp_recvmsg_mskq(struct mptcp_sock *msk,
19791979
struct msghdr *msg,
1980-
size_t len, int flags,
1980+
size_t len, int flags, int copied_total,
19811981
struct scm_timestamping_internal *tss,
19821982
int *cmsg_flags)
19831983
{
19841984
struct sk_buff *skb, *tmp;
1985+
int total_data_len = 0;
19851986
int copied = 0;
19861987

19871988
skb_queue_walk_safe(&msk->receive_queue, skb, tmp) {
1988-
u32 offset = MPTCP_SKB_CB(skb)->offset;
1989+
u32 delta, offset = MPTCP_SKB_CB(skb)->offset;
19891990
u32 data_len = skb->len - offset;
1990-
u32 count = min_t(size_t, len - copied, data_len);
1991+
u32 count;
19911992
int err;
19921993

1994+
if (flags & MSG_PEEK) {
1995+
/* skip already peeked skbs */
1996+
if (total_data_len + data_len <= copied_total) {
1997+
total_data_len += data_len;
1998+
continue;
1999+
}
2000+
2001+
/* skip the already peeked data in the current skb */
2002+
delta = copied_total - total_data_len;
2003+
offset += delta;
2004+
data_len -= delta;
2005+
}
2006+
2007+
count = min_t(size_t, len - copied, data_len);
2008+
19932009
if (!(flags & MSG_TRUNC)) {
19942010
err = skb_copy_datagram_msg(skb, offset, msg, count);
19952011
if (unlikely(err < 0)) {
@@ -2006,22 +2022,19 @@ static int __mptcp_recvmsg_mskq(struct mptcp_sock *msk,
20062022

20072023
copied += count;
20082024

2009-
if (count < data_len) {
2010-
if (!(flags & MSG_PEEK)) {
2025+
if (!(flags & MSG_PEEK)) {
2026+
msk->bytes_consumed += count;
2027+
if (count < data_len) {
20112028
MPTCP_SKB_CB(skb)->offset += count;
20122029
MPTCP_SKB_CB(skb)->map_seq += count;
2013-
msk->bytes_consumed += count;
2030+
break;
20142031
}
2015-
break;
2016-
}
20172032

2018-
if (!(flags & MSG_PEEK)) {
20192033
/* we will bulk release the skb memory later */
20202034
skb->destructor = NULL;
20212035
WRITE_ONCE(msk->rmem_released, msk->rmem_released + skb->truesize);
20222036
__skb_unlink(skb, &msk->receive_queue);
20232037
__kfree_skb(skb);
2024-
msk->bytes_consumed += count;
20252038
}
20262039

20272040
if (copied >= len)
@@ -2245,7 +2258,8 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
22452258
while (copied < len) {
22462259
int err, bytes_read;
22472260

2248-
bytes_read = __mptcp_recvmsg_mskq(msk, msg, len - copied, flags, &tss, &cmsg_flags);
2261+
bytes_read = __mptcp_recvmsg_mskq(msk, msg, len - copied, flags,
2262+
copied, &tss, &cmsg_flags);
22492263
if (unlikely(bytes_read < 0)) {
22502264
if (!copied)
22512265
copied = bytes_read;

0 commit comments

Comments
 (0)