]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
dccp: fix data-race around dp->dccps_mss_cache
authorEric Dumazet <edumazet@google.com>
Thu, 3 Aug 2023 16:30:21 +0000 (16:30 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 16 Aug 2023 16:10:54 +0000 (18:10 +0200)
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: 7c657876b63c ("[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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/dccp/output.c
net/dccp/proto.c

index 91a15b3c4915a31c40ab4ea3901b4ee4d9cef1a0..d872dd1cfb5e07236c813ada86cec2cc691cbb6e 100644 (file)
@@ -189,7 +189,7 @@ unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu)
 
        /* And store cached results */
        icsk->icsk_pmtu_cookie = pmtu;
-       dp->dccps_mss_cache = cur_mps;
+       WRITE_ONCE(dp->dccps_mss_cache, cur_mps);
 
        return cur_mps;
 }
index 794be8ab05f438f537f8800bef89b85e56aa73ce..24aeab90539b9f320dc070e84dd0df07112e6e6f 100644 (file)
@@ -645,7 +645,7 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
                return dccp_getsockopt_service(sk, len,
                                               (__be32 __user *)optval, optlen);
        case DCCP_SOCKOPT_GET_CUR_MPS:
-               val = dp->dccps_mss_cache;
+               val = READ_ONCE(dp->dccps_mss_cache);
                break;
        case DCCP_SOCKOPT_AVAILABLE_CCIDS:
                return ccid_getsockopt_builtin_ccids(sk, len, optval, optlen);
@@ -765,7 +765,7 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        int rc, size;
        long timeo;
 
-       if (len > dp->dccps_mss_cache)
+       if (len > READ_ONCE(dp->dccps_mss_cache))
                return -EMSGSIZE;
 
        lock_sock(sk);
@@ -798,6 +798,12 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                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);
        rc = memcpy_from_msg(skb_put(skb, len), msg, len);
        if (rc != 0)