diff options
Diffstat (limited to 'net/ipv4/raw.c')
| -rw-r--r-- | net/ipv4/raw.c | 15 | 
1 files changed, 10 insertions, 5 deletions
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 33b70bfd1122..125c1eab3eaa 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -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);  |