Skip to content

Commit 8e04ce4

Browse files
Paolo Abenikuba-moo
authored andcommitted
mptcp: fix MSG_PEEK stream corruption
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: [email protected] Signed-off-by: Paolo Abeni <[email protected]> Reviewed-by: Geliang Tang <[email protected]> Tested-by: Geliang Tang <[email protected]> Reviewed-by: Mat Martineau <[email protected]> Signed-off-by: Matthieu Baerts (NGI0) <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 27b0e70 commit 8e04ce4

1 file changed

Lines changed: 25 additions & 13 deletions

File tree

net/mptcp/protocol.c

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,22 +1945,36 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
19451945

19461946
static void mptcp_rcv_space_adjust(struct mptcp_sock *msk, int copied);
19471947

1948-
static int __mptcp_recvmsg_mskq(struct sock *sk,
1949-
struct msghdr *msg,
1950-
size_t len, int flags,
1948+
static int __mptcp_recvmsg_mskq(struct sock *sk, struct msghdr *msg,
1949+
size_t len, int flags, int copied_total,
19511950
struct scm_timestamping_internal *tss,
19521951
int *cmsg_flags)
19531952
{
19541953
struct mptcp_sock *msk = mptcp_sk(sk);
19551954
struct sk_buff *skb, *tmp;
1955+
int total_data_len = 0;
19561956
int copied = 0;
19571957

19581958
skb_queue_walk_safe(&sk->sk_receive_queue, skb, tmp) {
1959-
u32 offset = MPTCP_SKB_CB(skb)->offset;
1959+
u32 delta, offset = MPTCP_SKB_CB(skb)->offset;
19601960
u32 data_len = skb->len - offset;
1961-
u32 count = min_t(size_t, len - copied, data_len);
1961+
u32 count;
19621962
int err;
19631963

1964+
if (flags & MSG_PEEK) {
1965+
/* skip already peeked skbs */
1966+
if (total_data_len + data_len <= copied_total) {
1967+
total_data_len += data_len;
1968+
continue;
1969+
}
1970+
1971+
/* skip the already peeked data in the current skb */
1972+
delta = copied_total - total_data_len;
1973+
offset += delta;
1974+
data_len -= delta;
1975+
}
1976+
1977+
count = min_t(size_t, len - copied, data_len);
19641978
if (!(flags & MSG_TRUNC)) {
19651979
err = skb_copy_datagram_msg(skb, offset, msg, count);
19661980
if (unlikely(err < 0)) {
@@ -1977,24 +1991,21 @@ static int __mptcp_recvmsg_mskq(struct sock *sk,
19771991

19781992
copied += count;
19791993

1980-
if (count < data_len) {
1981-
if (!(flags & MSG_PEEK)) {
1994+
if (!(flags & MSG_PEEK)) {
1995+
msk->bytes_consumed += count;
1996+
if (count < data_len) {
19821997
MPTCP_SKB_CB(skb)->offset += count;
19831998
MPTCP_SKB_CB(skb)->map_seq += count;
1984-
msk->bytes_consumed += count;
1999+
break;
19852000
}
1986-
break;
1987-
}
19882001

1989-
if (!(flags & MSG_PEEK)) {
19902002
/* avoid the indirect call, we know the destructor is sock_rfree */
19912003
skb->destructor = NULL;
19922004
skb->sk = NULL;
19932005
atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
19942006
sk_mem_uncharge(sk, skb->truesize);
19952007
__skb_unlink(skb, &sk->sk_receive_queue);
19962008
skb_attempt_defer_free(skb);
1997-
msk->bytes_consumed += count;
19982009
}
19992010

20002011
if (copied >= len)
@@ -2191,7 +2202,8 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
21912202
while (copied < len) {
21922203
int err, bytes_read;
21932204

2194-
bytes_read = __mptcp_recvmsg_mskq(sk, msg, len - copied, flags, &tss, &cmsg_flags);
2205+
bytes_read = __mptcp_recvmsg_mskq(sk, msg, len - copied, flags,
2206+
copied, &tss, &cmsg_flags);
21952207
if (unlikely(bytes_read < 0)) {
21962208
if (!copied)
21972209
copied = bytes_read;

0 commit comments

Comments
 (0)