Re: [PATCH for-next V2 07/11] IB/core: Validate route in ib_init_ah_from_wc and ib_init_ah_from_path
On Mon, Dec 7, 2015 at 3:42 PM, Haggai Eran wrote: > On 12/03/2015 03:47 PM, Matan Barak wrote: >> +static int addr_resolve_neigh(struct dst_entry *dst, >> + const struct sockaddr *dst_in, >> + struct rdma_dev_addr *addr) >> +{ >> + if (dst->dev->flags & IFF_LOOPBACK) { >> + int ret; >> + >> + ret = rdma_translate_ip(dst_in, addr, NULL); >> + if (!ret) >> + memcpy(addr->dst_dev_addr, addr->src_dev_addr, >> +MAX_ADDR_LEN); >> + >> + return ret; >> + } >> + >> + /* If the device does ARP internally */ > You mean "doesn't do ARP internally" right? > Correct, nice catch :) >> + if (!(dst->dev->flags & IFF_NOARP)) { >> + const struct sockaddr_in *dst_in4 = >> + (const struct sockaddr_in *)dst_in; >> + const struct sockaddr_in6 *dst_in6 = >> + (const struct sockaddr_in6 *)dst_in; >> + >> + return dst_fetch_ha(dst, addr, >> + dst_in->sa_family == AF_INET ? >> + (const void *)&dst_in4->sin_addr.s_addr : >> + (const void *)&dst_in6->sin6_addr); >> + } >> + >> + return rdma_copy_addr(addr, dst->dev, NULL); >> +} > >> +int rdma_resolve_ip_route(struct sockaddr *src_addr, >> + const struct sockaddr *dst_addr, >> + struct rdma_dev_addr *addr) >> +{ >> + struct sockaddr_storage ssrc_addr; >> + struct sockaddr *src_in = (struct sockaddr *)&ssrc_addr; >> + >> + if (src_addr->sa_family != dst_addr->sa_family) >> + return -EINVAL; >> + >> + if (src_addr) >> + memcpy(src_in, src_addr, rdma_addr_size(src_addr)); >> + else >> + src_in->sa_family = dst_addr->sa_family; > Don't you need to clear the rest of src_in? I believe you pass > uninitialized memory to it. > Correct, I'll fix that. >> + >> + return addr_resolve(src_in, dst_addr, addr, false); >> +} >> +EXPORT_SYMBOL(rdma_resolve_ip_route); > > Haggai Thanks for taking a look. Matan > -- > To unsubscribe from this list: send the line "unsubscribe linux-rdma" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH for-next V2 07/11] IB/core: Validate route in ib_init_ah_from_wc and ib_init_ah_from_path
On 12/03/2015 03:47 PM, Matan Barak wrote: > +static int addr_resolve_neigh(struct dst_entry *dst, > + const struct sockaddr *dst_in, > + struct rdma_dev_addr *addr) > +{ > + if (dst->dev->flags & IFF_LOOPBACK) { > + int ret; > + > + ret = rdma_translate_ip(dst_in, addr, NULL); > + if (!ret) > + memcpy(addr->dst_dev_addr, addr->src_dev_addr, > +MAX_ADDR_LEN); > + > + return ret; > + } > + > + /* If the device does ARP internally */ You mean "doesn't do ARP internally" right? > + if (!(dst->dev->flags & IFF_NOARP)) { > + const struct sockaddr_in *dst_in4 = > + (const struct sockaddr_in *)dst_in; > + const struct sockaddr_in6 *dst_in6 = > + (const struct sockaddr_in6 *)dst_in; > + > + return dst_fetch_ha(dst, addr, > + dst_in->sa_family == AF_INET ? > + (const void *)&dst_in4->sin_addr.s_addr : > + (const void *)&dst_in6->sin6_addr); > + } > + > + return rdma_copy_addr(addr, dst->dev, NULL); > +} > +int rdma_resolve_ip_route(struct sockaddr *src_addr, > + const struct sockaddr *dst_addr, > + struct rdma_dev_addr *addr) > +{ > + struct sockaddr_storage ssrc_addr; > + struct sockaddr *src_in = (struct sockaddr *)&ssrc_addr; > + > + if (src_addr->sa_family != dst_addr->sa_family) > + return -EINVAL; > + > + if (src_addr) > + memcpy(src_in, src_addr, rdma_addr_size(src_addr)); > + else > + src_in->sa_family = dst_addr->sa_family; Don't you need to clear the rest of src_in? I believe you pass uninitialized memory to it. > + > + return addr_resolve(src_in, dst_addr, addr, false); > +} > +EXPORT_SYMBOL(rdma_resolve_ip_route); Haggai -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH for-next V2 07/11] IB/core: Validate route in ib_init_ah_from_wc and ib_init_ah_from_path
In order to make sure API users don't try to use SGIDs which don't conform to the routing table, validate the route before searching the RoCE GID table. Signed-off-by: Matan Barak --- drivers/infiniband/core/addr.c | 175 ++- drivers/infiniband/core/cm.c | 10 +- drivers/infiniband/core/cma.c| 30 +- drivers/infiniband/core/sa_query.c | 75 +++-- drivers/infiniband/core/verbs.c | 48 ++--- drivers/infiniband/hw/ocrdma/ocrdma_ah.c | 2 +- include/rdma/ib_addr.h | 10 +- 7 files changed, 270 insertions(+), 80 deletions(-) diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 6e35299..57eda11 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -121,7 +121,8 @@ int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, } EXPORT_SYMBOL(rdma_copy_addr); -int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr, +int rdma_translate_ip(const struct sockaddr *addr, + struct rdma_dev_addr *dev_addr, u16 *vlan_id) { struct net_device *dev; @@ -139,7 +140,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr, switch (addr->sa_family) { case AF_INET: dev = ip_dev_find(dev_addr->net, - ((struct sockaddr_in *) addr)->sin_addr.s_addr); + ((const struct sockaddr_in *)addr)->sin_addr.s_addr); if (!dev) return ret; @@ -154,7 +155,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr, rcu_read_lock(); for_each_netdev_rcu(dev_addr->net, dev) { if (ipv6_chk_addr(dev_addr->net, - &((struct sockaddr_in6 *) addr)->sin6_addr, + &((const struct sockaddr_in6 *)addr)->sin6_addr, dev, 1)) { ret = rdma_copy_addr(dev_addr, dev, NULL); if (vlan_id) @@ -198,7 +199,8 @@ static void queue_req(struct addr_req *req) mutex_unlock(&lock); } -static int dst_fetch_ha(struct dst_entry *dst, struct rdma_dev_addr *dev_addr, void *daddr) +static int dst_fetch_ha(struct dst_entry *dst, struct rdma_dev_addr *dev_addr, + const void *daddr) { struct neighbour *n; int ret; @@ -222,8 +224,9 @@ static int dst_fetch_ha(struct dst_entry *dst, struct rdma_dev_addr *dev_addr, v } static int addr4_resolve(struct sockaddr_in *src_in, -struct sockaddr_in *dst_in, -struct rdma_dev_addr *addr) +const struct sockaddr_in *dst_in, +struct rdma_dev_addr *addr, +struct rtable **prt) { __be32 src_ip = src_in->sin_addr.s_addr; __be32 dst_ip = dst_in->sin_addr.s_addr; @@ -243,36 +246,23 @@ static int addr4_resolve(struct sockaddr_in *src_in, src_in->sin_family = AF_INET; src_in->sin_addr.s_addr = fl4.saddr; - if (rt->dst.dev->flags & IFF_LOOPBACK) { - ret = rdma_translate_ip((struct sockaddr *)dst_in, addr, NULL); - if (!ret) - memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN); - goto put; - } - - /* If the device does ARP internally, return 'done' */ - if (rt->dst.dev->flags & IFF_NOARP) { - ret = rdma_copy_addr(addr, rt->dst.dev, NULL); - goto put; - } - /* If there's a gateway, we're definitely in RoCE v2 (as RoCE v1 isn't * routable) and we could set the network type accordingly. */ if (rt->rt_uses_gateway) addr->network = RDMA_NETWORK_IPV4; - ret = dst_fetch_ha(&rt->dst, addr, &fl4.daddr); -put: - ip_rt_put(rt); + *prt = rt; + return 0; out: return ret; } #if IS_ENABLED(CONFIG_IPV6) static int addr6_resolve(struct sockaddr_in6 *src_in, -struct sockaddr_in6 *dst_in, -struct rdma_dev_addr *addr) +const struct sockaddr_in6 *dst_in, +struct rdma_dev_addr *addr, +struct dst_entry **pdst) { struct flowi6 fl6; struct dst_entry *dst; @@ -299,49 +289,109 @@ static int addr6_resolve(struct sockaddr_in6 *src_in, src_in->sin6_addr = fl6.saddr; } - if (dst->dev->flags & IFF_LOOPBACK) { - ret = rdma_translate_ip((struct sockaddr *)dst_in, addr, NULL); - if (!ret) - memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN); - goto put; - } -
[PATCH for-next V2 07/11] IB/core: Validate route in ib_init_ah_from_wc and ib_init_ah_from_path
In order to make sure API users don't try to use SGIDs which don't conform to the routing table, validate the route before searching the RoCE GID table. Signed-off-by: Matan Barak --- drivers/infiniband/core/addr.c | 175 ++- drivers/infiniband/core/cm.c | 10 +- drivers/infiniband/core/cma.c| 30 +- drivers/infiniband/core/sa_query.c | 75 +++-- drivers/infiniband/core/verbs.c | 48 ++--- drivers/infiniband/hw/ocrdma/ocrdma_ah.c | 2 +- include/rdma/ib_addr.h | 10 +- 7 files changed, 270 insertions(+), 80 deletions(-) diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 6e35299..57eda11 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -121,7 +121,8 @@ int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, } EXPORT_SYMBOL(rdma_copy_addr); -int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr, +int rdma_translate_ip(const struct sockaddr *addr, + struct rdma_dev_addr *dev_addr, u16 *vlan_id) { struct net_device *dev; @@ -139,7 +140,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr, switch (addr->sa_family) { case AF_INET: dev = ip_dev_find(dev_addr->net, - ((struct sockaddr_in *) addr)->sin_addr.s_addr); + ((const struct sockaddr_in *)addr)->sin_addr.s_addr); if (!dev) return ret; @@ -154,7 +155,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr, rcu_read_lock(); for_each_netdev_rcu(dev_addr->net, dev) { if (ipv6_chk_addr(dev_addr->net, - &((struct sockaddr_in6 *) addr)->sin6_addr, + &((const struct sockaddr_in6 *)addr)->sin6_addr, dev, 1)) { ret = rdma_copy_addr(dev_addr, dev, NULL); if (vlan_id) @@ -198,7 +199,8 @@ static void queue_req(struct addr_req *req) mutex_unlock(&lock); } -static int dst_fetch_ha(struct dst_entry *dst, struct rdma_dev_addr *dev_addr, void *daddr) +static int dst_fetch_ha(struct dst_entry *dst, struct rdma_dev_addr *dev_addr, + const void *daddr) { struct neighbour *n; int ret; @@ -222,8 +224,9 @@ static int dst_fetch_ha(struct dst_entry *dst, struct rdma_dev_addr *dev_addr, v } static int addr4_resolve(struct sockaddr_in *src_in, -struct sockaddr_in *dst_in, -struct rdma_dev_addr *addr) +const struct sockaddr_in *dst_in, +struct rdma_dev_addr *addr, +struct rtable **prt) { __be32 src_ip = src_in->sin_addr.s_addr; __be32 dst_ip = dst_in->sin_addr.s_addr; @@ -243,36 +246,23 @@ static int addr4_resolve(struct sockaddr_in *src_in, src_in->sin_family = AF_INET; src_in->sin_addr.s_addr = fl4.saddr; - if (rt->dst.dev->flags & IFF_LOOPBACK) { - ret = rdma_translate_ip((struct sockaddr *)dst_in, addr, NULL); - if (!ret) - memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN); - goto put; - } - - /* If the device does ARP internally, return 'done' */ - if (rt->dst.dev->flags & IFF_NOARP) { - ret = rdma_copy_addr(addr, rt->dst.dev, NULL); - goto put; - } - /* If there's a gateway, we're definitely in RoCE v2 (as RoCE v1 isn't * routable) and we could set the network type accordingly. */ if (rt->rt_uses_gateway) addr->network = RDMA_NETWORK_IPV4; - ret = dst_fetch_ha(&rt->dst, addr, &fl4.daddr); -put: - ip_rt_put(rt); + *prt = rt; + return 0; out: return ret; } #if IS_ENABLED(CONFIG_IPV6) static int addr6_resolve(struct sockaddr_in6 *src_in, -struct sockaddr_in6 *dst_in, -struct rdma_dev_addr *addr) +const struct sockaddr_in6 *dst_in, +struct rdma_dev_addr *addr, +struct dst_entry **pdst) { struct flowi6 fl6; struct dst_entry *dst; @@ -299,49 +289,109 @@ static int addr6_resolve(struct sockaddr_in6 *src_in, src_in->sin6_addr = fl6.saddr; } - if (dst->dev->flags & IFF_LOOPBACK) { - ret = rdma_translate_ip((struct sockaddr *)dst_in, addr, NULL); - if (!ret) - memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN); - goto put; - } -