[PATCH] staging: unisys: visorbus: fix kernel BUG discovered by day0 testing

David Kershner david.kershner at unisys.com
Thu Mar 30 21:43:17 UTC 2017


Fixes: 5b6f9b95f7ae ("staging: unisys: visorbus: get rid of create_bus_type.")

Kernel day0 testing robot reported a kernel BUG at drivers/base/driver.c!
with the following call stack:

[   14.963563] ------------[ cut here ]------------
[   14.967298] kernel BUG at drivers/base/driver.c:153!
[   14.970948] invalid opcode: 0000 [#1] SMP
[   14.974013] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.11.0-rc4-00790-g0789e2c #1
[   14.978221] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.9.3-20161025_171302-gandalf 04/01/2014
[   14.983417] task: ffff88001ea46040 task.stack: ffffc90000008000
[   14.987315] RIP: 0010:driver_register+0xa1/0xd0
[   14.990044] RSP: 0000:ffffc9000000be60 EFLAGS: 00010246
[   14.993039] RAX: 0000000000000000 RBX: ffffffff831d4c20 RCX: 0000000000000000
[   14.997040] RDX: 000000000000004d RSI: ffffffff831d47c0 RDI: ffffffff831d4c20
[   15.001511] RBP: ffffc9000000be78 R08: ffffc9000000be78 R09: ffffc9000000be7c
[   15.006163] R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000
[   15.010068] R13: 00000000ffffffff R14: ffffffff832f3923 R15: 0000000000000000
[   15.013715] FS:  0000000000000000(0000) GS:ffff88001fa00000(0000) knlGS:0000000000000000
[   15.017460] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   15.021268] CR2: 0000000000000000 CR3: 0000000003009000 CR4: 00000000000006b0
[   15.025633] Call Trace:
[   15.028069]  ? visorbus_register_visor_driver+0x3f/0x60
[   15.031065]  ? init_unisys+0x3a/0x90
[   15.033562]  ? device_resume_response+0x50/0x50
[   15.036083]  visorinput_init+0x10/0x20
[   15.038937]  do_one_initcall+0x9a/0x164
[   15.041838]  ? set_debug_rodata+0x12/0x12
[   15.045333]  kernel_init_freeable+0x11e/0x1a1
[   15.048369]  ? rest_init+0x80/0x80
[   15.050813]  kernel_init+0x9/0x100
[   15.053353]  ret_from_fork+0x2c/0x40
[   15.056009] Code: ff 85 c0 41 89 c4 75 13 48 8b 7b 70 31 f6 e8 97 16 be ff 44 89 e0 5b 41 5c 5d c3 48 89 df e8 57 e1 ff ff 44 89 e0 5b 41 5c 5d c3 <0f> 0b 48 8b 33 48 c7 c7 a0 dd d5 82 e8 ec f0 6f ff 48 8b 73 08
[   15.065144] RIP: driver_register+0xa1/0xd0 RSP: ffffc9000000be60
[   15.068360] ---[ end trace 7d13369c38d80a8f ]---

This bug will occur if the visorbus driver is built-in to the kernel, and
the resulting kernel is run in an environment where visorbus devices are
NOT supported, and an attempt is made to load any of the drivers: visorhba,
visornic, or visorinput.

This reverts commit 5b6f9b95f7ae ("staging: unisys: visorbus: get rid of
create_bus_type.")

Signed-off-by: David Kershner <david.kershner at unisys.com>
Reviewed-by: Tim Sell <timothy.sell at unisys.com>
---
 drivers/staging/unisys/visorbus/visorbus_main.c | 32 ++++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c
index 4348072..9f698ab 100644
--- a/drivers/staging/unisys/visorbus/visorbus_main.c
+++ b/drivers/staging/unisys/visorbus/visorbus_main.c
@@ -29,6 +29,7 @@
 #define CURRENT_FILE_PC VISOR_BUS_PC_visorbus_main_c
 #define POLLJIFFIES_NORMALCHANNEL 10
 
+static int busreg_rc = -ENODEV; /* stores the result from bus registration */
 static struct dentry *visorbus_debugfs_dir;
 
 /*
@@ -959,6 +960,9 @@ static void bus_device_info_init(
  */
 int visorbus_register_visor_driver(struct visor_driver *drv)
 {
+	if (busreg_rc < 0)
+		return -ENODEV; /*can't register on a nonexistent bus*/
+
 	drv->driver.name = drv->name;
 	drv->driver.bus = &visorbus_type;
 	drv->driver.probe = visordriver_probe_device;
@@ -1067,6 +1071,29 @@ int visorbus_register_visor_driver(struct visor_driver *drv)
 }
 
 /*
+ * create_bus_type() - create and register the one-and-only one instance of
+ *                     the visor bus type (visorbus_type)
+ * Return: 0 for success, otherwise negative errno value returned by
+ *         bus_register() indicating the reason for failure
+ */
+static int
+create_bus_type(void)
+{
+	busreg_rc = bus_register(&visorbus_type);
+	return busreg_rc;
+}
+
+/*
+ * remove_bus_type() - remove the one-and-only one instance of the visor bus
+ *                     type (visorbus_type)
+ */
+static void
+remove_bus_type(void)
+{
+	bus_unregister(&visorbus_type);
+}
+
+/*
  * remove_all_visor_devices() - remove all child visor bus device instances
  */
 static void
@@ -1292,7 +1319,7 @@ int visorbus_register_visor_driver(struct visor_driver *drv)
 
 	bus_device_info_init(&clientbus_driverinfo, "clientbus", "visorbus");
 
-	err = bus_register(&visorbus_type);
+	err = create_bus_type();
 	if (err < 0) {
 		POSTCODE_LINUX(BUS_CREATE_ENTRY_PC, 0, 0, DIAG_SEVERITY_ERR);
 		goto error;
@@ -1320,7 +1347,6 @@ int visorbus_register_visor_driver(struct visor_driver *drv)
 						      list_all);
 		remove_bus_instance(dev);
 	}
-
-	bus_unregister(&visorbus_type);
+	remove_bus_type();
 	debugfs_remove_recursive(visorbus_debugfs_dir);
 }
-- 
1.9.1



More information about the devel mailing list