Re: [PATCH 4/5] net/packet: fix overflow in check for tp_reserve
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Date: 2017-03-28 15:02:18
On Tue, Mar 28, 2017 at 10:00 AM, Andrey Konovalov [off-list ref] wrote:
When calculating po->tp_hdrlen + po->tp_reserve the result can overflow. Fix by checking that tp_reserve <= INT_MAX on assign. This also takes cared of an overflow when calculating macoff = TPACKET_ALIGN(po->tp_hdrlen) + 16 + po->tp_reserve snaplen = skb->len macoff + snaplen since macoff ~ INT_MAX and snaplen < SKB_MAX_ALLOC.
This refers to the overflow of macoff + snaplen? Note that macoff is unsigned short, so will truncate any overflow from tp_reserve.
quoted hunk ↗ jump to hunk
Signed-off-by: Andrey Konovalov <redacted> --- net/packet/af_packet.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index c5c43fff8c01..28b49749d1af 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c@@ -3665,6 +3665,8 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv return -EBUSY; if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; + if (val > INT_MAX) + return -EINVAL;
This change on its own is sufficient to avoid the overflow. For net and backports to stable, this minimal patch is preferable.
quoted hunk ↗ jump to hunk
po->tp_reserve = val; return 0; }@@ -4200,6 +4202,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, if (unlikely((u64)req->tp_block_size * req->tp_block_nr > UINT_MAX)) goto out; + if (unlikely(po->tp_reserve >= req->tp_frame_size)) + goto out; if (unlikely(!PAGE_ALIGNED(req->tp_block_size))) goto out;@@ -4207,9 +4211,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, req->tp_block_size <= BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv)) goto out; - if (unlikely(req->tp_frame_size < po->tp_hdrlen + - po->tp_reserve)) - goto out;
Is there a reason that the test is moved up? It is probably not correct to remove tp_hdrlen from the test.
if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1)))
goto out;
--
2.12.2.564.g063fe858b8-goog