lkml.org 
[lkml]   [2019]   [Apr]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 031/101] net: ip6_gre: fix possible use-after-free in ip6erspan_rcv
    Date
    [ Upstream commit 2a3cabae4536edbcb21d344e7aa8be7a584d2afb ]

    erspan_v6 tunnels run __iptunnel_pull_header on received skbs to remove
    erspan header. This can determine a possible use-after-free accessing
    pkt_md pointer in ip6erspan_rcv since the packet will be 'uncloned'
    running pskb_expand_head if it is a cloned gso skb (e.g if the packet has
    been sent though a veth device). Fix it resetting pkt_md pointer after
    __iptunnel_pull_header

    Fixes: 1d7e2ed22f8d ("net: erspan: refactor existing erspan code")
    Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    net/ipv6/ip6_gre.c | 21 +++++++++++++--------
    1 file changed, 13 insertions(+), 8 deletions(-)

    diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
    index faed98dab913..c4a7db62658e 100644
    --- a/net/ipv6/ip6_gre.c
    +++ b/net/ipv6/ip6_gre.c
    @@ -540,11 +540,10 @@ static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
    return PACKET_REJECT;
    }

    -static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
    - struct tnl_ptk_info *tpi)
    +static int ip6erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
    + int gre_hdr_len)
    {
    struct erspan_base_hdr *ershdr;
    - struct erspan_metadata *pkt_md;
    const struct ipv6hdr *ipv6h;
    struct erspan_md2 *md2;
    struct ip6_tnl *tunnel;
    @@ -563,18 +562,16 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
    if (unlikely(!pskb_may_pull(skb, len)))
    return PACKET_REJECT;

    - ershdr = (struct erspan_base_hdr *)skb->data;
    - pkt_md = (struct erspan_metadata *)(ershdr + 1);
    -
    if (__iptunnel_pull_header(skb, len,
    htons(ETH_P_TEB),
    false, false) < 0)
    return PACKET_REJECT;

    if (tunnel->parms.collect_md) {
    + struct erspan_metadata *pkt_md, *md;
    struct metadata_dst *tun_dst;
    struct ip_tunnel_info *info;
    - struct erspan_metadata *md;
    + unsigned char *gh;
    __be64 tun_id;
    __be16 flags;

    @@ -587,6 +584,14 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
    if (!tun_dst)
    return PACKET_REJECT;

    + /* skb can be uncloned in __iptunnel_pull_header, so
    + * old pkt_md is no longer valid and we need to reset
    + * it
    + */
    + gh = skb_network_header(skb) +
    + skb_network_header_len(skb);
    + pkt_md = (struct erspan_metadata *)(gh + gre_hdr_len +
    + sizeof(*ershdr));
    info = &tun_dst->u.tun_info;
    md = ip_tunnel_info_opts(info);
    md->version = ver;
    @@ -623,7 +628,7 @@ static int gre_rcv(struct sk_buff *skb)

    if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
    tpi.proto == htons(ETH_P_ERSPAN2))) {
    - if (ip6erspan_rcv(skb, hdr_len, &tpi) == PACKET_RCVD)
    + if (ip6erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
    return 0;
    goto out;
    }
    --
    2.19.1


    \
     
     \ /
      Last update: 2019-04-15 21:24    [W:4.168 / U:0.156 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site