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

IB: Remove sysfs files before unregistering device

Move the ib_device_unregister_sysfs() call from ib_dealloc_device() to
ib_unregister_device(). The old code allows device unregister to
proceed even if some sysfs files are open, which leaves a window where
userspace can open a file before a device is removed but then end up
reading the file after the device is removed, which leads to various
kernel crashes either because the device data structure is freed or
because the low-level driver code is gone after module removal.

By not returning from ib_unregister_device() until after all sysfs
entries are removed, we make sure that data structures and/or module
code is not freed until after all sysfs access is done.

Reported-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>

+6 -1
+3 -1
drivers/infiniband/core/device.c
··· 193 193 194 194 BUG_ON(device->reg_state != IB_DEV_UNREGISTERED); 195 195 196 - ib_device_unregister_sysfs(device); 196 + kobject_put(&device->dev.kobj); 197 197 } 198 198 EXPORT_SYMBOL(ib_dealloc_device); 199 199 ··· 347 347 kfree(device->pkey_tbl_len); 348 348 349 349 mutex_unlock(&device_mutex); 350 + 351 + ib_device_unregister_sysfs(device); 350 352 351 353 spin_lock_irqsave(&device->client_data_lock, flags); 352 354 list_for_each_entry_safe(context, tmp, &device->client_data_list, list)
+3
drivers/infiniband/core/sysfs.c
··· 848 848 struct kobject *p, *t; 849 849 struct ib_port *port; 850 850 851 + /* Hold kobject until ib_dealloc_device() */ 852 + kobject_get(&device->dev.kobj); 853 + 851 854 list_for_each_entry_safe(p, t, &device->port_list, entry) { 852 855 list_del(&p->entry); 853 856 port = container_of(p, struct ib_port, kobj);