diff options
Diffstat (limited to 'net/packet/af_packet.c')
| -rw-r--r-- | net/packet/af_packet.c | 17 | 
1 files changed, 17 insertions, 0 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 8d9f8042705a..93896d2092f6 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -632,6 +632,7 @@ static void init_prb_bdqc(struct packet_sock *po,  	p1->tov_in_jiffies = msecs_to_jiffies(p1->retire_blk_tov);  	p1->blk_sizeof_priv = req_u->req3.tp_sizeof_priv; +	p1->max_frame_len = p1->kblk_size - BLK_PLUS_PRIV(p1->blk_sizeof_priv);  	prb_init_ft_ops(p1, req_u);  	prb_setup_retire_blk_timer(po, tx_ring);  	prb_open_block(p1, pbd); @@ -1942,6 +1943,18 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,  			if ((int)snaplen < 0)  				snaplen = 0;  		} +	} else if (unlikely(macoff + snaplen > +			    GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len)) { +		u32 nval; + +		nval = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len - macoff; +		pr_err_once("tpacket_rcv: packet too big, clamped from %u to %u. macoff=%u\n", +			    snaplen, nval, macoff); +		snaplen = nval; +		if (unlikely((int)snaplen < 0)) { +			snaplen = 0; +			macoff = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len; +		}  	}  	spin_lock(&sk->sk_receive_queue.lock);  	h.raw = packet_current_rx_frame(po, skb, @@ -3783,6 +3796,10 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,  			goto out;  		if (unlikely(req->tp_block_size & (PAGE_SIZE - 1)))  			goto out; +		if (po->tp_version >= TPACKET_V3 && +		    (int)(req->tp_block_size - +			  BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0) +			goto out;  		if (unlikely(req->tp_frame_size < po->tp_hdrlen +  					po->tp_reserve))  			goto out;  |