Skip to content

Commit e550dfb

Browse files
nhormandavem330
authored andcommitted
ipv6: Fix OOPS in ip6_dst_lookup_tail().
This fixes kernel bugzilla 11469: "TUN with 1024 neighbours: ip6_dst_lookup_tail NULL crash" dst->neighbour is not necessarily hooked up at this point in the processing path, so blindly dereferencing it is the wrong thing to do. This NULL check exists in other similar paths and this case was just an oversight. Also fix the completely wrong and confusing indentation here while we're at it. Based upon a patch by Evgeniy Polyakov. Signed-off-by: Neil Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 225f400 commit e550dfb

File tree

1 file changed

+32
-32
lines changed

1 file changed

+32
-32
lines changed

net/ipv6/ip6_output.c

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -943,39 +943,39 @@ static int ip6_dst_lookup_tail(struct sock *sk,
943943
}
944944

945945
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
946-
/*
947-
* Here if the dst entry we've looked up
948-
* has a neighbour entry that is in the INCOMPLETE
949-
* state and the src address from the flow is
950-
* marked as OPTIMISTIC, we release the found
951-
* dst entry and replace it instead with the
952-
* dst entry of the nexthop router
953-
*/
954-
if (!((*dst)->neighbour->nud_state & NUD_VALID)) {
955-
struct inet6_ifaddr *ifp;
956-
struct flowi fl_gw;
957-
int redirect;
958-
959-
ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
960-
(*dst)->dev, 1);
961-
962-
redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
963-
if (ifp)
964-
in6_ifa_put(ifp);
965-
966-
if (redirect) {
967-
/*
968-
* We need to get the dst entry for the
969-
* default router instead
970-
*/
971-
dst_release(*dst);
972-
memcpy(&fl_gw, fl, sizeof(struct flowi));
973-
memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
974-
*dst = ip6_route_output(net, sk, &fl_gw);
975-
if ((err = (*dst)->error))
976-
goto out_err_release;
977-
}
946+
/*
947+
* Here if the dst entry we've looked up
948+
* has a neighbour entry that is in the INCOMPLETE
949+
* state and the src address from the flow is
950+
* marked as OPTIMISTIC, we release the found
951+
* dst entry and replace it instead with the
952+
* dst entry of the nexthop router
953+
*/
954+
if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) {
955+
struct inet6_ifaddr *ifp;
956+
struct flowi fl_gw;
957+
int redirect;
958+
959+
ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
960+
(*dst)->dev, 1);
961+
962+
redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
963+
if (ifp)
964+
in6_ifa_put(ifp);
965+
966+
if (redirect) {
967+
/*
968+
* We need to get the dst entry for the
969+
* default router instead
970+
*/
971+
dst_release(*dst);
972+
memcpy(&fl_gw, fl, sizeof(struct flowi));
973+
memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
974+
*dst = ip6_route_output(net, sk, &fl_gw);
975+
if ((err = (*dst)->error))
976+
goto out_err_release;
978977
}
978+
}
979979
#endif
980980

981981
return 0;

0 commit comments

Comments
 (0)