lkml.org 
[lkml]   [2018]   [May]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 315/496] vlan: Fix vlan insertion for packets without ethernet header
    Date
    4.14-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>

    [ Upstream commit c769accdf3d8a103940bea2979b65556718567e9 ]

    In some situation vlan packets do not have ethernet headers. One example
    is packets from tun devices. Users can specify vlan protocol in tun_pi
    field instead of IP protocol. When we have a vlan device with reorder_hdr
    disabled on top of the tun device, such packets from tun devices are
    untagged in skb_vlan_untag() and vlan headers will be inserted back in
    vlan_insert_inner_tag().

    vlan_insert_inner_tag() however did not expect packets without ethernet
    headers, so in such a case size argument for memmove() underflowed.

    We don't need to copy headers for packets which do not have preceding
    headers of vlan headers, so skip memmove() in that case.
    Also don't write vlan protocol in skb->data when it does not have enough
    room for it.

    Fixes: cbe7128c4b92 ("vlan: Fix out of order vlan headers with reorder header off")
    Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    include/linux/if_vlan.h | 15 +++++++++++++--
    1 file changed, 13 insertions(+), 2 deletions(-)

    --- a/include/linux/if_vlan.h
    +++ b/include/linux/if_vlan.h
    @@ -323,13 +323,24 @@ static inline int __vlan_insert_inner_ta
    skb_push(skb, VLAN_HLEN);

    /* Move the mac header sans proto to the beginning of the new header. */
    - memmove(skb->data, skb->data + VLAN_HLEN, mac_len - ETH_TLEN);
    + if (likely(mac_len > ETH_TLEN))
    + memmove(skb->data, skb->data + VLAN_HLEN, mac_len - ETH_TLEN);
    skb->mac_header -= VLAN_HLEN;

    veth = (struct vlan_ethhdr *)(skb->data + mac_len - ETH_HLEN);

    /* first, the ethernet type */
    - veth->h_vlan_proto = vlan_proto;
    + if (likely(mac_len >= ETH_TLEN)) {
    + /* h_vlan_encapsulated_proto should already be populated, and
    + * skb->data has space for h_vlan_proto
    + */
    + veth->h_vlan_proto = vlan_proto;
    + } else {
    + /* h_vlan_encapsulated_proto should not be populated, and
    + * skb->data has no space for h_vlan_proto
    + */
    + veth->h_vlan_encapsulated_proto = skb->protocol;
    + }

    /* now, the TCI */
    veth->h_vlan_TCI = htons(vlan_tci);

    \
     
     \ /
      Last update: 2018-05-28 14:52    [W:4.063 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site