From 90acaa4de6ac63fda8bfa4f605de89ddd7019bda Mon Sep 17 00:00:00 2001 From: =?utf8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Mon, 15 Oct 2012 20:58:20 -0700 Subject: [PATCH] staging:iio:events: Don't copy data to user-space with a locked spinlock. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit iio_event_chrdev_read would return -EFAULT if the user-space page was not resident. Change-Id: I4ac5d3bc791bb503d014d9db576b9d6d522505b2 Signed-off-by: Arve Hjønnevåg --- drivers/iio/industrialio-event.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 10aa9ef86cec..145c98617936 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -35,6 +35,7 @@ */ struct iio_event_interface { wait_queue_head_t wait; + struct mutex read_lock; DECLARE_KFIFO(det_events, struct iio_event_data, 16); struct list_head dev_attr_list; @@ -97,14 +98,16 @@ static ssize_t iio_event_chrdev_read(struct file *filep, if (count < sizeof(struct iio_event_data)) return -EINVAL; - spin_lock_irq(&ev_int->wait.lock); + if (mutex_lock_interruptible(&ev_int->read_lock)) + return -ERESTARTSYS; + if (kfifo_is_empty(&ev_int->det_events)) { if (filep->f_flags & O_NONBLOCK) { ret = -EAGAIN; goto error_unlock; } /* Blocking on device; waiting for something to be there */ - ret = wait_event_interruptible_locked_irq(ev_int->wait, + ret = wait_event_interruptible(ev_int->wait, !kfifo_is_empty(&ev_int->det_events)); if (ret) goto error_unlock; @@ -114,7 +117,7 @@ static ssize_t iio_event_chrdev_read(struct file *filep, ret = kfifo_to_user(&ev_int->det_events, buf, count, &copied); error_unlock: - spin_unlock_irq(&ev_int->wait.lock); + mutex_unlock(&ev_int->read_lock); return ret ? ret : copied; } @@ -371,6 +374,7 @@ static void iio_setup_ev_int(struct iio_event_interface *ev_int) { INIT_KFIFO(ev_int->det_events); init_waitqueue_head(&ev_int->wait); + mutex_init(&ev_int->read_lock); } static const char *iio_event_group_name = "events"; @@ -434,6 +438,7 @@ int iio_device_register_eventset(struct iio_dev *indio_dev) error_free_setup_event_lines: __iio_remove_event_config_attrs(indio_dev); + mutex_destroy(&indio_dev->event_interface->read_lock); kfree(indio_dev->event_interface); error_ret: @@ -446,5 +451,6 @@ void iio_device_unregister_eventset(struct iio_dev *indio_dev) return; __iio_remove_event_config_attrs(indio_dev); kfree(indio_dev->event_interface->group.attrs); + mutex_destroy(&indio_dev->event_interface->read_lock); kfree(indio_dev->event_interface); } -- 2.34.1