Message ID | 20170207205721.23207-2-willemdebruijn.kernel@gmail.com |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
On Tue, 2017-02-07 at 15:57 -0500, Willem de Bruijn wrote: > From: Willem de Bruijn <willemb@google.com> > > The stack must not pass packets to device drivers that are shorter > than the minimum link layer header length. > > Previously, packet sockets would drop packets smaller than or equal > to dev->hard_header_len, but this has false positives. Zero length > payload is used over Ethernet. Other link layer protocols support > variable length headers. Support for validation of these protocols > removed the min length check for all protocols. > > Introduce an explicit dev->min_header_len parameter and drop all > packets below this value. Initially, set it to non-zero only for > Ethernet and loopback. Other protocols can follow in a patch to > net-next. > > Fixes: 9ed988cd5915 ("packet: validate variable length ll headers") > Reported-by: Sowmini Varadhan <sowmini.varadhan@oracle.com> > Signed-off-by: Willem de Bruijn <willemb@google.com> > --- Acked-by: Eric Dumazet <edumazet@google.com>
On (02/07/17 15:57), Willem de Bruijn wrote: > > From: Willem de Bruijn <willemb@google.com> > > The stack must not pass packets to device drivers that are shorter > than the minimum link layer header length. Acked-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 1e05b7c2d157..0844f8496413 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -164,6 +164,7 @@ static void loopback_setup(struct net_device *dev) { dev->mtu = 64 * 1024; dev->hard_header_len = ETH_HLEN; /* 14 */ + dev->min_header_len = ETH_HLEN; /* 14 */ dev->addr_len = ETH_ALEN; /* 6 */ dev->type = ARPHRD_LOOPBACK; /* 0x0001*/ dev->flags = IFF_LOOPBACK; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 70ad0291d517..27914672602d 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1511,6 +1511,7 @@ enum netdev_priv_flags { * @max_mtu: Interface Maximum MTU value * @type: Interface hardware type * @hard_header_len: Maximum hardware header length. + * @min_header_len: Minimum hardware header length * * @needed_headroom: Extra headroom the hardware may need, but not in all * cases can this be guaranteed @@ -1728,6 +1729,7 @@ struct net_device { unsigned int max_mtu; unsigned short type; unsigned short hard_header_len; + unsigned short min_header_len; unsigned short needed_headroom; unsigned short needed_tailroom; @@ -2694,6 +2696,8 @@ static inline bool dev_validate_header(const struct net_device *dev, { if (likely(len >= dev->hard_header_len)) return true; + if (len < dev->min_header_len) + return false; if (capable(CAP_SYS_RAWIO)) { memset(ll_header + len, 0, dev->hard_header_len - len); diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 8c5a479681ca..516c87e75de7 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -356,6 +356,7 @@ void ether_setup(struct net_device *dev) dev->header_ops = ð_header_ops; dev->type = ARPHRD_ETHER; dev->hard_header_len = ETH_HLEN; + dev->min_header_len = ETH_HLEN; dev->mtu = ETH_DATA_LEN; dev->min_mtu = ETH_MIN_MTU; dev->max_mtu = ETH_DATA_LEN;