Skip to contentSkip to conversation

net/packet: fix multiple overflow issues in ring buffers

PATCH In review Andrey Konovalov 3 participants 8 messages Mar 29, 2017 – Mar 30, 2017

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

v2 cover net/packet: fix multiple overflow issues in ring buffers

This patchset addresses multiple overflows and signedness-related issues in packet socket ring buffers.

Changes in v2:
- remove cleanup patches, will send in a separate patchset
- use a > UINT_MAX / b to check for a * b overflow

Andrey Konovalov (3):
net/packet: fix overflow in check for priv area size net/packet: fix overflow in check for tp_frame_nr net/packet: fix overflow in check for tp_reserve

 net/packet/af_packet.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
Signature · 1 line
2.12.2.564.g063fe858b8-goog
#1 lore raw

PATCH v2 1/3 net/packet: fix overflow in check for priv area size

Subtracting tp_sizeof_priv from tp_block_size and casting to int to check whether one is less then the other doesn't always work (both of them are unsigned ints).

Compare them as is instead.

Also cast tp_sizeof_priv to u64 before using BLK_PLUS_PRIV, as it can overflow inside BLK_PLUS_PRIV otherwise.

---
 net/packet/af_packet.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
net/packet/af_packet.c +2 -2
index a0dbe7ca8f72..2323ee35dc09 100644
@@ -4193,8 +4193,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
 		if (unlikely(!PAGE_ALIGNED(req->tp_block_size)))
 			goto out;
 		if (po->tp_version >= TPACKET_V3 &&
-		    (int)(req->tp_block_size -
-			  BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0)
+		    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))
Signature · 1 line
2.12.2.564.g063fe858b8-goog
Acked-by on v2 1/3
#2 lore raw

Re: [PATCH net v2 1/3] net/packet: fix overflow in check for priv area size

Quoted 11 lines · Andrey Konovalov

Subtracting tp_sizeof_priv from tp_block_size and casting to int to check whether one is less then the other doesn't always work (both of them are unsigned ints).

Compare them as is instead.

Also cast tp_sizeof_priv to u64 before using BLK_PLUS_PRIV, as it can overflow inside BLK_PLUS_PRIV otherwise.

---

#3 lore raw

PATCH v2 2/3 net/packet: fix overflow in check for tp_frame_nr

In reply to Andrey Konovalov

When calculating rb->frames_per_block * req->tp_block_nr the result can overflow.

Add a check that tp_block_size * tp_block_nr <= UINT_MAX.

Since frames_per_block <= tp_block_size, the expression would never overflow.

---
 net/packet/af_packet.c | 2 ++
 1 file changed, 2 insertions(+)
net/packet/af_packet.c +2 -0
index 2323ee35dc09..3ac286ebb2f4 100644
@@ -4205,6 +4205,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
 		rb->frames_per_block = req->tp_block_size / req->tp_frame_size;
 		if (unlikely(rb->frames_per_block == 0))
 			goto out;
+		if (unlikely(req->tp_block_size > UINT_MAX / req->tp_block_nr))
+			goto out;
 		if (unlikely((rb->frames_per_block * req->tp_block_nr) !=
 					req->tp_frame_nr))
 			goto out;
Signature · 1 line
2.12.2.564.g063fe858b8-goog
Acked-by on v2 2/3
#4 lore raw

Re: [PATCH net v2 2/3] net/packet: fix overflow in check for tp_frame_nr

Quoted 10 lines · Andrey Konovalov

When calculating rb->frames_per_block * req->tp_block_nr the result can overflow.

Add a check that tp_block_size * tp_block_nr <= UINT_MAX.

Since frames_per_block <= tp_block_size, the expression would never overflow.

---

#5 lore raw

PATCH v2 3/3 net/packet: fix overflow in check for tp_reserve

In reply to Andrey Konovalov

When calculating po->tp_hdrlen + po->tp_reserve the result can overflow.

Fix by checking that tp_reserve <= INT_MAX on assign.

---
 net/packet/af_packet.c | 2 ++
 1 file changed, 2 insertions(+)
net/packet/af_packet.c +2 -0
index 3ac286ebb2f4..8489beff5c25 100644
@@ -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;
 		po->tp_reserve = val;
 		return 0;
 	}
Signature · 1 line
2.12.2.564.g063fe858b8-goog
maintainer
#7 lore raw
In reply to Andrey Konovalov

From: Andrey Konovalov <[email protected]>
Date: Wed, 29 Mar 2017 16:11:19 +0200

Quoted 6 lines

This patchset addresses multiple overflows and signedness-related issues in packet socket ring buffers.

Changes in v2:
- remove cleanup patches, will send in a separate patchset
- use a > UINT_MAX / b to check for a * b overflow

All applied and queued up for -stable, thanks.