All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Håkon Bugge" <haakon.bugge@oracle.com>
To: Jason Gunthorpe <jgg@ziepe.ca>, Jason Gunthorpe <jgg@mellanox.com>
Cc: Doug Ledford <dledford@redhat.com>,
	OFED mailing list <linux-rdma@vger.kernel.org>
Subject: Re: [PATCH RDMA/uverbs] RDMA/uverbs: Protect list_empty() by lock
Date: Wed, 8 Jan 2020 15:23:55 +0100	[thread overview]
Message-ID: <EC6982F9-6AED-4EE7-9CF9-AB7564F27E88@oracle.com> (raw)
In-Reply-To: <20200107184238.GA7928@ziepe.ca>



> On 7 Jan 2020, at 19:42, Jason Gunthorpe <jgg@ziepe.ca> wrote:
> 
> On Mon, Jan 06, 2020 at 01:27:11PM +0100, Håkon Bugge wrote:
>> In ib_uverbs_event_read(), events are waited for, then pulled off the
>> kernel's event queue, and finally returned to user space.
>> 
>> There is an explicit check to see if the device is gone, and if so and
>> the there are no events pending, an -EIO is returned.
>> 
>> However, said test does not check for queue empty whilst holding the
>> lock, so there is a race where the existing code perceives the queue
>> to be empty, when it in fact isn't. Fixed by acquiring the lock ahead
>> of the list_empty() test.
>> 
>> Fixes: 036b10635739 ("IB/uverbs: Enable device removal when there are active user space applications")
>> Signed-off-by: Håkon Bugge <haakon.bugge@oracle.com>
>> ---
>> drivers/infiniband/core/uverbs_main.c | 8 +++++---
>> 1 file changed, 5 insertions(+), 3 deletions(-)
>> 
>> diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
>> index 970d8e31dd65..7165e51790ed 100644
>> --- a/drivers/infiniband/core/uverbs_main.c
>> +++ b/drivers/infiniband/core/uverbs_main.c
>> @@ -245,12 +245,14 @@ static ssize_t ib_uverbs_event_read(struct ib_uverbs_event_queue *ev_queue,
>> 					     !uverbs_file->device->ib_dev)))
>> 			return -ERESTARTSYS;
>> 
>> +		spin_lock_irq(&ev_queue->lock);
>> +
>> 		/* If device was disassociated and no event exists set an error */
>> 		if (list_empty(&ev_queue->event_list) &&
>> -		    !uverbs_file->device->ib_dev)
>> +		    !uverbs_file->device->ib_dev) {
>> +			spin_unlock_irq(&ev_queue->lock);
>> 			return -EIO;
> 
> I noticed this too last month. While this patch is an improvement, I
> had written this one which also fixes the wrong use of devce->ib_dev
> without a READ_ONCE or locking. It is just winding its way through
> testing right now.
> 
> What do you think?
> 
> From 37ddee0ea682eaf47e6167a090ae0a4e943f7f68 Mon Sep 17 00:00:00 2001
> From: Jason Gunthorpe <jgg@mellanox.com>
> Date: Tue, 26 Nov 2019 20:58:04 -0400
> Subject: [PATCH] RDMA/core: Fix locking in ib_uverbs_event_read
> 
> This should not be using ib_dev to test for disassociation, during
> disassociation is_closed is set under lock and the waitq is triggered.
> 
> Instead check is_closed and be sure to re-obtain the lock to test the
> value after the wait_event returns.
> 
> Fixes: 036b10635739 ("IB/uverbs: Enable device removal when there are active user space applications")
> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>

LGTM,

Reviewed-by: Håkon Bugge <haakon.bugge@oracle.com>
(or feel free to use my s-o-b, as we coined 80% of this independently of each other).


Thxs, Håkon


> ---
> drivers/infiniband/core/uverbs_main.c | 24 +++++++++---------------
> 1 file changed, 9 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
> index 953a8c3fae64bd..2b7dc94b6a7a69 100644
> --- a/drivers/infiniband/core/uverbs_main.c
> +++ b/drivers/infiniband/core/uverbs_main.c
> @@ -215,7 +215,6 @@ void ib_uverbs_release_file(struct kref *ref)
> }
> 
> static ssize_t ib_uverbs_event_read(struct ib_uverbs_event_queue *ev_queue,
> -				    struct ib_uverbs_file *uverbs_file,
> 				    struct file *filp, char __user *buf,
> 				    size_t count, loff_t *pos,
> 				    size_t eventsz)
> @@ -233,19 +232,16 @@ static ssize_t ib_uverbs_event_read(struct ib_uverbs_event_queue *ev_queue,
> 
> 		if (wait_event_interruptible(ev_queue->poll_wait,
> 					     (!list_empty(&ev_queue->event_list) ||
> -			/* The barriers built into wait_event_interruptible()
> -			 * and wake_up() guarentee this will see the null set
> -			 * without using RCU
> -			 */
> -					     !uverbs_file->device->ib_dev)))
> +					      ev_queue->is_closed)))
> 			return -ERESTARTSYS;
> 
> +		spin_lock_irq(&ev_queue->lock);
> +
> 		/* If device was disassociated and no event exists set an error */
> -		if (list_empty(&ev_queue->event_list) &&
> -		    !uverbs_file->device->ib_dev)
> +		if (list_empty(&ev_queue->event_list) && ev_queue->is_closed) {
> +			spin_unlock_irq(&ev_queue->lock);
> 			return -EIO;
> -
> -		spin_lock_irq(&ev_queue->lock);
> +		}
> 	}
> 
> 	event = list_entry(ev_queue->event_list.next, struct ib_uverbs_event, list);
> @@ -280,8 +276,7 @@ static ssize_t ib_uverbs_async_event_read(struct file *filp, char __user *buf,
> {
> 	struct ib_uverbs_async_event_file *file = filp->private_data;
> 
> -	return ib_uverbs_event_read(&file->ev_queue, file->uverbs_file, filp,
> -				    buf, count, pos,
> +	return ib_uverbs_event_read(&file->ev_queue, filp, buf, count, pos,
> 				    sizeof(struct ib_uverbs_async_event_desc));
> }
> 
> @@ -291,9 +286,8 @@ static ssize_t ib_uverbs_comp_event_read(struct file *filp, char __user *buf,
> 	struct ib_uverbs_completion_event_file *comp_ev_file =
> 		filp->private_data;
> 
> -	return ib_uverbs_event_read(&comp_ev_file->ev_queue,
> -				    comp_ev_file->uobj.ufile, filp,
> -				    buf, count, pos,
> +	return ib_uverbs_event_read(&comp_ev_file->ev_queue, filp, buf, count,
> +				    pos,
> 				    sizeof(struct ib_uverbs_comp_event_desc));
> }
> 
> -- 
> 2.24.1
> 


      reply	other threads:[~2020-01-08 14:25 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-06 12:27 [PATCH RDMA/uverbs] RDMA/uverbs: Protect list_empty() by lock Håkon Bugge
2020-01-07 18:42 ` Jason Gunthorpe
2020-01-08 14:23   ` Håkon Bugge [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=EC6982F9-6AED-4EE7-9CF9-AB7564F27E88@oracle.com \
    --to=haakon.bugge@oracle.com \
    --cc=dledford@redhat.com \
    --cc=jgg@mellanox.com \
    --cc=jgg@ziepe.ca \
    --cc=linux-rdma@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.