Still looking for OK's.

On Wed, Nov 26, 2014 at 17:18 +0100, Mike Belopuhov wrote:
> > 
> > better diff.  the problem is that dissectors use packetp and
> > snapend pointers themselves therefore they should be pointing
> > to the newly allocated structure.  we can restore them once
> > we're done with the inner content and go back to the caller
> > to see if we need to hexdump the contents.
> > 
> > i'll see if i can cook and test the ipv6 version.
> > 
> > OK?
> > 
> 
> now with an ip6 version and i've made sure that this fixes
> dumping unaligned ipv6 packets as well.  in the meantime
> jsg@ has lured me into looking at the afl crash in the same
> code and it looks like the check from ip6_print is useful
> here: if we haven't got enough data for a header, don't
> bother with anything else and just bail.
> 
> ok?
> 
> diff --git usr.sbin/tcpdump/print-ip.c usr.sbin/tcpdump/print-ip.c
> index 3f4194c..e9d2185 100644
> --- usr.sbin/tcpdump/print-ip.c
> +++ usr.sbin/tcpdump/print-ip.c
> @@ -351,22 +351,27 @@ in_cksum(const u_short *addr, register int len, int 
> csum)
>   * print an IP datagram.
>   */
>  void
>  ip_print(register const u_char *bp, register u_int length)
>  {
> +     static u_char *abuf = NULL;
>       register const struct ip *ip;
>       register u_int hlen, len, off;
>       register const u_char *cp;
> +     const u_char *pktp = packetp;
> +     const u_char *send = snapend;
>  
>       ip = (const struct ip *)bp;
> +     if ((u_char *)(ip + 1) > snapend) {
> +             printf("[|ip]");
> +             return;
> +     }
> +
>       /*
>        * If the IP header is not aligned, copy into abuf.
> -      * This will never happen with BPF.  It does happen with raw packet
> -      * dumps from -r.
>        */
>       if ((intptr_t)ip & (sizeof(long)-1)) {
> -             static u_char *abuf = NULL;
>               static int didwarn = 0;
>               int clen = snapend - bp;
>  
>               if (clen > snaplen)
>                       clen = snaplen;
> @@ -387,11 +392,11 @@ ip_print(register const u_char *bp, register u_int 
> length)
>       }
>  
>       TCHECK(*ip);
>       if (ip->ip_v != IPVERSION) {
>               (void)printf("bad-ip-version %u", ip->ip_v);
> -             return;
> +             goto out;
>       }
>  
>       len = ntohs(ip->ip_len);
>       if (length < len) {
>               (void)printf("truncated-ip - %d bytes missing!",
> @@ -400,11 +405,11 @@ ip_print(register const u_char *bp, register u_int 
> length)
>       }
>  
>       hlen = ip->ip_hl * 4;
>       if (hlen < sizeof(struct ip) || hlen > len) {
>               (void)printf("bad-hlen %d", hlen);
> -             return;
> +             goto out;
>       }
>  
>       len -= hlen;
>  
>       /*
> @@ -465,11 +470,11 @@ ip_print(register const u_char *bp, register u_int 
> length)
>                                            ipaddr_string(&ip->ip_src),
>                                            ipaddr_string(&ip->ip_dst));
>                       ip_print(cp, len);
>                       if (! vflag) {
>                               printf(" (encap)");
> -                             return;
> +                             goto out;
>                       }
>                       break;
>  
>  #ifdef INET6
>  #ifndef IPPROTO_IPV6
> @@ -482,11 +487,11 @@ ip_print(register const u_char *bp, register u_int 
> length)
>                                            ipaddr_string(&ip->ip_src),
>                                            ipaddr_string(&ip->ip_dst));
>                       ip6_print(cp, len);
>                       if (! vflag) {
>                               printf(" (encap)");
> -                             return;
> +                             goto out;
>                       }
>                       break;
>  #endif /*INET6*/
>  
>  #ifndef IPPROTO_GRE
> @@ -499,11 +504,11 @@ ip_print(register const u_char *bp, register u_int 
> length)
>                                            ipaddr_string(&ip->ip_dst));
>                       /* do it */
>                       gre_print(cp, len);
>                       if (! vflag) {
>                               printf(" (gre encap)");
> -                             return;
> +                             goto out;
>                       }
>                       break;
>  
>  #ifndef IPPROTO_ESP
>  #define IPPROTO_ESP 50
> @@ -528,11 +533,11 @@ ip_print(register const u_char *bp, register u_int 
> length)
>                                            ipaddr_string(&ip->ip_src),
>                                            ipaddr_string(&ip->ip_dst));
>                       mobile_print(cp, len);
>                       if (! vflag) {
>                               printf(" (mobile encap)");
> -                             return;
> +                             goto out;
>                       }
>                       break;
>  
>  #ifndef IPPROTO_ETHERIP
>  #define IPPROTO_ETHERIP      97
> @@ -653,10 +658,13 @@ ip_print(register const u_char *bp, register u_int 
> length)
>                       (void)printf("%soptlen=%d", sep, hlen);
>                       ip_optprint((u_char *)(ip + 1), hlen);
>               }
>               printf(")");
>       }
> +out:
> +     packetp = pktp;
> +     snapend = send;
>       return;
>  
>  trunc:
>       printf("[|ip]");
>  }
> diff --git usr.sbin/tcpdump/print-ip6.c usr.sbin/tcpdump/print-ip6.c
> index 648de8c..03c9c84 100644
> --- usr.sbin/tcpdump/print-ip6.c
> +++ usr.sbin/tcpdump/print-ip6.c
> @@ -50,26 +50,30 @@
>   * print an IP6 datagram.
>   */
>  void
>  ip6_print(register const u_char *bp, register u_int length)
>  {
> +     static u_char *abuf = NULL;
>       register const struct ip6_hdr *ip6;
>       register int hlen;
>       register int len;
>       register const u_char *cp;
> +     const u_char *pktp = packetp;
> +     const u_char *send = snapend;
>       int nh;
>       u_int flow;
> -     
> +
>       ip6 = (const struct ip6_hdr *)bp;
> +     if ((u_char *)(ip6 + 1) > snapend) {
> +             printf("[|ip6]");
> +             return;
> +     }
>  
>       /*
>        * The IP header is not word aligned, so copy into abuf.
> -      * This will never happen with BPF.  It does happen with
> -      * raw packet dumps from -r.
>        */
>       if ((intptr_t)ip6 & (sizeof(long)-1)) {
> -             static u_char *abuf = NULL;
>               static int didwarn = 0;
>               int clen = snapend - bp;
>               if (clen > snaplen)
>                       clen = snaplen;
>  
> @@ -87,21 +91,17 @@ ip6_print(register const u_char *bp, register u_int 
> length)
>                       warning("compensating for unaligned libpcap packets");
>                       ++didwarn;
>               }
>       }
>  
> -     if ((u_char *)(ip6 + 1) > snapend) {
> -             printf("[|ip6]");
> -             return;
> -     }
>       if (length < sizeof (struct ip6_hdr)) {
>               (void)printf("truncated-ip6 %d", length);
> -             return;
> +             goto out;
>       }
>       if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
>               (void)printf("bad-ip6-version %u", ip6->ip6_vfc >> 4);
> -             return;
> +             goto out;
>       }
>       hlen = sizeof(struct ip6_hdr);
>  
>       len = ntohs(ip6->ip6_plen);
>       if (length < len + hlen)
> @@ -204,11 +204,11 @@ ip6_print(register const u_char *bp, register u_int 
> length)
>               if (hlen == 0)
>                       break;
>       }
>  
>   end:
> -     
> +
>       flow = ntohl(ip6->ip6_flow);
>  #if 0
>       /* rfc1883 */
>       if (flow & 0x0f000000)
>               (void)printf(" [pri 0x%x]", (flow & 0x0f000000) >> 24);
> @@ -230,8 +230,12 @@ ip6_print(register const u_char *bp, register u_int 
> length)
>               (void)printf("len %d", len);
>               if (ip6->ip6_hlim > 1)
>                       (void)printf(", hlim %d", (int)ip6->ip6_hlim);
>               printf(")");
>       }
> +
> + out:
> +     packetp = pktp;
> +     snapend = send;
>  }
>  
>  #endif /* INET6 */

Reply via email to