Skip to content

Commit dc80811

Browse files
edumazetdavem330
authored andcommitted
packet: handle too big packets for PACKET_V3
af_packet can currently overwrite kernel memory by out of bound accesses, because it assumed a [new] block can always hold one frame. This is not generally the case, even if most existing tools do it right. This patch clamps too long frames as API permits, and issue a one time error on syslog. [ 394.357639] tpacket_rcv: packet too big, clamped from 5042 to 3966. macoff=82 In this example, packet header tp_snaplen was set to 3966, and tp_len was set to 5042 (skb->len) Signed-off-by: Eric Dumazet <[email protected]> Fixes: f6fb8f1 ("af-packet: TPACKET_V3 flexible buffer implementation.") Acked-by: Daniel Borkmann <[email protected]> Acked-by: Neil Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 564ee36 commit dc80811

File tree

2 files changed

+18
-0
lines changed

2 files changed

+18
-0
lines changed

net/packet/af_packet.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,7 @@ static void init_prb_bdqc(struct packet_sock *po,
632632
p1->tov_in_jiffies = msecs_to_jiffies(p1->retire_blk_tov);
633633
p1->blk_sizeof_priv = req_u->req3.tp_sizeof_priv;
634634

635+
p1->max_frame_len = p1->kblk_size - BLK_PLUS_PRIV(p1->blk_sizeof_priv);
635636
prb_init_ft_ops(p1, req_u);
636637
prb_setup_retire_blk_timer(po, tx_ring);
637638
prb_open_block(p1, pbd);
@@ -1942,6 +1943,18 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
19421943
if ((int)snaplen < 0)
19431944
snaplen = 0;
19441945
}
1946+
} else if (unlikely(macoff + snaplen >
1947+
GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len)) {
1948+
u32 nval;
1949+
1950+
nval = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len - macoff;
1951+
pr_err_once("tpacket_rcv: packet too big, clamped from %u to %u. macoff=%u\n",
1952+
snaplen, nval, macoff);
1953+
snaplen = nval;
1954+
if (unlikely((int)snaplen < 0)) {
1955+
snaplen = 0;
1956+
macoff = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len;
1957+
}
19451958
}
19461959
spin_lock(&sk->sk_receive_queue.lock);
19471960
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,
37833796
goto out;
37843797
if (unlikely(req->tp_block_size & (PAGE_SIZE - 1)))
37853798
goto out;
3799+
if (po->tp_version >= TPACKET_V3 &&
3800+
(int)(req->tp_block_size -
3801+
BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0)
3802+
goto out;
37863803
if (unlikely(req->tp_frame_size < po->tp_hdrlen +
37873804
po->tp_reserve))
37883805
goto out;

net/packet/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct tpacket_kbdq_core {
2929
char *pkblk_start;
3030
char *pkblk_end;
3131
int kblk_size;
32+
unsigned int max_frame_len;
3233
unsigned int knum_blocks;
3334
uint64_t knxt_seq_num;
3435
char *prev;

0 commit comments

Comments
 (0)