Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2bdc7f27 authored by Eric Dumazet's avatar Eric Dumazet Committed by Greg Kroah-Hartman
Browse files

dccp: fix data-race around dp->dccps_mss_cache



commit a47e598fbd8617967e49d85c49c22f9fc642704c upstream.

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: 7c657876 ("[DCCP]: Initial implementation")
Reported-by: default avatarsyzbot <syzkaller@googlegroups.com>
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/20230803163021.2958262-1-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent cfdcb95a
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -189,7 +189,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;
}
}
+8 −2
Original line number Original line Diff line number Diff line
@@ -648,7 +648,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);
@@ -770,7 +770,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);
@@ -803,6 +803,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)