diff options
Diffstat (limited to 'net/packet/af_packet.c')
| -rw-r--r-- | net/packet/af_packet.c | 37 | 
1 files changed, 20 insertions, 17 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 50809748c127..e6445d8f3f57 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2262,6 +2262,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,  		if (po->stats.stats1.tp_drops)  			status |= TP_STATUS_LOSING;  	} + +	if (do_vnet && +	    virtio_net_hdr_from_skb(skb, h.raw + macoff - +				    sizeof(struct virtio_net_hdr), +				    vio_le(), true, 0)) +		goto drop_n_account; +  	po->stats.stats1.tp_packets++;  	if (copy_skb) {  		status |= TP_STATUS_COPY; @@ -2269,15 +2276,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,  	}  	spin_unlock(&sk->sk_receive_queue.lock); -	if (do_vnet) { -		if (virtio_net_hdr_from_skb(skb, h.raw + macoff - -					    sizeof(struct virtio_net_hdr), -					    vio_le(), true, 0)) { -			spin_lock(&sk->sk_receive_queue.lock); -			goto drop_n_account; -		} -	} -  	skb_copy_bits(skb, 0, h.raw + macoff, snaplen);  	if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp))) @@ -2880,6 +2878,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)  			goto out_free;  	} else if (reserve) {  		skb_reserve(skb, -reserve); +		if (len < reserve) +			skb_reset_network_header(skb);  	}  	/* Returns -EFAULT on error */ @@ -4078,11 +4078,12 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd,  	return 0;  } -static __poll_t packet_poll_mask(struct socket *sock, __poll_t events) +static __poll_t packet_poll(struct file *file, struct socket *sock, +				poll_table *wait)  {  	struct sock *sk = sock->sk;  	struct packet_sock *po = pkt_sk(sk); -	__poll_t mask = datagram_poll_mask(sock, events); +	__poll_t mask = datagram_poll(file, sock, wait);  	spin_lock_bh(&sk->sk_receive_queue.lock);  	if (po->rx_ring.pg_vec) { @@ -4225,6 +4226,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,  	}  	if (req->tp_block_nr) { +		unsigned int min_frame_size; +  		/* Sanity tests and some calculations */  		err = -EBUSY;  		if (unlikely(rb->pg_vec)) @@ -4247,12 +4250,12 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,  			goto out;  		if (unlikely(!PAGE_ALIGNED(req->tp_block_size)))  			goto out; +		min_frame_size = po->tp_hdrlen + po->tp_reserve;  		if (po->tp_version >= TPACKET_V3 && -		    req->tp_block_size <= -		    BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv) + sizeof(struct tpacket3_hdr)) +		    req->tp_block_size < +		    BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv) + min_frame_size)  			goto out; -		if (unlikely(req->tp_frame_size < po->tp_hdrlen + -					po->tp_reserve)) +		if (unlikely(req->tp_frame_size < min_frame_size))  			goto out;  		if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1)))  			goto out; @@ -4424,7 +4427,7 @@ static const struct proto_ops packet_ops_spkt = {  	.socketpair =	sock_no_socketpair,  	.accept =	sock_no_accept,  	.getname =	packet_getname_spkt, -	.poll_mask =	datagram_poll_mask, +	.poll =		datagram_poll,  	.ioctl =	packet_ioctl,  	.listen =	sock_no_listen,  	.shutdown =	sock_no_shutdown, @@ -4445,7 +4448,7 @@ static const struct proto_ops packet_ops = {  	.socketpair =	sock_no_socketpair,  	.accept =	sock_no_accept,  	.getname =	packet_getname, -	.poll_mask =	packet_poll_mask, +	.poll =		packet_poll,  	.ioctl =	packet_ioctl,  	.listen =	sock_no_listen,  	.shutdown =	sock_no_shutdown,  | 
