Message ID | 5f42b5e97e3b57d3d21fcb436f4e47d044661280.1546431888.git.sbrivio@redhat.com |
---|---|
State | Accepted |
Delegated to: | David Miller |
Headers | show |
Series | [net] ipv6: route: Fix return value of ip6_neigh_lookup() on neigh_create() error | expand |
On 1/2/19 5:29 AM, Stefano Brivio wrote: > In ip6_neigh_lookup(), we must not return errors coming from > neigh_create(): if creation of a neighbour entry fails, the lookup should > return NULL, in the same way as it's done in __neigh_lookup(). > > Otherwise, callers legitimately checking for a non-NULL return value of > the lookup function might dereference an invalid pointer. > > For instance, on neighbour table overflow, ndisc_router_discovery() > crashes ndisc_update() by passing ERR_PTR(-ENOBUFS) as 'neigh' argument. > > Reported-by: Jianlin Shi <jishi@redhat.com> > Fixes: f8a1b43b709d ("net/ipv6: Create a neigh_lookup for FIB entries") > Signed-off-by: Stefano Brivio <sbrivio@redhat.com> > --- > net/ipv6/route.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/net/ipv6/route.c b/net/ipv6/route.c > index a94e0b02a8ac..40b225f87d5e 100644 > --- a/net/ipv6/route.c > +++ b/net/ipv6/route.c > @@ -210,7 +210,9 @@ struct neighbour *ip6_neigh_lookup(const struct in6_addr *gw, > n = __ipv6_neigh_lookup(dev, daddr); > if (n) > return n; > - return neigh_create(&nd_tbl, daddr, dev); > + > + n = neigh_create(&nd_tbl, daddr, dev); > + return IS_ERR(n) ? NULL : n; > } > > static struct neighbour *ip6_dst_neigh_lookup(const struct dst_entry *dst, > I see now -- dst_neigh_lookup handles that check and I forgot to add the same to the new ip6_neigh_lookup. Thanks for the patch. Reviewed-by: David Ahern <dsahern@gmail.com>
From: Stefano Brivio <sbrivio@redhat.com> Date: Wed, 2 Jan 2019 13:29:27 +0100 > In ip6_neigh_lookup(), we must not return errors coming from > neigh_create(): if creation of a neighbour entry fails, the lookup should > return NULL, in the same way as it's done in __neigh_lookup(). > > Otherwise, callers legitimately checking for a non-NULL return value of > the lookup function might dereference an invalid pointer. > > For instance, on neighbour table overflow, ndisc_router_discovery() > crashes ndisc_update() by passing ERR_PTR(-ENOBUFS) as 'neigh' argument. > > Reported-by: Jianlin Shi <jishi@redhat.com> > Fixes: f8a1b43b709d ("net/ipv6: Create a neigh_lookup for FIB entries") > Signed-off-by: Stefano Brivio <sbrivio@redhat.com> Applied and queued up for -stable, thank you.
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index a94e0b02a8ac..40b225f87d5e 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -210,7 +210,9 @@ struct neighbour *ip6_neigh_lookup(const struct in6_addr *gw, n = __ipv6_neigh_lookup(dev, daddr); if (n) return n; - return neigh_create(&nd_tbl, daddr, dev); + + n = neigh_create(&nd_tbl, daddr, dev); + return IS_ERR(n) ? NULL : n; } static struct neighbour *ip6_dst_neigh_lookup(const struct dst_entry *dst,
In ip6_neigh_lookup(), we must not return errors coming from neigh_create(): if creation of a neighbour entry fails, the lookup should return NULL, in the same way as it's done in __neigh_lookup(). Otherwise, callers legitimately checking for a non-NULL return value of the lookup function might dereference an invalid pointer. For instance, on neighbour table overflow, ndisc_router_discovery() crashes ndisc_update() by passing ERR_PTR(-ENOBUFS) as 'neigh' argument. Reported-by: Jianlin Shi <jishi@redhat.com> Fixes: f8a1b43b709d ("net/ipv6: Create a neigh_lookup for FIB entries") Signed-off-by: Stefano Brivio <sbrivio@redhat.com> --- net/ipv6/route.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)