Re: [PATCH 4/5] net/packet: fix overflow in check for tp_reserve
From: Andrey Konovalov <hidden>
Date: 2017-03-28 15:12:49
On Tue, Mar 28, 2017 at 5:00 PM, Willem de Bruijn [off-list ref] wrote:
On Tue, Mar 28, 2017 at 10:00 AM, Andrey Konovalov [off-list ref] wrote:quoted
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.
Yes, you're right. Should I make macoff unsigned int to fix this?
quoted
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.
I will put it into a separate patch then.
quoted
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.
Just to group together all checks of tp_frame_size and tp_block_size. I'm not sure there's any difference between checking against po->tp_hdrlen + po->tp_reserve and just po->tp_reserve. I guess the correct check should be against TPACKET_ALIGN(po->tp_hdrlen) + 16 + po->tp_reserve. Should I use this value?
quoted
if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1))) goto out; -- 2.12.2.564.g063fe858b8-goog