summaryrefslogtreecommitdiffstats
path: root/include/linux/netdevice.h
diff options
context:
space:
mode:
authorWillem de Bruijn <willemb@google.com>2016-03-09 21:58:32 -0500
committerDavid S. Miller <davem@davemloft.net>2016-03-09 22:13:01 -0500
commit2793a23aacbd754dbbb5cb75093deb7e4103bace (patch)
tree736ba574091e9959f0e47fa2be122b46f26e372d /include/linux/netdevice.h
parent9531ab65f4ec066a6e6617a08a293c60397a161b (diff)
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>
Diffstat (limited to 'include/linux/netdevice.h')
-rw-r--r--include/linux/netdevice.h22
1 files changed, 20 insertions, 2 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index efe7cec111fa..fd30cb545c45 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -268,6 +268,7 @@ struct header_ops {
268 void (*cache_update)(struct hh_cache *hh, 268 void (*cache_update)(struct hh_cache *hh,
269 const struct net_device *dev, 269 const struct net_device *dev,
270 const unsigned char *haddr); 270 const unsigned char *haddr);
271 bool (*validate)(const char *ll_header, unsigned int len);
271}; 272};
272 273
273/* These flag bits are private to the generic network queueing 274/* These flag bits are private to the generic network queueing
@@ -1459,8 +1460,7 @@ enum netdev_priv_flags {
1459 * @dma: DMA channel 1460 * @dma: DMA channel
1460 * @mtu: Interface MTU value 1461 * @mtu: Interface MTU value
1461 * @type: Interface hardware type 1462 * @type: Interface hardware type
1462 * @hard_header_len: Hardware header length, which means that this is the 1463 * @hard_header_len: Maximum hardware header length.
1463 * minimum size of a packet.
1464 * 1464 *
1465 * @needed_headroom: Extra headroom the hardware may need, but not in all 1465 * @needed_headroom: Extra headroom the hardware may need, but not in all
1466 * cases can this be guaranteed 1466 * cases can this be guaranteed
@@ -2687,6 +2687,24 @@ static inline int dev_parse_header(const struct sk_buff *skb,
2687 return dev->header_ops->parse(skb, haddr); 2687 return dev->header_ops->parse(skb, haddr);
2688} 2688}
2689 2689
2690/* ll_header must have at least hard_header_len allocated */
2691static 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;
2706}
2707
2690typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len); 2708typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len);
2691int register_gifconf(unsigned int family, gifconf_func_t *gifconf); 2709int register_gifconf(unsigned int family, gifconf_func_t *gifconf);
2692static inline int unregister_gifconf(unsigned int family) 2710static inline int unregister_gifconf(unsigned int family)