Skip to content

Commit 42c09c0

Browse files
Geliang Tangintel-lab-lkp
authored andcommitted
mptcp: implement .read_sock
nvme_tcp_try_recv() needs to call .read_sock interface of struct proto_ops, but it is not implemented in MPTCP. This patch implements it with reference to __mptcp_recvmsg_mskq(). v2: - first check the sk_state (Matt), but not look for the end of the end of a connection like TCP in __tcp_read_sock(): if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) break; This will cause a use-after-free error: BUG: KASAN: slab-use-after-free in mptcp_read_sock. v3: - Use sk->sk_rcvbuf instead of INT_MAX as the max len. v4: - invoke __mptcp_move_skbs. Reviewed-by: Hannes Reinecke <[email protected]> Signed-off-by: Geliang Tang <[email protected]>
1 parent d3091af commit 42c09c0

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

net/mptcp/protocol.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3956,6 +3956,68 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock,
39563956
return mask;
39573957
}
39583958

3959+
/*
3960+
* Note:
3961+
* - It is assumed that the socket was locked by the caller.
3962+
*/
3963+
static int mptcp_read_sock(struct sock *sk, read_descriptor_t *desc,
3964+
sk_read_actor_t recv_actor)
3965+
{
3966+
struct mptcp_sock *msk = mptcp_sk(sk);
3967+
struct scm_timestamping_internal tss;
3968+
size_t len = sk->sk_rcvbuf;
3969+
struct sk_buff *skb, *tmp;
3970+
int copied = 0;
3971+
3972+
if (sk->sk_state == TCP_LISTEN)
3973+
return -ENOTCONN;
3974+
skb_queue_walk_safe(&sk->sk_receive_queue, skb, tmp) {
3975+
u32 offset = MPTCP_SKB_CB(skb)->offset;
3976+
u32 data_len = skb->len - offset;
3977+
u32 size = min_t(size_t, len - copied, data_len);
3978+
int count;
3979+
3980+
count = recv_actor(desc, skb, offset, size);
3981+
if (count <= 0) {
3982+
if (!copied)
3983+
copied = count;
3984+
break;
3985+
}
3986+
3987+
if (MPTCP_SKB_CB(skb)->has_rxtstamp)
3988+
tcp_update_recv_tstamps(skb, &tss);
3989+
3990+
copied += count;
3991+
3992+
if (count < data_len) {
3993+
MPTCP_SKB_CB(skb)->offset += count;
3994+
MPTCP_SKB_CB(skb)->map_seq += count;
3995+
msk->bytes_consumed += count;
3996+
break;
3997+
}
3998+
3999+
/* avoid the indirect call, we know the destructor is sock_wfree */
4000+
skb->destructor = NULL;
4001+
atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
4002+
sk_mem_uncharge(sk, skb->truesize);
4003+
sk_eat_skb(sk, skb);
4004+
msk->bytes_consumed += count;
4005+
4006+
if (copied >= len)
4007+
break;
4008+
}
4009+
4010+
mptcp_rcv_space_adjust(msk, copied);
4011+
4012+
if (copied > 0) {
4013+
if (skb_queue_empty(&sk->sk_receive_queue))
4014+
__mptcp_move_skbs(sk);
4015+
mptcp_cleanup_rbuf(msk, copied);
4016+
}
4017+
4018+
return copied;
4019+
}
4020+
39594021
static const struct proto_ops mptcp_stream_ops = {
39604022
.family = PF_INET,
39614023
.owner = THIS_MODULE,
@@ -3976,6 +4038,7 @@ static const struct proto_ops mptcp_stream_ops = {
39764038
.recvmsg = inet_recvmsg,
39774039
.mmap = sock_no_mmap,
39784040
.set_rcvlowat = mptcp_set_rcvlowat,
4041+
.read_sock = mptcp_read_sock,
39794042
};
39804043

39814044
static struct inet_protosw mptcp_protosw = {
@@ -4080,6 +4143,7 @@ static const struct proto_ops mptcp_v6_stream_ops = {
40804143
.compat_ioctl = inet6_compat_ioctl,
40814144
#endif
40824145
.set_rcvlowat = mptcp_set_rcvlowat,
4146+
.read_sock = mptcp_read_sock,
40834147
};
40844148

40854149
static struct proto mptcp_v6_prot;

0 commit comments

Comments
 (0)