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:   Mon, 4 Jul 2022 15:44:07 +0900
From:   Tetsuo Handa <penguin-kernel@...ove.SAKURA.ne.jp>
To:     arnd@...db.de, gregkh@...uxfoundation.org
Cc:     linux-kernel@...r.kernel.org
Subject: [PATCH] char: misc: make misc_open() and misc_register() killable

syzbot is reporting hung task at misc_open() [1], for snapshot_open() from
misc_open() might sleep for long with misc_mtx held whereas userspace can
flood with concurrent misc_open() requests. Mitigate this problem by making
misc_open() and misc_register() killable.

Link: https://syzkaller.appspot.com/bug?extid=358c9ab4c93da7b7238c [1]
Reported-by: syzbot <syzbot+358c9ab4c93da7b7238c@...kaller.appspotmail.com>
Signed-off-by: Tetsuo Handa <penguin-kernel@...ove.SAKURA.ne.jp>
---
 drivers/char/misc.c | 57 +++++++++++++++++++--------------------------
 1 file changed, 24 insertions(+), 33 deletions(-)

diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index cba19bfdc44d..b9a494bc4228 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -100,49 +100,39 @@ static const struct seq_operations misc_seq_ops = {
 static int misc_open(struct inode *inode, struct file *file)
 {
 	int minor = iminor(inode);
-	struct miscdevice *c = NULL, *iter;
+	struct miscdevice *iter;
 	int err = -ENODEV;
 	const struct file_operations *new_fops = NULL;
+	bool retried = false;
 
-	mutex_lock(&misc_mtx);
-
+ retry:
+	if (mutex_lock_killable(&misc_mtx))
+		return -EINTR;
 	list_for_each_entry(iter, &misc_list, list) {
 		if (iter->minor != minor)
 			continue;
-		c = iter;
 		new_fops = fops_get(iter->fops);
+		if (!new_fops)
+			break;
+		/*
+		 * Place the miscdevice in the file's
+		 * private_data so it can be used by the
+		 * file operations, including f_op->open below
+		 */
+		file->private_data = iter;
+
+		err = 0;
+		replace_fops(file, new_fops);
+		if (file->f_op->open)
+			err = file->f_op->open(inode, file);
 		break;
 	}
-
-	if (!new_fops) {
-		mutex_unlock(&misc_mtx);
+	mutex_unlock(&misc_mtx);
+	if (!new_fops && !retried) {
 		request_module("char-major-%d-%d", MISC_MAJOR, minor);
-		mutex_lock(&misc_mtx);
-
-		list_for_each_entry(iter, &misc_list, list) {
-			if (iter->minor != minor)
-				continue;
-			c = iter;
-			new_fops = fops_get(iter->fops);
-			break;
-		}
-		if (!new_fops)
-			goto fail;
+		retried = true;
+		goto retry;
 	}
-
-	/*
-	 * Place the miscdevice in the file's
-	 * private_data so it can be used by the
-	 * file operations, including f_op->open below
-	 */
-	file->private_data = c;
-
-	err = 0;
-	replace_fops(file, new_fops);
-	if (file->f_op->open)
-		err = file->f_op->open(inode, file);
-fail:
-	mutex_unlock(&misc_mtx);
 	return err;
 }
 
@@ -180,7 +170,8 @@ int misc_register(struct miscdevice *misc)
 
 	INIT_LIST_HEAD(&misc->list);
 
-	mutex_lock(&misc_mtx);
+	if (mutex_lock_killable(&misc_mtx))
+		return -EINTR;
 
 	if (is_dynamic) {
 		int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);
-- 
2.18.4


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ