On 14/06/16(Tue) 20:10, Florian Obser wrote:
> On Tue, Jun 14, 2016 at 06:26:00PM +0200, Martin Pieuchot wrote:
> > On 14/06/16(Tue) 15:18, Florian Obser wrote:
> > > Hi,
> > > I'm seeing this panic on my v6 gateway running in a vm (don't ask):
> > > It has a v6 tunnel via HE on gif0.
> > > 
> > > I hope I copied all relevant information, if not, my appologies, I'm
> > > in a hurry currently, please just ask for more.
> > > 
> > > I will probably investigate more when I'm home :)
> > > 
> > > panic: trap type 6, code=0, pc=ffffffff812fe70f
> > > Starting stack trace...
> > > panic() at panic+0x10b
> > > trap() at trap+0x7b8
> > > --- trap (number 6) ---
> > > ip6_output_ipsec_lookup() at ip6_output_ipsec_lookup+0x6f
> > > ip6_output() at ip6_output+0x21c
> > > esp_output_cb() at esp_output_cb+0x135
> > > taskq_thread() at taskq_thread+0x6c
> > > end trace frame: 0x0, count: 251
> > > End of stack trace.
> > > syncing disks... done
> > 
> > This seems to be an invalid `'tdbi'' dereference in 
> > ip6_output_ipsec_lookup():
> > 
> > 2890:               tdbi = (struct tdb_ident *)(mtag + 1);
> > 2891: HERE ->       if (tdbi->spi == tdb->tdb_spi &&
> > 2892:                   tdbi->proto == tdb->tdb_sproto &&
> >                 ...
> > 
> > Markus, Mike any idea how this could happen?
> 
> I tracked it down to ref 1.89 of ip6_forward.c / ref 1.205 ip6_output.c:
> "factor out ipsec into ip6_output_ipsec_{lookup,send}(); ok mpi@, naddy@"
> 
> The problem is that we are not exiting the "loop detection" for loop
> when tdb is set to NULL. We enter again and dereference tdb -> boom.
> 
> The following diff makes ip6_output_ipsec_lookup() similar to
> ip_output_ipsec_lookup().
> It's easier to see what the diff is doing by applying and doing diff -b.
> OK?

ok mpi@

> p.s. I also note that the v4 and v6 version are really similiar, we
> can probably merge them. Wonder if it's worth it or if it's best to
> keep v4 and v6 seperate...

For the moment we're trying to reduce the size of "#ifdef IPSEC" chunks
inside the IP paths.  But reducing differences between v4 and v6 by
reusing code is a good thing.

> diff --git ip6_output.c ip6_output.c
> index 64eea86..3adaa7d 100644
> --- ip6_output.c
> +++ ip6_output.c
> @@ -2882,21 +2882,21 @@ ip6_output_ipsec_lookup(struct mbuf *m, int *error, 
> struct inpcb *inp)
>       tdb = ipsp_spd_lookup(m, AF_INET6, sizeof(struct ip6_hdr),
>           error, IPSP_DIRECTION_OUT, NULL, inp, 0);
>  
> -     if (tdb != NULL) {
> -             /* Loop detection */
> -             for (mtag = m_tag_first(m); mtag != NULL;
> -                 mtag = m_tag_next(m, mtag)) {
> -                     if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE)
> -                             continue;
> -                     tdbi = (struct tdb_ident *)(mtag + 1);
> -                     if (tdbi->spi == tdb->tdb_spi &&
> -                         tdbi->proto == tdb->tdb_sproto &&
> -                         tdbi->rdomain == tdb->tdb_rdomain &&
> -                         !bcmp(&tdbi->dst, &tdb->tdb_dst,
> -                         sizeof(union sockaddr_union)))
> -                             tdb = NULL;
> +     if (tdb == NULL)
> +             return NULL;
> +     /* Loop detection */
> +     for (mtag = m_tag_first(m); mtag != NULL; mtag = m_tag_next(m, mtag)) {
> +             if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE)
> +                     continue;
> +             tdbi = (struct tdb_ident *)(mtag + 1);
> +             if (tdbi->spi == tdb->tdb_spi &&
> +                 tdbi->proto == tdb->tdb_sproto &&
> +                 tdbi->rdomain == tdb->tdb_rdomain &&
> +                 !memcmp(&tdbi->dst, &tdb->tdb_dst,
> +                 sizeof(union sockaddr_union))) {
> +                     /* no IPsec needed */
> +                     return NULL;
>               }
> -             /* We need to do IPsec */
>       }
>       return tdb;
>  }
> 
> 
> -- 
> I'm not entirely sure you are real.
> 

Reply via email to