forked from mirrors/linux
		
	net: Fix data-races around sysctl_[rw]mem_(max|default).
While reading sysctl_[rw]mem_(max|default), they can be changed
concurrently.  Thus, we need to add READ_ONCE() to its readers.
Fixes: 1da177e4c3 ("Linux-2.6.12-rc2")
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									c624c58e08
								
							
						
					
					
						commit
						1227c1771d
					
				
					 5 changed files with 10 additions and 10 deletions
				
			
		|  | @ -5034,14 +5034,14 @@ static int __bpf_setsockopt(struct sock *sk, int level, int optname, | |||
| 		/* Only some socketops are supported */ | ||||
| 		switch (optname) { | ||||
| 		case SO_RCVBUF: | ||||
| 			val = min_t(u32, val, sysctl_rmem_max); | ||||
| 			val = min_t(u32, val, READ_ONCE(sysctl_rmem_max)); | ||||
| 			val = min_t(int, val, INT_MAX / 2); | ||||
| 			sk->sk_userlocks |= SOCK_RCVBUF_LOCK; | ||||
| 			WRITE_ONCE(sk->sk_rcvbuf, | ||||
| 				   max_t(int, val * 2, SOCK_MIN_RCVBUF)); | ||||
| 			break; | ||||
| 		case SO_SNDBUF: | ||||
| 			val = min_t(u32, val, sysctl_wmem_max); | ||||
| 			val = min_t(u32, val, READ_ONCE(sysctl_wmem_max)); | ||||
| 			val = min_t(int, val, INT_MAX / 2); | ||||
| 			sk->sk_userlocks |= SOCK_SNDBUF_LOCK; | ||||
| 			WRITE_ONCE(sk->sk_sndbuf, | ||||
|  |  | |||
|  | @ -1101,7 +1101,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, | |||
| 		 * play 'guess the biggest size' games. RCVBUF/SNDBUF | ||||
| 		 * are treated in BSD as hints | ||||
| 		 */ | ||||
| 		val = min_t(u32, val, sysctl_wmem_max); | ||||
| 		val = min_t(u32, val, READ_ONCE(sysctl_wmem_max)); | ||||
| set_sndbuf: | ||||
| 		/* Ensure val * 2 fits into an int, to prevent max_t()
 | ||||
| 		 * from treating it as a negative value. | ||||
|  | @ -1133,7 +1133,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, | |||
| 		 * play 'guess the biggest size' games. RCVBUF/SNDBUF | ||||
| 		 * are treated in BSD as hints | ||||
| 		 */ | ||||
| 		__sock_set_rcvbuf(sk, min_t(u32, val, sysctl_rmem_max)); | ||||
| 		__sock_set_rcvbuf(sk, min_t(u32, val, READ_ONCE(sysctl_rmem_max))); | ||||
| 		break; | ||||
| 
 | ||||
| 	case SO_RCVBUFFORCE: | ||||
|  | @ -3309,8 +3309,8 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
| 	timer_setup(&sk->sk_timer, NULL, 0); | ||||
| 
 | ||||
| 	sk->sk_allocation	=	GFP_KERNEL; | ||||
| 	sk->sk_rcvbuf		=	sysctl_rmem_default; | ||||
| 	sk->sk_sndbuf		=	sysctl_wmem_default; | ||||
| 	sk->sk_rcvbuf		=	READ_ONCE(sysctl_rmem_default); | ||||
| 	sk->sk_sndbuf		=	READ_ONCE(sysctl_wmem_default); | ||||
| 	sk->sk_state		=	TCP_CLOSE; | ||||
| 	sk_set_socket(sk, sock); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1730,7 +1730,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, | |||
| 
 | ||||
| 	sk->sk_protocol = ip_hdr(skb)->protocol; | ||||
| 	sk->sk_bound_dev_if = arg->bound_dev_if; | ||||
| 	sk->sk_sndbuf = sysctl_wmem_default; | ||||
| 	sk->sk_sndbuf = READ_ONCE(sysctl_wmem_default); | ||||
| 	ipc.sockc.mark = fl4.flowi4_mark; | ||||
| 	err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, | ||||
| 			     len, 0, &ipc, &rt, MSG_DONTWAIT); | ||||
|  |  | |||
|  | @ -239,7 +239,7 @@ void tcp_select_initial_window(const struct sock *sk, int __space, __u32 mss, | |||
| 	if (wscale_ok) { | ||||
| 		/* Set window scaling on max possible window */ | ||||
| 		space = max_t(u32, space, READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_rmem[2])); | ||||
| 		space = max_t(u32, space, sysctl_rmem_max); | ||||
| 		space = max_t(u32, space, READ_ONCE(sysctl_rmem_max)); | ||||
| 		space = min_t(u32, space, *window_clamp); | ||||
| 		*rcv_wscale = clamp_t(int, ilog2(space) - 15, | ||||
| 				      0, TCP_MAX_WSCALE); | ||||
|  |  | |||
|  | @ -1280,12 +1280,12 @@ static void set_sock_size(struct sock *sk, int mode, int val) | |||
| 	lock_sock(sk); | ||||
| 	if (mode) { | ||||
| 		val = clamp_t(int, val, (SOCK_MIN_SNDBUF + 1) / 2, | ||||
| 			      sysctl_wmem_max); | ||||
| 			      READ_ONCE(sysctl_wmem_max)); | ||||
| 		sk->sk_sndbuf = val * 2; | ||||
| 		sk->sk_userlocks |= SOCK_SNDBUF_LOCK; | ||||
| 	} else { | ||||
| 		val = clamp_t(int, val, (SOCK_MIN_RCVBUF + 1) / 2, | ||||
| 			      sysctl_rmem_max); | ||||
| 			      READ_ONCE(sysctl_rmem_max)); | ||||
| 		sk->sk_rcvbuf = val * 2; | ||||
| 		sk->sk_userlocks |= SOCK_RCVBUF_LOCK; | ||||
| 	} | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Kuniyuki Iwashima
						Kuniyuki Iwashima