diff options
| author | Roy Marples <roy@marples.name> | 2013-02-19 16:28:43 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2013-02-19 16:28:43 +0000 |
| commit | bae38a5f3c604fe56669c094d9c9ae64dcbcc424 (patch) | |
| tree | 6ec7bee7ceccb68d47723572b5574cc02cde6cee | |
| parent | ec19d7914fcdd1718dd38944abb3549e68444529 (diff) | |
| download | dhcpcd-bae38a5f3c604fe56669c094d9c9ae64dcbcc424.tar.xz | |
Avoid a potential buffer overflow.
Thanks to Christos Zoulas.
| -rw-r--r-- | arp.c | 47 |
1 files changed, 28 insertions, 19 deletions
@@ -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 |
