Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

staging: dgnc: cleanup properly

dgnc_cleanup_module() was called when the module unloaded to do a total
cleanup and it was also called if pci_register_driver() fails. But
dgnc_cleanup_module() will try dgnc_remove_driver_sysfiles() but the
sysfiles will be created only if pci_register_driver() succeeds.
So if pci_register_driver() fails and we try dgnc_cleanup_module() then we
were getting:

[ 942.001479] BUG: unable to handle kernel NULL pointer dereference at 00000018
[ 942.001482] IP: [<c122c7a8>] sysfs_remove_file_ns+0x8/0x20

with part of the call trace as:

[ 942.001544] Call Trace:
[ 942.001555] [<c149acc6>] driver_remove_file+0x16/0x20
[ 942.001571] [<f864a708>] dgnc_remove_driver_sysfiles+0x18/0x40 [dgnc]
[ 942.001575] [<f8643ac7>] dgnc_cleanup_module+0x47/0x260 [dgnc]
[ 942.001577] [<f86cb000>] ? 0xf86cb000
[ 942.001580] [<f86cb1e6>] dgnc_init_module+0x1e6/0x1000 [dgnc]

Lets have a separate cleanup function which will execute
dgnc_remove_driver_sysfiles() depending on the argument passed to it.

Reported-by: Navy Cheng <navych@126.com>
Signed-off-by: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Sudip Mukherjee and committed by
Greg Kroah-Hartman
18f038e6 b3ca2e08

+13 -8
+13 -8
drivers/staging/dgnc/dgnc_driver.c
··· 125 125 * 126 126 ************************************************************************/ 127 127 128 - /* 129 - * dgnc_cleanup_module() 130 - * 131 - * Module unload. This is where it all ends. 132 - */ 133 - static void dgnc_cleanup_module(void) 128 + static void cleanup(bool sysfiles) 134 129 { 135 130 int i; 136 131 unsigned long flags; ··· 137 142 /* Turn off poller right away. */ 138 143 del_timer_sync(&dgnc_poll_timer); 139 144 140 - dgnc_remove_driver_sysfiles(&dgnc_driver); 145 + if (sysfiles) 146 + dgnc_remove_driver_sysfiles(&dgnc_driver); 141 147 142 148 device_destroy(dgnc_class, MKDEV(dgnc_Major, 0)); 143 149 class_destroy(dgnc_class); ··· 151 155 } 152 156 153 157 dgnc_tty_post_uninit(); 158 + } 154 159 160 + /* 161 + * dgnc_cleanup_module() 162 + * 163 + * Module unload. This is where it all ends. 164 + */ 165 + static void dgnc_cleanup_module(void) 166 + { 167 + cleanup(true); 155 168 pci_unregister_driver(&dgnc_driver); 156 169 } 157 170 ··· 187 182 rc = pci_register_driver(&dgnc_driver); 188 183 if (rc) { 189 184 pr_warn("WARNING: dgnc driver load failed. No Digi Neo or Classic boards found.\n"); 190 - dgnc_cleanup_module(); 185 + cleanup(false); 191 186 return rc; 192 187 } 193 188 dgnc_create_driver_sysfiles(&dgnc_driver);