diff options
Diffstat (limited to 'net/packet/af_packet.c')
| -rw-r--r-- | net/packet/af_packet.c | 29 | 
1 files changed, 15 insertions, 14 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 18f616f487ea..ea3ebc160e25 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2522,8 +2522,7 @@ static void tpacket_destruct_skb(struct sk_buff *skb)  		ts = __packet_set_timestamp(po, ph, skb);  		__packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts); -		if (!packet_read_pending(&po->tx_ring)) -			complete(&po->skb_completion); +		complete(&po->skb_completion);  	}  	sock_wfree(skb); @@ -3800,28 +3799,30 @@ packet_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval,  	case PACKET_TX_RING:  	{  		union tpacket_req_u req_u; -		int len; +		ret = -EINVAL;  		lock_sock(sk);  		switch (po->tp_version) {  		case TPACKET_V1:  		case TPACKET_V2: -			len = sizeof(req_u.req); +			if (optlen < sizeof(req_u.req)) +				break; +			ret = copy_from_sockptr(&req_u.req, optval, +						sizeof(req_u.req)) ? +						-EINVAL : 0;  			break;  		case TPACKET_V3:  		default: -			len = sizeof(req_u.req3); +			if (optlen < sizeof(req_u.req3)) +				break; +			ret = copy_from_sockptr(&req_u.req3, optval, +						sizeof(req_u.req3)) ? +						-EINVAL : 0;  			break;  		} -		if (optlen < len) { -			ret = -EINVAL; -		} else { -			if (copy_from_sockptr(&req_u.req, optval, len)) -				ret = -EFAULT; -			else -				ret = packet_set_ring(sk, &req_u, 0, -						    optname == PACKET_TX_RING); -		} +		if (!ret) +			ret = packet_set_ring(sk, &req_u, 0, +					      optname == PACKET_TX_RING);  		release_sock(sk);  		return ret;  	}  |