From: Maor Gottlieb <maorg@xxxxxxxxxx> In RoCE we should use cma_iboe_set_mgid and not cma_set_mgid to generate the mgid, otherwise we will try to remove incorrect address. Fixes: b5de0c60cc30 ("RDMA/cma: Fix use after free race in roce multicast join") Signed-off-by: Maor Gottlieb <maorg@xxxxxxxxxx> Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxx> --- drivers/infiniband/core/cma.c | 61 +++++++++++++++++------------------ 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 27a00ce2e101..69c9a12dd14e 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1830,6 +1830,31 @@ static void cma_release_port(struct rdma_id_private *id_priv) mutex_unlock(&lock); } +static void cma_iboe_set_mgid(struct sockaddr *addr, union ib_gid *mgid, + enum ib_gid_type gid_type) +{ + struct sockaddr_in *sin = (struct sockaddr_in *)addr; + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; + + if (!cma_any_addr(addr) && addr->sa_family == AF_INET6) { + memcpy(mgid, &sin6->sin6_addr, sizeof(*mgid)); + return; + } + + memset(mgid, 0, sizeof(*mgid)); + if (cma_any_addr(addr)) + return; + + /* AF_INET4 */ + if (gid_type != IB_GID_TYPE_ROCE_UDP_ENCAP) { + mgid->raw[0] = 0xff; + mgid->raw[1] = 0x0e; + } + mgid->raw[10] = 0xff; + mgid->raw[11] = 0xff; + *(__be32 *)(&mgid->raw[12]) = sin->sin_addr.s_addr; +} + static void destroy_mc(struct rdma_id_private *id_priv, struct cma_multicast *mc) { @@ -1847,10 +1872,13 @@ static void destroy_mc(struct rdma_id_private *id_priv, ndev = dev_get_by_index(dev_addr->net, dev_addr->bound_dev_if); if (ndev) { + enum ib_gid_type gid_type; union ib_gid mgid; - cma_set_mgid(id_priv, (struct sockaddr *)&mc->addr, - &mgid); + gid_type = cma_get_default_gid_type( + id_priv->cma_dev, id_priv->id.port_num); + cma_iboe_set_mgid((struct sockaddr *)&mc->addr, &mgid, + gid_type); if (!send_only) cma_igmp_send(ndev, &mgid, false); @@ -4702,35 +4730,6 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv, return PTR_ERR_OR_ZERO(mc->sa_mc); } -static void cma_iboe_set_mgid(struct sockaddr *addr, union ib_gid *mgid, - enum ib_gid_type gid_type) -{ - struct sockaddr_in *sin = (struct sockaddr_in *)addr; - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; - - if (cma_any_addr(addr)) { - memset(mgid, 0, sizeof *mgid); - } else if (addr->sa_family == AF_INET6) { - memcpy(mgid, &sin6->sin6_addr, sizeof *mgid); - } else { - mgid->raw[0] = - (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) ? 0 : 0xff; - mgid->raw[1] = - (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) ? 0 : 0x0e; - mgid->raw[2] = 0; - mgid->raw[3] = 0; - mgid->raw[4] = 0; - mgid->raw[5] = 0; - mgid->raw[6] = 0; - mgid->raw[7] = 0; - mgid->raw[8] = 0; - mgid->raw[9] = 0; - mgid->raw[10] = 0xff; - mgid->raw[11] = 0xff; - *(__be32 *)(&mgid->raw[12]) = sin->sin_addr.s_addr; - } -} - static int cma_iboe_join_multicast(struct rdma_id_private *id_priv, struct cma_multicast *mc) { -- 2.34.1