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>] [day] [month] [year] [list]
Date:	Sat, 24 Oct 2015 02:27:43 +0300
From:	Alexey Khoroshilov <khoroshilov@...ras.ru>
To:	Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
	Jiri Slaby <jslaby@...e.com>
Cc:	Alexey Khoroshilov <khoroshilov@...ras.ru>,
	linux-kernel@...r.kernel.org, ldv-project@...uxtesting.org
Subject: [PATCH] tty: synclinkmp: do not ignore errors in probe()

synclinkmp_init_one() ignores all errors and does not release
all resources if something fails.

The patch adds returned code to device_init() and add_device()
and proper error handling.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Alexey Khoroshilov <khoroshilov@...ras.ru>
---
 drivers/tty/synclinkmp.c | 44 ++++++++++++++++++++++++++++----------------
 1 file changed, 28 insertions(+), 16 deletions(-)

diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
index 08633a8139ff..5b622788d4bf 100644
--- a/drivers/tty/synclinkmp.c
+++ b/drivers/tty/synclinkmp.c
@@ -549,8 +549,8 @@ static int  tiocmset(struct tty_struct *tty,
 			unsigned int set, unsigned int clear);
 static int  set_break(struct tty_struct *tty, int break_state);
 
-static void add_device(SLMP_INFO *info);
-static void device_init(int adapter_num, struct pci_dev *pdev);
+static int  add_device(SLMP_INFO *info);
+static int  device_init(int adapter_num, struct pci_dev *pdev);
 static int  claim_resources(SLMP_INFO *info);
 static void release_resources(SLMP_INFO *info);
 
@@ -3703,7 +3703,7 @@ static void release_resources(SLMP_INFO *info)
 /* Add the specified device instance data structure to the
  * global linked list of devices and increment the device count.
  */
-static void add_device(SLMP_INFO *info)
+static int add_device(SLMP_INFO *info)
 {
 	info->next_device = NULL;
 	info->line = synclinkmp_device_count;
@@ -3741,7 +3741,9 @@ static void add_device(SLMP_INFO *info)
 		info->max_frame_size );
 
 #if SYNCLINK_GENERIC_HDLC
-	hdlcdev_init(info);
+	return hdlcdev_init(info);
+#else
+	return 0;
 #endif
 }
 
@@ -3830,10 +3832,10 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
 	return info;
 }
 
-static void device_init(int adapter_num, struct pci_dev *pdev)
+static int device_init(int adapter_num, struct pci_dev *pdev)
 {
 	SLMP_INFO *port_array[SCA_MAX_PORTS];
-	int port;
+	int port, rc;
 
 	/* allocate device instances for up to SCA_MAX_PORTS devices */
 	for ( port = 0; port < SCA_MAX_PORTS; ++port ) {
@@ -3843,14 +3845,16 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
 				tty_port_destroy(&port_array[port]->port);
 				kfree(port_array[port]);
 			}
-			return;
+			return -ENOMEM;
 		}
 	}
 
 	/* give copy of port_array to all ports and add to device list  */
 	for ( port = 0; port < SCA_MAX_PORTS; ++port ) {
 		memcpy(port_array[port]->port_array,port_array,sizeof(port_array));
-		add_device( port_array[port] );
+		rc = add_device( port_array[port] );
+		if (rc)
+			goto err_add;
 		spin_lock_init(&port_array[port]->lock);
 	}
 
@@ -3870,21 +3874,30 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
 			alloc_dma_bufs(port_array[port]);
 		}
 
-		if ( request_irq(port_array[0]->irq_level,
+		rc = request_irq(port_array[0]->irq_level,
 					synclinkmp_interrupt,
 					port_array[0]->irq_flags,
 					port_array[0]->device_name,
-					port_array[0]) < 0 ) {
+					port_array[0]);
+		if ( rc ) {
 			printk( "%s(%d):%s Can't request interrupt, IRQ=%d\n",
 				__FILE__,__LINE__,
 				port_array[0]->device_name,
 				port_array[0]->irq_level );
+			goto err_irq;
 		}
-		else {
-			port_array[0]->irq_requested = true;
-			adapter_test(port_array[0]);
-		}
+		port_array[0]->irq_requested = true;
+		adapter_test(port_array[0]);
 	}
+	return 0;
+err_irq:
+	release_resources( port_array[0] );
+err_add:
+	for ( port = 0; port < SCA_MAX_PORTS; ++port ) {
+		tty_port_destroy(&port_array[port]->port);
+		kfree(port_array[port]);
+	}
+	return rc;
 }
 
 static const struct tty_operations ops = {
@@ -5599,8 +5612,7 @@ static int synclinkmp_init_one (struct pci_dev *dev,
 		printk("error enabling pci device %p\n", dev);
 		return -EIO;
 	}
-	device_init( ++synclinkmp_adapter_count, dev );
-	return 0;
+	return device_init( ++synclinkmp_adapter_count, dev );
 }
 
 static void synclinkmp_remove_one (struct pci_dev *dev)
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ