Reported by Dave Miller:
In drivers/infiniband/core/addr.c:
neigh = dst->neighbour;
if (!neigh || !(neigh->nud_state & NUD_VALID)) {
neigh_event_send(dst->neighbour, NULL);
ret = -ENODATA;
goto put;
}
neigh_event_send() can be passed a NULL pointer, and it will
OOPS when this happens.
Avoid passing in a NULL neighbour pointer to neigh_event_send().
Add checks when resolving both ipv4 and ipv6 addresses.
Signed-off-by: Sean Hefty <[email protected]>
---
I added a check to addr4_resolve() as well, but tried to keep the same overall
logic. There may be a cleaner way of handling this, but we should at least
avoid an OOPS in neigh_event_send().
drivers/infiniband/core/addr.c | 29 +++++++++++++++++------------
1 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 8e21d45..29e8571 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -214,17 +214,18 @@ static int addr4_resolve(struct sockaddr_in *src_in,
}
neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
- if (!neigh || !(neigh->nud_state & NUD_VALID)) {
+ if (neigh && (neigh->nud_state & NUD_VALID)) {
+ ret = rdma_copy_addr(addr, neigh->dev, neigh->ha);
+ } else if (rt->dst.neighbour) {
neigh_event_send(rt->dst.neighbour, NULL);
ret = -ENODATA;
- if (neigh)
- goto release;
- goto put;
+ } else {
+ ret = -EHOSTUNREACH;
}
- ret = rdma_copy_addr(addr, neigh->dev, neigh->ha);
-release:
- neigh_release(neigh);
+ if (neigh)
+ neigh_release(neigh);
+
put:
ip_rt_put(rt);
out:
@@ -274,13 +275,17 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
}
neigh = dst->neighbour;
- if (!neigh || !(neigh->nud_state & NUD_VALID)) {
- neigh_event_send(dst->neighbour, NULL);
- ret = -ENODATA;
- goto put;
+ if (neigh) {
+ if (neigh->nud_state & NUD_VALID) {
+ ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
+ } else {
+ neigh_event_send(neigh, NULL);
+ ret = -ENODATA;
+ }
+ } else {
+ ret = -EHOSTUNREACH;
}
- ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
put:
dst_release(dst);
return ret;
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html