Ignore:
Timestamp:
Apr 16, 2017, 3:07:01 PM (5 weeks ago)
Author:
brainslayer
Message:

update

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/linux/universal/linux-3.18/net/ipv6/ip6_tunnel.c

    r30256 r31869  
    408408__u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw)
    409409{
    410         const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw;
    411         __u8 nexthdr = ipv6h->nexthdr;
    412         __u16 off = sizeof(*ipv6h);
     410        const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw;
     411        unsigned int nhoff = raw - skb->data;
     412        unsigned int off = nhoff + sizeof(*ipv6h);
     413        u8 next, nexthdr = ipv6h->nexthdr;
    413414
    414415        while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) {
    415                 __u16 optlen = 0;
    416416                struct ipv6_opt_hdr *hdr;
    417                 if (raw + off + sizeof(*hdr) > skb->data &&
    418                     !pskb_may_pull(skb, raw - skb->data + off + sizeof (*hdr)))
     417                u16 optlen;
     418
     419                if (!pskb_may_pull(skb, off + sizeof(*hdr)))
    419420                        break;
    420421
    421                 hdr = (struct ipv6_opt_hdr *) (raw + off);
     422                hdr = (struct ipv6_opt_hdr *)(skb->data + off);
    422423                if (nexthdr == NEXTHDR_FRAGMENT) {
    423424                        struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr;
     
    430431                        optlen = ipv6_optlen(hdr);
    431432                }
     433                /* cache hdr->nexthdr, since pskb_may_pull() might
     434                 * invalidate hdr
     435                 */
     436                next = hdr->nexthdr;
    432437                if (nexthdr == NEXTHDR_DEST) {
    433                         __u16 i = off + 2;
     438                        u16 i = 2;
     439
     440                        /* Remember : hdr is no longer valid at this point. */
     441                        if (!pskb_may_pull(skb, off + optlen))
     442                                break;
     443
    434444                        while (1) {
    435445                                struct ipv6_tlv_tnl_enc_lim *tel;
    436446
    437447                                /* No more room for encapsulation limit */
    438                                 if (i + sizeof (*tel) > off + optlen)
     448                                if (i + sizeof(*tel) > optlen)
    439449                                        break;
    440450
    441                                 tel = (struct ipv6_tlv_tnl_enc_lim *) &raw[i];
     451                                tel = (struct ipv6_tlv_tnl_enc_lim *)(skb->data + off + i);
    442452                                /* return index of option if found and valid */
    443453                                if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT &&
    444454                                    tel->length == 1)
    445                                         return i;
     455                                        return i + off - nhoff;
    446456                                /* else jump to next option */
    447457                                if (tel->type)
     
    451461                        }
    452462                }
    453                 nexthdr = hdr->nexthdr;
     463                nexthdr = next;
    454464                off += optlen;
    455465        }
Note: See TracChangeset for help on using the changeset viewer.