Skip to content

Commit 33efa29

Browse files
houlz0507bjorn-helgaas
authored andcommitted
PCI: of_property: Handle interrupt parsing failures
of_pci_prop_intr_map() uses uninitialized addr_sz[] values if of_irq_parse_raw() fails, which leads to intermittent crashes. Clear addr_sz[] before use so we never use uninitialized elements. If no valid IRQs are parsed, don't bother adding the interrupt-map property. Fixes: 407d1a5 ("PCI: Create device tree node for bridge") Link: https://lore.kernel.org/r/1696007448-42127-1-git-send-email-lizhi.hou@amd.com Reported-by: Jonathan Cameron <Jonathan.Cameron@Huawei.com> Closes: https://lore.kernel.org/all/20230911154856.000076c3@Huawei.com/ Reported-by: Herve Codina <herve.codina@bootlin.com> Closes: https://lore.kernel.org/all/20230911171319.495bb837@bootlin.com/ Signed-off-by: Lizhi Hou <lizhi.hou@amd.com> [bhelgaas: commit log, add similar report from Herve] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Herve Codina <herve.codina@bootlin.com>
1 parent 6a878a5 commit 33efa29

File tree

1 file changed

+18
-7
lines changed

1 file changed

+18
-7
lines changed

drivers/pci/of_property.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ static int of_pci_prop_interrupts(struct pci_dev *pdev,
186186
static int of_pci_prop_intr_map(struct pci_dev *pdev, struct of_changeset *ocs,
187187
struct device_node *np)
188188
{
189+
u32 i, addr_sz[OF_PCI_MAX_INT_PIN] = { 0 }, map_sz = 0;
189190
struct of_phandle_args out_irq[OF_PCI_MAX_INT_PIN];
190-
u32 i, addr_sz[OF_PCI_MAX_INT_PIN], map_sz = 0;
191191
__be32 laddr[OF_PCI_ADDRESS_CELLS] = { 0 };
192192
u32 int_map_mask[] = { 0xffff00, 0, 0, 7 };
193193
struct device_node *pnode;
@@ -213,33 +213,44 @@ static int of_pci_prop_intr_map(struct pci_dev *pdev, struct of_changeset *ocs,
213213
out_irq[i].args[0] = pin;
214214
ret = of_irq_parse_raw(laddr, &out_irq[i]);
215215
if (ret) {
216-
pci_err(pdev, "parse irq %d failed, ret %d", pin, ret);
216+
out_irq[i].np = NULL;
217+
pci_dbg(pdev, "parse irq %d failed, ret %d", pin, ret);
217218
continue;
218219
}
219-
ret = of_property_read_u32(out_irq[i].np, "#address-cells",
220-
&addr_sz[i]);
221-
if (ret)
222-
addr_sz[i] = 0;
220+
of_property_read_u32(out_irq[i].np, "#address-cells",
221+
&addr_sz[i]);
223222
}
224223

225224
list_for_each_entry(child, &pdev->subordinate->devices, bus_list) {
226225
for (pin = 1; pin <= OF_PCI_MAX_INT_PIN; pin++) {
227226
i = pci_swizzle_interrupt_pin(child, pin) - 1;
227+
if (!out_irq[i].np)
228+
continue;
228229
map_sz += 5 + addr_sz[i] + out_irq[i].args_count;
229230
}
230231
}
231232

233+
/*
234+
* Parsing interrupt failed for all pins. In this case, it does not
235+
* need to generate interrupt-map property.
236+
*/
237+
if (!map_sz)
238+
return 0;
239+
232240
int_map = kcalloc(map_sz, sizeof(u32), GFP_KERNEL);
233241
mapp = int_map;
234242

235243
list_for_each_entry(child, &pdev->subordinate->devices, bus_list) {
236244
for (pin = 1; pin <= OF_PCI_MAX_INT_PIN; pin++) {
245+
i = pci_swizzle_interrupt_pin(child, pin) - 1;
246+
if (!out_irq[i].np)
247+
continue;
248+
237249
*mapp = (child->bus->number << 16) |
238250
(child->devfn << 8);
239251
mapp += OF_PCI_ADDRESS_CELLS;
240252
*mapp = pin;
241253
mapp++;
242-
i = pci_swizzle_interrupt_pin(child, pin) - 1;
243254
*mapp = out_irq[i].np->phandle;
244255
mapp++;
245256
if (addr_sz[i]) {

0 commit comments

Comments
 (0)