dccp: fix data-race around dp->dccps_mss_cache
dccp_sendmsg() reads dp->dccps_mss_cache before locking the socket.
Same thing in do_dccp_getsockopt().
Add READ_ONCE()/WRITE_ONCE() annotations,
and change dccp_sendmsg() to check again dccps_mss_cache
after socket is locked.
Fixes: 7c657876b6
("[DCCP]: Initial implementation")
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/20230803163021.2958262-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
fc2ea6ab0a
commit
a47e598fbd
@ -187,7 +187,7 @@ unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu)
|
|||||||
|
|
||||||
/* And store cached results */
|
/* And store cached results */
|
||||||
icsk->icsk_pmtu_cookie = pmtu;
|
icsk->icsk_pmtu_cookie = pmtu;
|
||||||
dp->dccps_mss_cache = cur_mps;
|
WRITE_ONCE(dp->dccps_mss_cache, cur_mps);
|
||||||
|
|
||||||
return cur_mps;
|
return cur_mps;
|
||||||
}
|
}
|
||||||
|
@ -630,7 +630,7 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
|
|||||||
return dccp_getsockopt_service(sk, len,
|
return dccp_getsockopt_service(sk, len,
|
||||||
(__be32 __user *)optval, optlen);
|
(__be32 __user *)optval, optlen);
|
||||||
case DCCP_SOCKOPT_GET_CUR_MPS:
|
case DCCP_SOCKOPT_GET_CUR_MPS:
|
||||||
val = dp->dccps_mss_cache;
|
val = READ_ONCE(dp->dccps_mss_cache);
|
||||||
break;
|
break;
|
||||||
case DCCP_SOCKOPT_AVAILABLE_CCIDS:
|
case DCCP_SOCKOPT_AVAILABLE_CCIDS:
|
||||||
return ccid_getsockopt_builtin_ccids(sk, len, optval, optlen);
|
return ccid_getsockopt_builtin_ccids(sk, len, optval, optlen);
|
||||||
@ -739,7 +739,7 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||||||
|
|
||||||
trace_dccp_probe(sk, len);
|
trace_dccp_probe(sk, len);
|
||||||
|
|
||||||
if (len > dp->dccps_mss_cache)
|
if (len > READ_ONCE(dp->dccps_mss_cache))
|
||||||
return -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
|
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
@ -772,6 +772,12 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||||||
goto out_discard;
|
goto out_discard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We need to check dccps_mss_cache after socket is locked. */
|
||||||
|
if (len > dp->dccps_mss_cache) {
|
||||||
|
rc = -EMSGSIZE;
|
||||||
|
goto out_discard;
|
||||||
|
}
|
||||||
|
|
||||||
skb_reserve(skb, sk->sk_prot->max_header);
|
skb_reserve(skb, sk->sk_prot->max_header);
|
||||||
rc = memcpy_from_msg(skb_put(skb, len), msg, len);
|
rc = memcpy_from_msg(skb_put(skb, len), msg, len);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user