lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 24 Oct 2019 17:45:33 +0100
From:   John Keeping <john@...anate.com>
To:     linux-usb@...r.kernel.org
Cc:     Felipe Balbi <balbi@...nel.org>,
        Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
        linux-kernel@...r.kernel.org, John Keeping <john@...anate.com>
Subject: [PATCH 1/6] USB: gadget: f_hid: move chardev setup to module init

Lifetime of the objects in the HID gadget is currently tied to the USB
function, which makes it very easy to trigger a use-after-free by
holding a file descriptor on the HID device after deleting the gadget.

As a first step towards fixing this, move the character device
allocation to module initialisation so that we don't have to worry about
when the allocation can be released after closing all of the open
handles on the device.

Signed-off-by: John Keeping <john@...anate.com>
---
 drivers/usb/gadget/function/f_hid.c | 27 +++++++--------------------
 drivers/usb/gadget/function/u_hid.h |  3 ---
 2 files changed, 7 insertions(+), 23 deletions(-)

diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
index f3816a5c861e..e9e45f9eae80 100644
--- a/drivers/usb/gadget/function/f_hid.c
+++ b/drivers/usb/gadget/function/f_hid.c
@@ -1006,11 +1006,7 @@ static void hidg_free_inst(struct usb_function_instance *f)
 	opts = container_of(f, struct f_hid_opts, func_inst);
 
 	mutex_lock(&hidg_ida_lock);
-
 	hidg_put_minor(opts->minor);
-	if (ida_is_empty(&hidg_ida))
-		ghid_cleanup();
-
 	mutex_unlock(&hidg_ida_lock);
 
 	if (opts->report_desc_alloc)
@@ -1023,7 +1019,6 @@ static struct usb_function_instance *hidg_alloc_inst(void)
 {
 	struct f_hid_opts *opts;
 	struct usb_function_instance *ret;
-	int status = 0;
 
 	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
 	if (!opts)
@@ -1034,21 +1029,10 @@ static struct usb_function_instance *hidg_alloc_inst(void)
 
 	mutex_lock(&hidg_ida_lock);
 
-	if (ida_is_empty(&hidg_ida)) {
-		status = ghid_setup(NULL, HIDG_MINORS);
-		if (status)  {
-			ret = ERR_PTR(status);
-			kfree(opts);
-			goto unlock;
-		}
-	}
-
 	opts->minor = hidg_get_minor();
 	if (opts->minor < 0) {
 		ret = ERR_PTR(opts->minor);
 		kfree(opts);
-		if (ida_is_empty(&hidg_ida))
-			ghid_cleanup();
 		goto unlock;
 	}
 	config_group_init_type_name(&opts->func_inst.group, "", &hid_func_type);
@@ -1133,7 +1117,7 @@ DECLARE_USB_FUNCTION_INIT(hid, hidg_alloc_inst, hidg_alloc);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Fabien Chouteau");
 
-int ghid_setup(struct usb_gadget *g, int count)
+static int ghid_setup(void)
 {
 	int status;
 	dev_t dev;
@@ -1145,7 +1129,7 @@ int ghid_setup(struct usb_gadget *g, int count)
 		return status;
 	}
 
-	status = alloc_chrdev_region(&dev, 0, count, "hidg");
+	status = alloc_chrdev_region(&dev, 0, HIDG_MINORS, "hidg");
 	if (status) {
 		class_destroy(hidg_class);
 		hidg_class = NULL;
@@ -1153,12 +1137,12 @@ int ghid_setup(struct usb_gadget *g, int count)
 	}
 
 	major = MAJOR(dev);
-	minors = count;
+	minors = HIDG_MINORS;
 
 	return 0;
 }
 
-void ghid_cleanup(void)
+static void ghid_cleanup(void)
 {
 	if (major) {
 		unregister_chrdev_region(MKDEV(major, 0), minors);
@@ -1168,3 +1152,6 @@ void ghid_cleanup(void)
 	class_destroy(hidg_class);
 	hidg_class = NULL;
 }
+
+module_init(ghid_setup);
+module_exit(ghid_cleanup);
diff --git a/drivers/usb/gadget/function/u_hid.h b/drivers/usb/gadget/function/u_hid.h
index 1594bfa312eb..d52acc977c7e 100644
--- a/drivers/usb/gadget/function/u_hid.h
+++ b/drivers/usb/gadget/function/u_hid.h
@@ -33,7 +33,4 @@ struct f_hid_opts {
 	 int				refcnt;
 };
 
-int ghid_setup(struct usb_gadget *g, int count);
-void ghid_cleanup(void);
-
 #endif /* U_HID_H */
-- 
2.23.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ