forked from mirrors/linux
		
	net: ipv4: fix for a race condition in raw_sendmsg
inet->hdrincl is racy, and could lead to uninitialized stack pointer
usage, so its value should be read only once.
Fixes: c008ba5bdc ("ipv4: Avoid reading user iov twice after raw_probe_proto_opt")
Signed-off-by: Mohamed Ghannam <simo.ghannam@gmail.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									93c647643b
								
							
						
					
					
						commit
						8f659a03a0
					
				
					 1 changed files with 10 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -513,11 +513,16 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 | 
			
		|||
	int err;
 | 
			
		||||
	struct ip_options_data opt_copy;
 | 
			
		||||
	struct raw_frag_vec rfv;
 | 
			
		||||
	int hdrincl;
 | 
			
		||||
 | 
			
		||||
	err = -EMSGSIZE;
 | 
			
		||||
	if (len > 0xFFFF)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	/* hdrincl should be READ_ONCE(inet->hdrincl)
 | 
			
		||||
	 * but READ_ONCE() doesn't work with bit fields
 | 
			
		||||
	 */
 | 
			
		||||
	hdrincl = inet->hdrincl;
 | 
			
		||||
	/*
 | 
			
		||||
	 *	Check the flags.
 | 
			
		||||
	 */
 | 
			
		||||
| 
						 | 
				
			
			@ -593,7 +598,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 | 
			
		|||
		/* Linux does not mangle headers on raw sockets,
 | 
			
		||||
		 * so that IP options + IP_HDRINCL is non-sense.
 | 
			
		||||
		 */
 | 
			
		||||
		if (inet->hdrincl)
 | 
			
		||||
		if (hdrincl)
 | 
			
		||||
			goto done;
 | 
			
		||||
		if (ipc.opt->opt.srr) {
 | 
			
		||||
			if (!daddr)
 | 
			
		||||
| 
						 | 
				
			
			@ -615,12 +620,12 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 | 
			
		|||
 | 
			
		||||
	flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
 | 
			
		||||
			   RT_SCOPE_UNIVERSE,
 | 
			
		||||
			   inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
 | 
			
		||||
			   hdrincl ? IPPROTO_RAW : sk->sk_protocol,
 | 
			
		||||
			   inet_sk_flowi_flags(sk) |
 | 
			
		||||
			    (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
 | 
			
		||||
			    (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
 | 
			
		||||
			   daddr, saddr, 0, 0, sk->sk_uid);
 | 
			
		||||
 | 
			
		||||
	if (!inet->hdrincl) {
 | 
			
		||||
	if (!hdrincl) {
 | 
			
		||||
		rfv.msg = msg;
 | 
			
		||||
		rfv.hlen = 0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -645,7 +650,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 | 
			
		|||
		goto do_confirm;
 | 
			
		||||
back_from_confirm:
 | 
			
		||||
 | 
			
		||||
	if (inet->hdrincl)
 | 
			
		||||
	if (hdrincl)
 | 
			
		||||
		err = raw_send_hdrinc(sk, &fl4, msg, len,
 | 
			
		||||
				      &rt, msg->msg_flags, &ipc.sockc);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue