From: Lee Jones <lee@kernel.org>
To: lee@kernel.org
Cc: linux-kernel@vger.kernel.org, Felipe Balbi <balbi@kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
linux-usb@vger.kernel.org
Subject: [PATCH 1/1] usb: gadget: f_hid: Conduct proper refcounting on shared f_hidg pointer
Date: Mon, 17 Oct 2022 12:27:37 +0100 [thread overview]
Message-ID: <20221017112737.230772-1-lee@kernel.org> (raw)
A pointer to the main HID gadget struct (*f_hidg) is shared with the
character device handing (read() and write(), etc support) on open().
However external references are presently not tracked. This could
easily lead to some unsavoury behaviour if gadget support is disabled
/ disconnected. Keeping track of the refcount ensures that resources
are only freed *after* they are no longer in use.
Cc: Felipe Balbi <balbi@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/usb/gadget/function/f_hid.c | 37 +++++++++++++++++++++--------
1 file changed, 27 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
index ca0a7d9eaa34e..79d4ee8a5647f 100644
--- a/drivers/usb/gadget/function/f_hid.c
+++ b/drivers/usb/gadget/function/f_hid.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/hid.h>
#include <linux/idr.h>
+#include <linux/kref.h>
#include <linux/cdev.h>
#include <linux/mutex.h>
#include <linux/poll.h>
@@ -77,6 +78,8 @@ struct f_hidg {
struct usb_ep *in_ep;
struct usb_ep *out_ep;
+
+ struct kref refcount;
};
static inline struct f_hidg *func_to_hidg(struct usb_function *f)
@@ -273,6 +276,19 @@ static struct usb_gadget_strings *ct_func_strings[] = {
NULL,
};
+static void hidg_free_resources(struct kref *ref)
+{
+ struct f_hidg *hidg = container_of(ref, struct f_hidg, refcount);
+ struct f_hid_opts *opts = container_of(hidg->func.fi, struct f_hid_opts, func_inst);
+
+ mutex_lock(&opts->lock);
+ kfree(hidg->report_desc);
+ kfree(hidg->set_report_buf);
+ kfree(hidg);
+ --opts->refcnt;
+ mutex_unlock(&opts->lock);
+}
+
/*-------------------------------------------------------------------------*/
/* Char Device */
@@ -539,7 +555,13 @@ static __poll_t f_hidg_poll(struct file *file, poll_table *wait)
static int f_hidg_release(struct inode *inode, struct file *fd)
{
+ struct f_hidg *hidg =
+ container_of(inode->i_cdev, struct f_hidg, cdev);
+
fd->private_data = NULL;
+
+ kref_put(&hidg->refcount, hidg_free_resources);
+
return 0;
}
@@ -548,6 +570,8 @@ static int f_hidg_open(struct inode *inode, struct file *fd)
struct f_hidg *hidg =
container_of(inode->i_cdev, struct f_hidg, cdev);
+ kref_get(&hidg->refcount);
+
fd->private_data = hidg;
return 0;
@@ -1239,17 +1263,9 @@ static struct usb_function_instance *hidg_alloc_inst(void)
static void hidg_free(struct usb_function *f)
{
- struct f_hidg *hidg;
- struct f_hid_opts *opts;
+ struct f_hidg *hidg = func_to_hidg(f);
- hidg = func_to_hidg(f);
- opts = container_of(f->fi, struct f_hid_opts, func_inst);
- kfree(hidg->report_desc);
- kfree(hidg->set_report_buf);
- kfree(hidg);
- mutex_lock(&opts->lock);
- --opts->refcnt;
- mutex_unlock(&opts->lock);
+ kref_put(&hidg->refcount, hidg_free_resources);
}
static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
@@ -1271,6 +1287,7 @@ static struct usb_function *hidg_alloc(struct usb_function_instance *fi)
hidg = kzalloc(sizeof(*hidg), GFP_KERNEL);
if (!hidg)
return ERR_PTR(-ENOMEM);
+ kref_init(&hidg->refcount);
opts = container_of(fi, struct f_hid_opts, func_inst);
--
2.38.0.413.g74048e4d9e-goog
next reply other threads:[~2022-10-17 11:28 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-17 11:27 Lee Jones [this message]
2022-10-22 12:52 ` [PATCH 1/1] usb: gadget: f_hid: Conduct proper refcounting on shared f_hidg pointer Greg Kroah-Hartman
2022-10-24 7:17 ` Lee Jones
-- strict thread matches above, loose matches on Subject: below --
2022-11-17 12:08 Lee Jones
2022-11-17 12:50 ` Greg KH
2022-11-17 13:26 ` Lee Jones
2022-11-17 17:38 ` Greg KH
2022-11-17 12:50 ` Greg KH
2022-11-17 13:46 ` Lee Jones
2022-11-17 16:47 ` Alan Stern
2022-11-18 8:54 ` Lee Jones
2022-11-18 15:59 ` Alan Stern
2022-11-18 16:37 ` John Keeping
2022-11-18 21:07 ` Alan Stern
2022-11-20 17:22 ` John Keeping
2022-11-20 20:46 ` Alan Stern
2022-11-21 12:30 ` Lee Jones
2022-11-21 12:38 ` John Keeping
2022-11-21 16:18 ` Alan Stern
2022-11-21 18:54 ` John Keeping
2022-11-21 19:17 ` Alan Stern
2022-11-22 11:52 ` John Keeping
2022-11-22 8:31 ` Lee Jones
2022-11-22 11:55 ` John Keeping
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=20221017112737.230772-1-lee@kernel.org \
--to=lee@kernel.org \
--cc=balbi@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox