diff --git a/src/include/ipxe/if_arp.h b/src/include/ipxe/if_arp.h index 4eb1f80b..9d7b03fe 100644 --- a/src/include/ipxe/if_arp.h +++ b/src/include/ipxe/if_arp.h @@ -99,4 +99,14 @@ static inline void * arp_target_pa ( struct arphdr *arphdr ) { return ( arp_target_ha ( arphdr ) + arphdr->ar_hln ); } +/** ARP packet length + * + * @v arphdr ARP header + * @ret len Length (including header) + */ +static inline size_t arp_len ( struct arphdr *arphdr ) { + return ( sizeof ( *arphdr ) + + ( 2 * ( arphdr->ar_hln + arphdr->ar_pln ) ) ); +} + #endif /* _IPXE_IF_ARP_H */ diff --git a/src/net/arp.c b/src/net/arp.c index 1e27c44e..c9b4109a 100644 --- a/src/net/arp.c +++ b/src/net/arp.c @@ -139,8 +139,15 @@ static int arp_rx ( struct io_buffer *iobuf, struct net_device *netdev, struct arp_net_protocol *arp_net_protocol; struct net_protocol *net_protocol; struct ll_protocol *ll_protocol; + size_t len = iob_len ( iobuf ); int rc; + /* Sanity check */ + if ( ( len < sizeof ( *arphdr ) ) || ( len < arp_len ( arphdr ) ) ) { + rc = -EINVAL; + goto done; + } + /* Identify network-layer and link-layer protocols */ arp_net_protocol = arp_find_protocol ( arphdr->ar_pro ); if ( ! arp_net_protocol ) {