Commit baa495d9de2af97310128bfc0e365a813b63d5bb
Committed by
Bjorn Helgaas
1 parent
610929e119
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
x86/PCI: fix memleak with get_current_resources()
In pci_scan_acpi_root(), when pci_use_crs is set, get_current_resources() is used to get pci_root_info, and it will allocate name and resource array. Later if pci_create_root_bus() can not create bus (could be already there...) it will only free bus res list, but the name and res array is not freed. Let get_current_resource() take info pointer instead of using local info. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Showing 1 changed file with 30 additions and 19 deletions Side-by-side Diff
arch/x86/pci/acpi.c
... | ... | @@ -315,49 +315,55 @@ |
315 | 315 | } |
316 | 316 | } |
317 | 317 | |
318 | +static void free_pci_root_info(struct pci_root_info *info) | |
319 | +{ | |
320 | + kfree(info->name); | |
321 | + kfree(info->res); | |
322 | + memset(info, 0, sizeof(struct pci_root_info)); | |
323 | +} | |
324 | + | |
318 | 325 | static void |
319 | -get_current_resources(struct acpi_device *device, int busnum, | |
326 | +get_current_resources(struct pci_root_info *info, | |
327 | + struct acpi_device *device, int busnum, | |
320 | 328 | int domain, struct list_head *resources) |
321 | 329 | { |
322 | - struct pci_root_info info; | |
323 | 330 | size_t size; |
324 | 331 | |
325 | - info.bridge = device; | |
326 | - info.res_num = 0; | |
327 | - info.resources = resources; | |
332 | + info->bridge = device; | |
333 | + info->res_num = 0; | |
334 | + info->resources = resources; | |
328 | 335 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource, |
329 | - &info); | |
330 | - if (!info.res_num) | |
336 | + info); | |
337 | + if (!info->res_num) | |
331 | 338 | return; |
332 | 339 | |
333 | - size = sizeof(*info.res) * info.res_num; | |
334 | - info.res = kmalloc(size, GFP_KERNEL); | |
335 | - if (!info.res) | |
340 | + size = sizeof(*info->res) * info->res_num; | |
341 | + info->res = kmalloc(size, GFP_KERNEL); | |
342 | + if (!info->res) | |
336 | 343 | return; |
337 | 344 | |
338 | - info.name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum); | |
339 | - if (!info.name) | |
345 | + info->name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum); | |
346 | + if (!info->name) | |
340 | 347 | goto name_alloc_fail; |
341 | 348 | |
342 | - info.res_num = 0; | |
349 | + info->res_num = 0; | |
343 | 350 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource, |
344 | - &info); | |
351 | + info); | |
345 | 352 | |
346 | 353 | if (pci_use_crs) { |
347 | - add_resources(&info); | |
354 | + add_resources(info); | |
348 | 355 | |
349 | 356 | return; |
350 | 357 | } |
351 | 358 | |
352 | - kfree(info.name); | |
353 | - | |
354 | 359 | name_alloc_fail: |
355 | - kfree(info.res); | |
360 | + free_pci_root_info(info); | |
356 | 361 | } |
357 | 362 | |
358 | 363 | struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) |
359 | 364 | { |
360 | 365 | struct acpi_device *device = root->device; |
366 | + struct pci_root_info info; | |
361 | 367 | int domain = root->segment; |
362 | 368 | int busnum = root->secondary.start; |
363 | 369 | LIST_HEAD(resources); |
... | ... | @@ -402,6 +408,7 @@ |
402 | 408 | |
403 | 409 | sd->domain = domain; |
404 | 410 | sd->node = node; |
411 | + memset(&info, 0, sizeof(struct pci_root_info)); | |
405 | 412 | /* |
406 | 413 | * Maybe the desired pci bus has been already scanned. In such case |
407 | 414 | * it is unnecessary to scan the pci bus with the given domain,busnum. |
... | ... | @@ -415,7 +422,8 @@ |
415 | 422 | memcpy(bus->sysdata, sd, sizeof(*sd)); |
416 | 423 | kfree(sd); |
417 | 424 | } else { |
418 | - get_current_resources(device, busnum, domain, &resources); | |
425 | + get_current_resources(&info, device, busnum, domain, | |
426 | + &resources); | |
419 | 427 | |
420 | 428 | /* |
421 | 429 | * _CRS with no apertures is normal, so only fall back to |
... | ... | @@ -429,6 +437,9 @@ |
429 | 437 | bus->subordinate = pci_scan_child_bus(bus); |
430 | 438 | else |
431 | 439 | pci_free_resource_list(&resources); |
440 | + | |
441 | + if (!bus && pci_use_crs) | |
442 | + free_pci_root_info(&info); | |
432 | 443 | } |
433 | 444 | |
434 | 445 | /* After the PCI-E bus has been walked and all devices discovered, |