Skip to content

Commit 14e23bd

Browse files
committed
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: 036b106 ("IB/uverbs: Enable device removal when there are active user space applications") Link: https://lore.kernel.org/r/1578504126-9400-12-git-send-email-yishaih@mellanox.com Signed-off-by: Yishai Hadas <yishaih@mellanox.com> Reviewed-by: Håkon Bugge <haakon.bugge@oracle.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
1 parent 74f75cd commit 14e23bd

File tree

1 file changed

+14
-18
lines changed

1 file changed

+14
-18
lines changed

drivers/infiniband/core/uverbs_main.c

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,6 @@ void ib_uverbs_release_file(struct kref *ref)
220220
}
221221

222222
static ssize_t ib_uverbs_event_read(struct ib_uverbs_event_queue *ev_queue,
223-
struct ib_uverbs_file *uverbs_file,
224223
struct file *filp, char __user *buf,
225224
size_t count, loff_t *pos,
226225
size_t eventsz)
@@ -238,19 +237,16 @@ static ssize_t ib_uverbs_event_read(struct ib_uverbs_event_queue *ev_queue,
238237

239238
if (wait_event_interruptible(ev_queue->poll_wait,
240239
(!list_empty(&ev_queue->event_list) ||
241-
/* The barriers built into wait_event_interruptible()
242-
* and wake_up() guarentee this will see the null set
243-
* without using RCU
244-
*/
245-
!uverbs_file->device->ib_dev)))
240+
ev_queue->is_closed)))
246241
return -ERESTARTSYS;
247242

243+
spin_lock_irq(&ev_queue->lock);
244+
248245
/* If device was disassociated and no event exists set an error */
249-
if (list_empty(&ev_queue->event_list) &&
250-
!uverbs_file->device->ib_dev)
246+
if (list_empty(&ev_queue->event_list) && ev_queue->is_closed) {
247+
spin_unlock_irq(&ev_queue->lock);
251248
return -EIO;
252-
253-
spin_lock_irq(&ev_queue->lock);
249+
}
254250
}
255251

256252
event = list_entry(ev_queue->event_list.next, struct ib_uverbs_event, list);
@@ -285,8 +281,7 @@ static ssize_t ib_uverbs_async_event_read(struct file *filp, char __user *buf,
285281
{
286282
struct ib_uverbs_async_event_file *file = filp->private_data;
287283

288-
return ib_uverbs_event_read(&file->ev_queue, file->uverbs_file, filp,
289-
buf, count, pos,
284+
return ib_uverbs_event_read(&file->ev_queue, filp, buf, count, pos,
290285
sizeof(struct ib_uverbs_async_event_desc));
291286
}
292287

@@ -296,9 +291,8 @@ static ssize_t ib_uverbs_comp_event_read(struct file *filp, char __user *buf,
296291
struct ib_uverbs_completion_event_file *comp_ev_file =
297292
filp->private_data;
298293

299-
return ib_uverbs_event_read(&comp_ev_file->ev_queue,
300-
comp_ev_file->uobj.ufile, filp,
301-
buf, count, pos,
294+
return ib_uverbs_event_read(&comp_ev_file->ev_queue, filp, buf, count,
295+
pos,
302296
sizeof(struct ib_uverbs_comp_event_desc));
303297
}
304298

@@ -321,7 +315,9 @@ static __poll_t ib_uverbs_event_poll(struct ib_uverbs_event_queue *ev_queue,
321315
static __poll_t ib_uverbs_async_event_poll(struct file *filp,
322316
struct poll_table_struct *wait)
323317
{
324-
return ib_uverbs_event_poll(filp->private_data, filp, wait);
318+
struct ib_uverbs_async_event_file *file = filp->private_data;
319+
320+
return ib_uverbs_event_poll(&file->ev_queue, filp, wait);
325321
}
326322

327323
static __poll_t ib_uverbs_comp_event_poll(struct file *filp,
@@ -335,9 +331,9 @@ static __poll_t ib_uverbs_comp_event_poll(struct file *filp,
335331

336332
static int ib_uverbs_async_event_fasync(int fd, struct file *filp, int on)
337333
{
338-
struct ib_uverbs_event_queue *ev_queue = filp->private_data;
334+
struct ib_uverbs_async_event_file *file = filp->private_data;
339335

340-
return fasync_helper(fd, filp, on, &ev_queue->async_queue);
336+
return fasync_helper(fd, filp, on, &file->ev_queue.async_queue);
341337
}
342338

343339
static int ib_uverbs_comp_event_fasync(int fd, struct file *filp, int on)

0 commit comments

Comments
 (0)