Re: [PATCH rdma-next 1/2] RDMA/cma: Consider net namespace while leaving multicast group

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jun 21, 2018 at 09:37:44AM -0600, Jason Gunthorpe wrote:
> On Thu, Jun 21, 2018 at 03:31:24PM +0300, Leon Romanovsky wrote:
> > From: Parav Pandit <parav@xxxxxxxxxxxx>
> >
> > When sending multicast leave request, consider the net ns in which this
> > cm_id is created.
> >
> > Code was duplicated in cma_leave_mc_groups() and rdma_leave_multicast(),
> > which is now done using a helper function cma_leave_roce_mc_group().
> >
> > Fixes: bee3c3c91865 ("IB/cma: Join and leave multicast groups with IGMP")
> > Reviewed-by: Daniel Jurgens <danielj@xxxxxxxxxxxx>
> > Signed-off-by: Parav Pandit <parav@xxxxxxxxxxxx>
> > Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx>
> > ---
> >  drivers/infiniband/core/cma.c | 57 ++++++++++++++++++-------------------------
> >  1 file changed, 24 insertions(+), 33 deletions(-)
>
> There is nothing wrong with this patch.. But looking at this I see
> a bug.. What do you think about the below?

I think that you are right.

>
> From 8e1ec13aeae2105468481fbc5ff01461e91b58b7 Mon Sep 17 00:00:00 2001
> From: Jason Gunthorpe <jgg@xxxxxxxxxxxx>
> Date: Thu, 21 Jun 2018 09:02:30 -0600
> Subject: [PATCH] IB/cm: Remove cma_multicast->igmp_joined
>
> This variable isn't read and written to with proper locking, so it is
> racy. Instead of using an unlocked bool use presence in the mc->list ie
> the caller could race rdma_join_multicast with rdma_leave_multicast which
> would leak a mc join and cause a use after free of mc.
>
> Instead, do not add the mc to the list until it has completed
> initialization, all mcs on the list require leaving.
>
> Signed-off-by: Jason Gunthorpe <jgg@xxxxxxxxxxxx>
> ---
>  drivers/infiniband/core/cma.c | 53 +++++++++++++++--------------------
>  1 file changed, 23 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
> index fca2854749e59a..543254fe23610a 100644
> --- a/drivers/infiniband/core/cma.c
> +++ b/drivers/infiniband/core/cma.c
> @@ -366,7 +366,6 @@ struct cma_multicast {
>  	void			*context;
>  	struct sockaddr_storage	addr;
>  	struct kref		mcref;
> -	bool			igmp_joined;
>  	u8			join_state;
>  };
>
> @@ -1632,21 +1631,14 @@ static void cma_release_port(struct rdma_id_private *id_priv)
>  static void cma_leave_roce_mc_group(struct rdma_id_private *id_priv,
>  				    struct cma_multicast *mc)
>  {
> -	if (mc->igmp_joined) {
> -		struct rdma_dev_addr *dev_addr =
> -			&id_priv->id.route.addr.dev_addr;
> -		struct net_device *ndev = NULL;
> -
> -		if (dev_addr->bound_dev_if)
> -			ndev = dev_get_by_index(dev_addr->net,
> -						dev_addr->bound_dev_if);
> -		if (ndev) {
> -			cma_igmp_send(ndev,
> -				      &mc->multicast.ib->rec.mgid,
> -				      false);
> -			dev_put(ndev);
> -		}
> -		mc->igmp_joined = false;
> +	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
> +	struct net_device *ndev = NULL;
> +
> +	if (dev_addr->bound_dev_if)
> +		ndev = dev_get_by_index(dev_addr->net, dev_addr->bound_dev_if);
> +	if (ndev) {
> +		cma_igmp_send(ndev, &mc->multicast.ib->rec.mgid, false);
> +		dev_put(ndev);
>  	}
>  	kref_put(&mc->mcref, release_mc);
>  }
> @@ -4175,8 +4167,6 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv,
>  			if (!send_only) {
>  				err = cma_igmp_send(ndev, &mc->multicast.ib->rec.mgid,
>  						    true);
> -				if (!err)
> -					mc->igmp_joined = true;
>  			}
>  		}
>  	} else {
> @@ -4228,26 +4218,29 @@ int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
>  	memcpy(&mc->addr, addr, rdma_addr_size(addr));
>  	mc->context = context;
>  	mc->id_priv = id_priv;
> -	mc->igmp_joined = false;
>  	mc->join_state = join_state;
> -	spin_lock(&id_priv->lock);
> -	list_add(&mc->list, &id_priv->mc_list);
> -	spin_unlock(&id_priv->lock);
>
>  	if (rdma_protocol_roce(id->device, id->port_num)) {
>  		kref_init(&mc->mcref);
>  		ret = cma_iboe_join_multicast(id_priv, mc);
> -	} else if (rdma_cap_ib_mcast(id->device, id->port_num))
> +		if (ret)
> +			goto out_err;
> +	} else if (rdma_cap_ib_mcast(id->device, id->port_num)) {
>  		ret = cma_join_ib_multicast(id_priv, mc);
> -	else
> +		if (ret)
> +			goto out_err;
> +	} else {
>  		ret = -ENOSYS;
> -
> -	if (ret) {
> -		spin_lock_irq(&id_priv->lock);
> -		list_del(&mc->list);
> -		spin_unlock_irq(&id_priv->lock);
> -		kfree(mc);
> +		goto out_err;
>  	}
> +
> +	spin_lock(&id_priv->lock);
> +	list_add(&mc->list, &id_priv->mc_list);
> +	spin_unlock(&id_priv->lock);
> +
> +	return 0;
> +out_err:
> +	kfree(mc);
>  	return ret;
>  }
>  EXPORT_SYMBOL(rdma_join_multicast);
> --
> 2.17.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux