Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: validate variable length ll headers

Netdevice parameter hard_header_len is variously interpreted both as
an upper and lower bound on link layer header length. The field is
used as upper bound when reserving room at allocation, as lower bound
when validating user input in PF_PACKET.

Clarify the definition to be maximum header length. For validation
of untrusted headers, add an optional validate member to header_ops.

Allow bypassing of validation by passing CAP_SYS_RAWIO, for instance
for deliberate testing of corrupt input. In this case, pad trailing
bytes, as some device drivers expect completely initialized headers.

See also http://comments.gmane.org/gmane.linux.network/401064

Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Willem de Bruijn and committed by
David S. Miller
2793a23a 9531ab65

+20 -2
+20 -2
include/linux/netdevice.h
··· 268 268 void (*cache_update)(struct hh_cache *hh, 269 269 const struct net_device *dev, 270 270 const unsigned char *haddr); 271 + bool (*validate)(const char *ll_header, unsigned int len); 271 272 }; 272 273 273 274 /* These flag bits are private to the generic network queueing ··· 1460 1459 * @dma: DMA channel 1461 1460 * @mtu: Interface MTU value 1462 1461 * @type: Interface hardware type 1463 - * @hard_header_len: Hardware header length, which means that this is the 1464 - * minimum size of a packet. 1462 + * @hard_header_len: Maximum hardware header length. 1465 1463 * 1466 1464 * @needed_headroom: Extra headroom the hardware may need, but not in all 1467 1465 * cases can this be guaranteed ··· 2685 2685 if (!dev->header_ops || !dev->header_ops->parse) 2686 2686 return 0; 2687 2687 return dev->header_ops->parse(skb, haddr); 2688 + } 2689 + 2690 + /* ll_header must have at least hard_header_len allocated */ 2691 + static inline bool dev_validate_header(const struct net_device *dev, 2692 + char *ll_header, int len) 2693 + { 2694 + if (likely(len >= dev->hard_header_len)) 2695 + return true; 2696 + 2697 + if (capable(CAP_SYS_RAWIO)) { 2698 + memset(ll_header + len, 0, dev->hard_header_len - len); 2699 + return true; 2700 + } 2701 + 2702 + if (dev->header_ops && dev->header_ops->validate) 2703 + return dev->header_ops->validate(ll_header, len); 2704 + 2705 + return false; 2688 2706 } 2689 2707 2690 2708 typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len);