changeset 1867:f0da5566cdab draft

Avoid a potential buffer overflow. Thanks to Christos Zoulas.
author Roy Marples <roy@marples.name>
date Tue, 19 Feb 2013 16:28:43 +0000
parents 6ced00f7d88e
children 4447b9139224
files arp.c
diffstat 1 files changed, 28 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/arp.c	Fri Feb 15 20:36:33 2013 +0000
+++ b/arp.c	Tue Feb 19 16:28:43 2013 +0000
@@ -45,34 +45,43 @@
 	(sizeof(struct arphdr) + (2 * sizeof(uint32_t)) + (2 * HWADDR_LEN))
 
 static int
-send_arp(const struct interface *iface, int op, in_addr_t sip, in_addr_t tip)
+send_arp(const struct interface *ifp, int op, in_addr_t sip, in_addr_t tip)
 {
 	uint8_t arp_buffer[ARP_LEN];
 	struct arphdr ar;
 	size_t len;
 	uint8_t *p;
-	int retval;
 
-	ar.ar_hrd = htons(iface->family);
+	ar.ar_hrd = htons(ifp->family);
 	ar.ar_pro = htons(ETHERTYPE_IP);
-	ar.ar_hln = iface->hwlen;
+	ar.ar_hln = ifp->hwlen;
 	ar.ar_pln = sizeof(sip);
 	ar.ar_op = htons(op);
-	memcpy(arp_buffer, &ar, sizeof(ar));
-	p = arp_buffer + sizeof(ar);
-	memcpy(p, iface->hwaddr, iface->hwlen);
-	p += iface->hwlen;
-	memcpy(p, &sip, sizeof(sip));
-	p += sizeof(sip);
-	/* ARP requests should ignore this */
-	retval = iface->hwlen;
-	while (retval--)
-		*p++ = '\0';
-	memcpy(p, &tip, sizeof(tip));
-	p += sizeof(tip);
-	len = p - arp_buffer;
-	retval = send_raw_packet(iface, ETHERTYPE_ARP, arp_buffer, len);
-	return retval;
+
+	p = arp_buffer;
+	len = sizeof(arp_buffer);
+
+#define CHECK(fun, b, l)						\
+	do {								\
+		if (len < (l))						\
+			goto eexit;					\
+		fun(p, (b), (l));					\
+		p += (l);						\
+		len -= (l);						\
+	} while (/* CONSTCOND */ 0)
+#define APPEND(b, l)	CHECK(memcpy, b, l)
+#define ZERO(l)		CHECK(memset, 0, l)
+
+	APPEND(&ar, sizeof(ar));
+	APPEND(ifp->hwaddr, ifp->hwlen);
+	APPEND(&sip, sizeof(sip));
+	ZERO(ifp->hwlen);
+	APPEND(&tip, sizeof(tip));
+	return send_raw_packet(ifp, ETHERTYPE_ARP, arp_buffer, len);
+
+eexit:
+	errno = ENOSPC;
+	return -1;
 }
 
 static void