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-next>] [day] [month] [year] [list]
Message-ID: <F17EA9D408D3644C864D33B8F5E1CC526DAC2ACF47@BGMAIL02.nvidia.com>
Date:	Mon, 22 Jul 2013 18:23:15 +0530
From:	Manoj Chourasia <mchourasia@...dia.com>
To:	"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>
CC:	"jkosina@...e.cz" <jkosina@...e.cz>
Subject: [PATCH] hidraw: correctly deallocate memory on device disconnect

Hi Jiri,

This is mail is in regard to your commit for hidaw devices. We were seeing kernel crashes while connect and disconnect a hidraw device and we were hitting 
rb tree corruption in vmalloc and kernel was crashing because of null pointer de-reference.
Later we figure out that was because the hid device disconnect is freeing memory which later got access by hidraw_read and hid_write. 

commit df0cfd6990347c20ae031f3f34137cba274f1972
Author: Jiri Kosina <jkosina@...e.cz>
Date:   Thu Nov 1 11:33:26 2012 +0100

    HID: hidraw: put old deallocation mechanism in place

    This basically reverts commit 4fe9f8e203fda. It causes multiple problems,
    namely:


We found following commit by Ratan Nalumasu was helping in solving our issue
commit 4fe9f8e203fdad1524c04beb390f3c6099781ed9
Author: Ratan Nalumasu <ratan@...gle.com>
Date:   Sat Sep 22 11:46:30 2012 -0700

    HID: hidraw: don't deallocate memory when it is in use

    When a device is unplugged, wait for all processes that have opened the device
    to close before deallocating the device.


But there was a bug in Ratan's that commit which was causing slab memory corruption.  We fixed that bug and now our issue solved. I can give evidence on issue.
The bug that was there in the commit that he was deleting list after words and feeing head of it before.
I am attaching the patch.  


-regards
Manoj


-----------------------------------------------------------------------

diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index a745163..612a655 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -113,7 +113,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
 	__u8 *buf;
 	int ret = 0;
 
-	if (!hidraw_table[minor]) {
+	if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
 		ret = -ENODEV;
 		goto out;
 	}
@@ -261,7 +261,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
 	}
 
 	mutex_lock(&minors_lock);
-	if (!hidraw_table[minor]) {
+	if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
 		err = -ENODEV;
 		goto out_unlock;
 	}
@@ -302,39 +302,38 @@ static int hidraw_fasync(int fd, struct file *file, int on)
 	return fasync_helper(fd, file, on, &list->fasync);
 }
 
+static void drop_ref(struct hidraw *hidraw, int exists_bit)
+{
+	if (exists_bit) {
+		hid_hw_close(hidraw->hid);
+		hidraw->exist = 0;
+		if (hidraw->open)
+			wake_up_interruptible(&hidraw->wait);
+	} else {
+		--hidraw->open;
+	}
+
+	if (!hidraw->open && !hidraw->exist) {
+		device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
+		hidraw_table[hidraw->minor] = NULL;
+		kfree(hidraw);
+	}
+}
+
 static int hidraw_release(struct inode * inode, struct file * file)
 {
 	unsigned int minor = iminor(inode);
-	struct hidraw *dev;
 	struct hidraw_list *list = file->private_data;
-	int ret;
-	int i;
 
 	mutex_lock(&minors_lock);
-	if (!hidraw_table[minor]) {
-		ret = -ENODEV;
-		goto unlock;
-	}
 
 	list_del(&list->node);
-	dev = hidraw_table[minor];
-	if (!--dev->open) {
-		if (list->hidraw->exist) {
-			hid_hw_power(dev->hid, PM_HINT_NORMAL);
-			hid_hw_close(dev->hid);
-		} else {
-			kfree(list->hidraw);
-		}
-	}
-
-	for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i)
-		kfree(list->buffer[i].value);
 	kfree(list);
-	ret = 0;
-unlock:
-	mutex_unlock(&minors_lock);
 
-	return ret;
+	drop_ref(hidraw_table[minor], 0);
+
+	mutex_unlock(&minors_lock);
+	return 0;
 }
 
 static long hidraw_ioctl(struct file *file, unsigned int cmd,
@@ -539,18 +538,9 @@ void hidraw_disconnect(struct hid_device *hid)
 	struct hidraw *hidraw = hid->hidraw;
 
 	mutex_lock(&minors_lock);
-	hidraw->exist = 0;
-
-	device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
 
-	hidraw_table[hidraw->minor] = NULL;
+	drop_ref(hidraw, 1);
 
-	if (hidraw->open) {
-		hid_hw_close(hid);
-		wake_up_interruptible(&hidraw->wait);
-	} else {
-		kfree(hidraw);
-	}
 	mutex_unlock(&minors_lock);
 }
 EXPORT_SYMBOL_GPL(hidraw_disconnect);
--

-Regards
Manoj


View attachment "kernel_crash.txt" of type "text/plain" (895 bytes)

Download attachment "PATCH_HID-hidraw-correctly-deallocate-memory-on-device-dis.patch" of type "application/octet-stream" (3564 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ