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]
Message-Id: <20211103174521.1426407-13-mcgrof@kernel.org>
Date:   Wed,  3 Nov 2021 10:45:20 -0700
From:   Luis Chamberlain <mcgrof@...nel.org>
To:     axboe@...nel.dk, hch@....de, penguin-kernel@...ove.sakura.ne.jp,
        dan.j.williams@...el.com, vishal.l.verma@...el.com,
        dave.jiang@...el.com, ira.weiny@...el.com, richard@....at,
        miquel.raynal@...tlin.com, vigneshr@...com, efremov@...ux.com,
        song@...nel.org, martin.petersen@...cle.com, hare@...e.de,
        jack@...e.cz, ming.lei@...hat.com, tj@...nel.org, mcgrof@...nel.org
Cc:     linux-mtd@...ts.infradead.org, linux-scsi@...r.kernel.org,
        linux-raid@...r.kernel.org, linux-block@...r.kernel.org,
        linux-kernel@...r.kernel.org
Subject: [PATCH v3 12/13] block: fix __register_blkdev() probe add_disk() failures

__register_blkdev() is used to register a probe callback, and
that callback is typically used to call add_disk(). Now that
we are able to capture errors for add_disk(), we need to fix
those probe calls where add_disk() fails and clean up resources.

We don't extend the probe call to return the error given:

1) we'd have to always special-case the case where the disk
   was already present, as otherwise concurrent requests to
   open an existing block device would fail, and this would be
   a userspace visible change
2) the error from ilookup() on blkdev_get_no_open() is sufficient
3) The only thing the probe call is used for is to support
   pre-devtmpfs, pre-udev semantics that want to create disks when
   their pre-created device node is accessed, and so we don't care
   for failures on probe there.

We expand documentation for the probe callback to ensure users
cleanup resources if add_disk() is used and to clarify this interface
may be removed in the future.

This fixes the ataflop and floppy driver uses of the probe call,
which lacked proper error handling for the add_disk() calls.

Cc: Tetsuo Handa <penguin-kernel@...ove.sakura.ne.jp>
Signed-off-by: Luis Chamberlain <mcgrof@...nel.org>
---
 block/genhd.c           |  5 ++++-
 drivers/block/ataflop.c | 12 +++++++++---
 drivers/block/floppy.c  | 11 +++++++++--
 3 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/block/genhd.c b/block/genhd.c
index 4ed87f25276a..8837a89242a2 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -213,7 +213,10 @@ void blkdev_show(struct seq_file *seqf, off_t offset)
  * @major: the requested major device number [1..BLKDEV_MAJOR_MAX-1]. If
  *         @major = 0, try to allocate any unused major number.
  * @name: the name of the new block device as a zero terminated string
- * @probe: allback that is called on access to any minor number of @major
+ * @probe: pre-devtmpfs / pre-udev callback used to create disks when their
+ *	   their pre-created device node is accessed. When a probe call
+ *	   uses add_disk() and it fails the driver must cleanup resources.
+ *	   This interface may soon be removed.
  *
  * The @name must be unique within the system.
  *
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 170dd193cef6..cce6615fe10a 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -2012,6 +2012,7 @@ static void ataflop_probe(dev_t dev)
 {
 	int drive = MINOR(dev) & 3;
 	int type  = MINOR(dev) >> 2;
+	int err = 0;
 
 	if (type)
 		type--;
@@ -2019,9 +2020,14 @@ static void ataflop_probe(dev_t dev)
 	if (drive >= FD_MAX_UNITS || type >= NUM_DISK_MINORS)
 		return;
 	if (!unit[drive].disk[type]) {
-		if (ataflop_alloc_disk(drive, type) == 0) {
-			add_disk(unit[drive].disk[type]);
-			unit[drive].registered[type] = true;
+		err = ataflop_alloc_disk(drive, type);
+		if (err == 0) {
+			err = add_disk(unit[drive].disk[type]);
+			if (err) {
+				blk_cleanup_disk(unit[drive].disk[type]);
+				unit[drive].disk[type] = NULL;
+			} else
+				unit[drive].registered[type] = true;
 		}
 	}
 }
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 3873e789478e..cebc11b74b1a 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4522,6 +4522,7 @@ static void floppy_probe(dev_t dev)
 {
 	unsigned int drive = (MINOR(dev) & 3) | ((MINOR(dev) & 0x80) >> 5);
 	unsigned int type = (MINOR(dev) >> 2) & 0x1f;
+	int err = 0;
 
 	if (drive >= N_DRIVE || !floppy_available(drive) ||
 	    type >= ARRAY_SIZE(floppy_type))
@@ -4529,8 +4530,14 @@ static void floppy_probe(dev_t dev)
 
 	mutex_lock(&floppy_probe_lock);
 	if (!disks[drive][type]) {
-		if (floppy_alloc_disk(drive, type) == 0)
-			add_disk(disks[drive][type]);
+		err = floppy_alloc_disk(drive, type);
+		if (err == 0) {
+			err = add_disk(disks[drive][type]);
+			if (err) {
+				blk_cleanup_disk(disks[drive][type]);
+				disks[drive][type] = NULL;
+			}
+		}
 	}
 	mutex_unlock(&floppy_probe_lock);
 }
-- 
2.33.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ