Re: BUG ip_dst_cache (Not tainted): Poison overwritten

Tommi Rantala <[email protected]>
Newsgroups org.kernel.vger.trinity,org.kernel.vger.linux-kernel,org.kernel.vger.netdev
Message-ID <CA+ydwtpmFbhkck9z8G7tfHQZW+4rWSepQMgPURqVCwrZ77v2bA@mail.gmail.com>
2014-01-31 Eric Dumazet <[email protected]>:
> On Fri, 2014-01-31 at 22:11 +0200, Tommi Rantala wrote:
>> Hello,
>>
>> Hit this while fuzzing v3.13-9218-g0e47c96 with trinity in a qemu
>> virtual machine.
>>
>> Tommi
>
> Hi Tommi
>
> Could you please try the following fix ?

Thanks, giving this a spin. This does not reproduce very easily with
Trinity, I'll let you know if anything blows up.

Tommi

> I'll send an official patch in a couple of hours
>
> There are two bugs :
> One dst leak, and one plain bug, as rt initial NULL
> value might be scratched.
>
>  net/ipv4/ip_tunnel.c |   27 ++++++++++-----------------
>  1 file changed, 10 insertions(+), 17 deletions(-)
>
> diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
> index bd28f386bd02..bc6acdcb7625 100644
> --- a/net/ipv4/ip_tunnel.c
> +++ b/net/ipv4/ip_tunnel.c
> @@ -101,27 +101,21 @@ static void tunnel_dst_reset_all(struct ip_tunnel *t)
>                 __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL);
>  }
>
> -static struct dst_entry *tunnel_dst_get(struct ip_tunnel *t)
> +static struct dst_entry *tunnel_dst_check(struct ip_tunnel *t, u32 cookie)
>  {
>         struct dst_entry *dst;
>
>         rcu_read_lock();
>         dst = rcu_dereference(this_cpu_ptr(t->dst_cache)->dst);
> -       if (dst)
> +       if (dst) {
> +               if (dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
> +                       rcu_read_unlock();
> +                       tunnel_dst_reset(t);
> +                       return NULL;
> +               }
>                 dst_hold(dst);
> -       rcu_read_unlock();
> -       return dst;
> -}
> -
> -static struct dst_entry *tunnel_dst_check(struct ip_tunnel *t, u32 cookie)
> -{
> -       struct dst_entry *dst = tunnel_dst_get(t);
> -
> -       if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
> -               tunnel_dst_reset(t);
> -               return NULL;
>         }
> -
> +       rcu_read_unlock();
>         return dst;
>  }
>
> @@ -584,7 +578,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
>         struct flowi4 fl4;
>         u8     tos, ttl;
>         __be16 df;
> -       struct rtable *rt = NULL;       /* Route to the other host */
> +       struct rtable *rt;              /* Route to the other host */
>         unsigned int max_headroom;      /* The extra header space needed */
>         __be32 dst;
>         int err;
> @@ -657,8 +651,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
>         init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr,
>                          tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link);
>
> -       if (connected)
> -               rt = (struct rtable *)tunnel_dst_check(tunnel, 0);
> +       rt = (connected) ? (struct rtable *)tunnel_dst_check(tunnel, 0) : NULL;
>
>         if (!rt) {
>                 rt = ip_route_output_key(tunnel->net, &fl4);
>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.