lkml.org 
[lkml]   [2021]   [Jul]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.13 572/800] ipv6: fix out-of-bound access in ip6_parse_tlv()
    Date
    From: Eric Dumazet <edumazet@google.com>

    [ Upstream commit 624085a31c1ad6a80b1e53f686bf6ee92abbf6e8 ]

    First problem is that optlen is fetched without checking
    there is more than one byte to parse.

    Fix this by taking care of IPV6_TLV_PAD1 before
    fetching optlen (under appropriate sanity checks against len)

    Second problem is that IPV6_TLV_PADN checks of zero
    padding are performed before the check of remaining length.

    Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
    Fixes: c1412fce7ecc ("net/ipv6/exthdrs.c: Strict PadN option checking")
    Signed-off-by: Eric Dumazet <edumazet@google.com>
    Cc: Paolo Abeni <pabeni@redhat.com>
    Cc: Tom Herbert <tom@herbertland.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    net/ipv6/exthdrs.c | 27 +++++++++++++--------------
    1 file changed, 13 insertions(+), 14 deletions(-)

    diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
    index 6f7da8f3e2e5..26882e165c9e 100644
    --- a/net/ipv6/exthdrs.c
    +++ b/net/ipv6/exthdrs.c
    @@ -135,18 +135,23 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
    len -= 2;

    while (len > 0) {
    - int optlen = nh[off + 1] + 2;
    - int i;
    + int optlen, i;

    - switch (nh[off]) {
    - case IPV6_TLV_PAD1:
    - optlen = 1;
    + if (nh[off] == IPV6_TLV_PAD1) {
    padlen++;
    if (padlen > 7)
    goto bad;
    - break;
    + off++;
    + len--;
    + continue;
    + }
    + if (len < 2)
    + goto bad;
    + optlen = nh[off + 1] + 2;
    + if (optlen > len)
    + goto bad;

    - case IPV6_TLV_PADN:
    + if (nh[off] == IPV6_TLV_PADN) {
    /* RFC 2460 states that the purpose of PadN is
    * to align the containing header to multiples
    * of 8. 7 is therefore the highest valid value.
    @@ -163,12 +168,7 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
    if (nh[off + i] != 0)
    goto bad;
    }
    - break;
    -
    - default: /* Other TLV code so scan list */
    - if (optlen > len)
    - goto bad;
    -
    + } else {
    tlv_count++;
    if (tlv_count > max_count)
    goto bad;
    @@ -188,7 +188,6 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
    return false;

    padlen = 0;
    - break;
    }
    off += optlen;
    len -= optlen;
    --
    2.30.2


    \
     
     \ /
      Last update: 2021-07-12 11:09    [W:2.563 / U:0.372 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site