Skip to content

Commit

Permalink
PCI: Fix Oops caused by uninitialized slot->list in pci_slot_release()
Browse files Browse the repository at this point in the history
Once kobject_init_and_add() failed, pci_slot_release() is called to
delete slot->list from parent->slots. But slot->list is intialized
afterwards, so we ran into the following crash:

  Unable to handle kernel NULL pointer dereference at virtual address
00000000
  ...
  CPU: 10 PID: 1 Comm: swapper/0 Not tainted 4.4.240 torvalds#197
  task: ffffeb398a45ef10 task.stack: ffffeb398a470000
  PC is at __list_del_entry_valid+0x5c/0xb0
  LR is at pci_slot_release+0x84/0xe4
  ...
  __list_del_entry_valid+0x5c/0xb0
  pci_slot_release+0x84/0xe4
  kobject_put+0x184/0x1c4
  pci_create_slot+0x17c/0x1b4
  __pci_hp_initialize+0x68/0xa4
  pciehp_probe+0x1a4/0x2fc
  pcie_port_probe_service+0x58/0x84
  driver_probe_device+0x320/0x470
  __driver_attach+0x54/0xb8
  bus_for_each_dev+0xc8/0xf0
  driver_attach+0x30/0x3c
  bus_add_driver+0x1b0/0x24c
  driver_register+0x9c/0xe0
  pcie_port_service_register+0x64/0x7c
  pcied_init+0x44/0xa4
  do_one_initcall+0x1d0/0x1f0
  kernel_init_freeable+0x24c/0x254
  kernel_init+0x18/0xe8
  ret_from_fork+0x10/0x20

Fixes: 8a94644 ("PCI: Fix pci_create_slot() reference count leak")
Signed-off-by: Jubin Zhong <[email protected]>
Cc: [email protected] #v4.4.235

----
v2:
  Since both slot memory and slot->list would be handled by
pci_slot_release(), we need to make sure slot->list is properly
initialized beforehand.

v1: https://lore.kernel.org/lkml/[email protected]/
  Two things need to be cleaned up on pci_create_slot's error path:
  1. free slot memory
  2. remove slot->list from its parent->slots
  This patch mistakenly took slot memory as unfreed (which is not), and
would introduce double free problem.
  • Loading branch information
Jubin Zhong authored and intel-lab-lkp committed Dec 2, 2020
1 parent 46f821a commit 7218efe
Showing 1 changed file with 3 additions and 3 deletions.
6 changes: 3 additions & 3 deletions drivers/pci/slot.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,16 +272,16 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
goto err;
}

INIT_LIST_HEAD(&slot->list);
list_add(&slot->list, &parent->slots);

err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL,
"%s", slot_name);
if (err) {
kobject_put(&slot->kobj);
goto err;
}

INIT_LIST_HEAD(&slot->list);
list_add(&slot->list, &parent->slots);

down_read(&pci_bus_sem);
list_for_each_entry(dev, &parent->devices, bus_list)
if (PCI_SLOT(dev->devfn) == slot_nr)
Expand Down

0 comments on commit 7218efe

Please sign in to comment.