mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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
					
				
					 2 changed files with 9 additions and 3 deletions
				
			
		| 
						 | 
					@ -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 a new issue