All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yonghua Zheng <younghua.zheng@gmail.com>
To: Jiri Kosina <jkosina@suse.cz>
Cc: linux-input@vger.kernel.org
Subject: Re: [PATCH 1/1] HID: hidraw: Add spinlock in struct hidraw to protect list
Date: Mon, 26 Aug 2013 23:38:35 +0800	[thread overview]
Message-ID: <20130826153833.GA2962@gmail.com> (raw)
In-Reply-To: <alpine.LNX.2.00.1308261359440.2077@pobox.suse.cz>

Hi Jiri,

Fix the conflict and update the patch:

>From 7c06e1f3a5959e73a5b827bda67e7c1eaed7da67 Mon Sep 17 00:00:00 2001
From: Yonghua Zheng <younghua.zheng@gmail.com>
Date: Wed, 14 Aug 2013 17:43:36 +0800
Subject: [PATCH 1/1] HID: hidraw: Add spinlock in struct hidraw to protect
 member list

It is unsafe to call list_for_each_entry in hidraw_report_event to
traverse each hidraw_list node without a lock protection, the list
could be modified if someone calls hidraw_release and list_del to
remove itself from the list, this can cause hidraw_report_event
to touch a deleted list struct and panic.

To prevent this, introduce a spinlock in struct hidraw to protect
list from concurrent access.

Signed-off-by: Yonghua Zheng <younghua.zheng@gmail.com>

diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index dbfe300..8918dd1 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -253,6 +253,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
 	unsigned int minor = iminor(inode);
 	struct hidraw *dev;
 	struct hidraw_list *list;
+	unsigned long flags;
 	int err = 0;
 
 	if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) {
@@ -266,11 +267,6 @@ static int hidraw_open(struct inode *inode, struct file *file)
 		goto out_unlock;
 	}
 
-	list->hidraw = hidraw_table[minor];
-	mutex_init(&list->read_mutex);
-	list_add_tail(&list->node, &hidraw_table[minor]->list);
-	file->private_data = list;
-
 	dev = hidraw_table[minor];
 	if (!dev->open++) {
 		err = hid_hw_power(dev->hid, PM_HINT_FULLON);
@@ -283,9 +279,16 @@ static int hidraw_open(struct inode *inode, struct file *file)
 		if (err < 0) {
 			hid_hw_power(dev->hid, PM_HINT_NORMAL);
 			dev->open--;
+			goto out_unlock;
 		}
 	}
 
+	list->hidraw = hidraw_table[minor];
+	mutex_init(&list->read_mutex);
+	spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
+	list_add_tail(&list->node, &hidraw_table[minor]->list);
+	spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
+	file->private_data = list;
 out_unlock:
 	mutex_unlock(&minors_lock);
 out:
@@ -324,10 +327,13 @@ static int hidraw_release(struct inode * inode, struct file * file)
 {
 	unsigned int minor = iminor(inode);
 	struct hidraw_list *list = file->private_data;
+	unsigned long flags;
 
 	mutex_lock(&minors_lock);
 
+	spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
 	list_del(&list->node);
+	spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
 	kfree(list);
 
 	drop_ref(hidraw_table[minor], 0);
@@ -456,7 +462,9 @@ int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
 	struct hidraw *dev = hid->hidraw;
 	struct hidraw_list *list;
 	int ret = 0;
+	unsigned long flags;
 
+	spin_lock_irqsave(&dev->list_lock, flags);
 	list_for_each_entry(list, &dev->list, node) {
 		int new_head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
 
@@ -471,6 +479,7 @@ int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
 		list->head = new_head;
 		kill_fasync(&list->fasync, SIGIO, POLL_IN);
 	}
+	spin_unlock_irqrestore(&dev->list_lock, flags);
 
 	wake_up_interruptible(&dev->wait);
 	return ret;
@@ -518,6 +527,7 @@ int hidraw_connect(struct hid_device *hid)
 	}
 
 	init_waitqueue_head(&dev->wait);
+	spin_lock_init(&dev->list_lock);
 	INIT_LIST_HEAD(&dev->list);
 
 	dev->hid = hid;
diff --git a/include/linux/hidraw.h b/include/linux/hidraw.h
index 2451662..ddf5261 100644
--- a/include/linux/hidraw.h
+++ b/include/linux/hidraw.h
@@ -23,6 +23,7 @@ struct hidraw {
 	wait_queue_head_t wait;
 	struct hid_device *hid;
 	struct device *dev;
+	spinlock_t list_lock;
 	struct list_head list;
 };
 
-- 
1.7.9.5

Thanks
Yonghua

On Mon, Aug 26, 2013 at 02:03:18PM +0200, Jiri Kosina wrote:
> On Thu, 15 Aug 2013, Yonghua Zheng wrote:
> 
> > As hidraw_report_event can be called from interrupt context, it is a mistake
> > to use mutex_lock for protecting the list member in my previous patch, so
> > update the patch which adds a spinlock in struct hidraw to protect the list
> > member from concurrent access:
> 
> Hi,
> 
> thanks for the patch.
> 
> I already have
> 
> 	commit 212a871a3934beccf43431608c27ed2e05a476ec
> 	Author: Manoj Chourasia <mchourasia@nvidia.com>
> 	Date:   Mon Jul 22 15:33:13 2013 +0530
> 
> 	    HID: hidraw: correctly deallocate memory on device disconnect
> 
> in the tree, which collides with your patch. Could you please check what 
> changes are needed on top of it so that it makes sense for my 'for-next' 
> branch, rebase, and resend to me?
> 
> Thanks,
> 
> -- 
> Jiri Kosina
> SUSE Labs

On Mon, Aug 26, 2013 at 02:03:18PM +0200, Jiri Kosina wrote:
> On Thu, 15 Aug 2013, Yonghua Zheng wrote:
> 
> > As hidraw_report_event can be called from interrupt context, it is a mistake
> > to use mutex_lock for protecting the list member in my previous patch, so
> > update the patch which adds a spinlock in struct hidraw to protect the list
> > member from concurrent access:
> 
> Hi,
> 
> thanks for the patch.
> 
> I already have
> 
> 	commit 212a871a3934beccf43431608c27ed2e05a476ec
> 	Author: Manoj Chourasia <mchourasia@nvidia.com>
> 	Date:   Mon Jul 22 15:33:13 2013 +0530
> 
> 	    HID: hidraw: correctly deallocate memory on device disconnect
> 
> in the tree, which collides with your patch. Could you please check what 
> changes are needed on top of it so that it makes sense for my 'for-next' 
> branch, rebase, and resend to me?
> 
> Thanks,
> 
> -- 
> Jiri Kosina
> SUSE Labs

  reply	other threads:[~2013-08-26 15:38 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-09  8:45 [PATCH 1/1] HID: hidraw: need to grab minors_lock in hidraw_report_event yonghua zheng
2013-08-15 14:57 ` [PATCH 1/1] HID: hidraw: Add spinlock in struct hidraw to protect list Yonghua Zheng
2013-08-26 12:03   ` Jiri Kosina
2013-08-26 15:38     ` Yonghua Zheng [this message]
2013-08-26 19:44       ` Jiri Kosina

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=20130826153833.GA2962@gmail.com \
    --to=younghua.zheng@gmail.com \
    --cc=jkosina@suse.cz \
    --cc=linux-input@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.