diff options
author | Alexey Khoroshilov <khoroshilov@ispras.ru> | 2014-07-10 18:43:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-11 16:34:48 -0400 |
commit | 19eeb2f9e750f47c805f66e3b0e889b12557d80f (patch) | |
tree | 5b571dc3639692a8476fedbda56388f7bf699b1b /drivers/net/wan | |
parent | f6864c6f3513ab44d4472a7a28b902468675d7a7 (diff) |
farsync: fix invalid memory accesses in fst_add_one() and fst_init_card()
There are several issues in fst_add_one() and fst_init_card():
- invalid pointer dereference at card->ports[card->nports - 1] if
register_hdlc_device() fails for the first port in fst_init_card();
- fst_card_array overflow at fst_card_array[no_of_cards_added]
because there is no checks for array overflow;
- use after free because pointer to deallocated card is left in fst_card_array
if something fails after fst_card_array[no_of_cards_added] = card;
- several leaks on failure paths in fst_add_one().
The patch fixes all the issues and makes code more readable.
Found by Linux Driver Verification project (linuxtesting.org).
Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wan')
-rw-r--r-- | drivers/net/wan/farsync.c | 112 |
1 files changed, 58 insertions, 54 deletions
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index 93ace042d0aa..1f041271f7fe 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c | |||
@@ -2363,7 +2363,7 @@ static char *type_strings[] = { | |||
2363 | "FarSync TE1" | 2363 | "FarSync TE1" |
2364 | }; | 2364 | }; |
2365 | 2365 | ||
2366 | static void | 2366 | static int |
2367 | fst_init_card(struct fst_card_info *card) | 2367 | fst_init_card(struct fst_card_info *card) |
2368 | { | 2368 | { |
2369 | int i; | 2369 | int i; |
@@ -2374,24 +2374,21 @@ fst_init_card(struct fst_card_info *card) | |||
2374 | * we'll have to revise it in some way then. | 2374 | * we'll have to revise it in some way then. |
2375 | */ | 2375 | */ |
2376 | for (i = 0; i < card->nports; i++) { | 2376 | for (i = 0; i < card->nports; i++) { |
2377 | err = register_hdlc_device(card->ports[i].dev); | 2377 | err = register_hdlc_device(card->ports[i].dev); |
2378 | if (err < 0) { | 2378 | if (err < 0) { |
2379 | int j; | ||
2380 | pr_err("Cannot register HDLC device for port %d (errno %d)\n", | 2379 | pr_err("Cannot register HDLC device for port %d (errno %d)\n", |
2381 | i, -err); | 2380 | i, -err); |
2382 | for (j = i; j < card->nports; j++) { | 2381 | while (i--) |
2383 | free_netdev(card->ports[j].dev); | 2382 | unregister_hdlc_device(card->ports[i].dev); |
2384 | card->ports[j].dev = NULL; | 2383 | return err; |
2385 | } | 2384 | } |
2386 | card->nports = i; | ||
2387 | break; | ||
2388 | } | ||
2389 | } | 2385 | } |
2390 | 2386 | ||
2391 | pr_info("%s-%s: %s IRQ%d, %d ports\n", | 2387 | pr_info("%s-%s: %s IRQ%d, %d ports\n", |
2392 | port_to_dev(&card->ports[0])->name, | 2388 | port_to_dev(&card->ports[0])->name, |
2393 | port_to_dev(&card->ports[card->nports - 1])->name, | 2389 | port_to_dev(&card->ports[card->nports - 1])->name, |
2394 | type_strings[card->type], card->irq, card->nports); | 2390 | type_strings[card->type], card->irq, card->nports); |
2391 | return 0; | ||
2395 | } | 2392 | } |
2396 | 2393 | ||
2397 | static const struct net_device_ops fst_ops = { | 2394 | static const struct net_device_ops fst_ops = { |
@@ -2447,15 +2444,12 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2447 | /* Try to enable the device */ | 2444 | /* Try to enable the device */ |
2448 | if ((err = pci_enable_device(pdev)) != 0) { | 2445 | if ((err = pci_enable_device(pdev)) != 0) { |
2449 | pr_err("Failed to enable card. Err %d\n", -err); | 2446 | pr_err("Failed to enable card. Err %d\n", -err); |
2450 | kfree(card); | 2447 | goto enable_fail; |
2451 | return err; | ||
2452 | } | 2448 | } |
2453 | 2449 | ||
2454 | if ((err = pci_request_regions(pdev, "FarSync")) !=0) { | 2450 | if ((err = pci_request_regions(pdev, "FarSync")) !=0) { |
2455 | pr_err("Failed to allocate regions. Err %d\n", -err); | 2451 | pr_err("Failed to allocate regions. Err %d\n", -err); |
2456 | pci_disable_device(pdev); | 2452 | goto regions_fail; |
2457 | kfree(card); | ||
2458 | return err; | ||
2459 | } | 2453 | } |
2460 | 2454 | ||
2461 | /* Get virtual addresses of memory regions */ | 2455 | /* Get virtual addresses of memory regions */ |
@@ -2464,30 +2458,21 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2464 | card->phys_ctlmem = pci_resource_start(pdev, 3); | 2458 | card->phys_ctlmem = pci_resource_start(pdev, 3); |
2465 | if ((card->mem = ioremap(card->phys_mem, FST_MEMSIZE)) == NULL) { | 2459 | if ((card->mem = ioremap(card->phys_mem, FST_MEMSIZE)) == NULL) { |
2466 | pr_err("Physical memory remap failed\n"); | 2460 | pr_err("Physical memory remap failed\n"); |
2467 | pci_release_regions(pdev); | 2461 | err = -ENODEV; |
2468 | pci_disable_device(pdev); | 2462 | goto ioremap_physmem_fail; |
2469 | kfree(card); | ||
2470 | return -ENODEV; | ||
2471 | } | 2463 | } |
2472 | if ((card->ctlmem = ioremap(card->phys_ctlmem, 0x10)) == NULL) { | 2464 | if ((card->ctlmem = ioremap(card->phys_ctlmem, 0x10)) == NULL) { |
2473 | pr_err("Control memory remap failed\n"); | 2465 | pr_err("Control memory remap failed\n"); |
2474 | pci_release_regions(pdev); | 2466 | err = -ENODEV; |
2475 | pci_disable_device(pdev); | 2467 | goto ioremap_ctlmem_fail; |
2476 | iounmap(card->mem); | ||
2477 | kfree(card); | ||
2478 | return -ENODEV; | ||
2479 | } | 2468 | } |
2480 | dbg(DBG_PCI, "kernel mem %p, ctlmem %p\n", card->mem, card->ctlmem); | 2469 | dbg(DBG_PCI, "kernel mem %p, ctlmem %p\n", card->mem, card->ctlmem); |
2481 | 2470 | ||
2482 | /* Register the interrupt handler */ | 2471 | /* Register the interrupt handler */ |
2483 | if (request_irq(pdev->irq, fst_intr, IRQF_SHARED, FST_DEV_NAME, card)) { | 2472 | if (request_irq(pdev->irq, fst_intr, IRQF_SHARED, FST_DEV_NAME, card)) { |
2484 | pr_err("Unable to register interrupt %d\n", card->irq); | 2473 | pr_err("Unable to register interrupt %d\n", card->irq); |
2485 | pci_release_regions(pdev); | 2474 | err = -ENODEV; |
2486 | pci_disable_device(pdev); | 2475 | goto irq_fail; |
2487 | iounmap(card->ctlmem); | ||
2488 | iounmap(card->mem); | ||
2489 | kfree(card); | ||
2490 | return -ENODEV; | ||
2491 | } | 2476 | } |
2492 | 2477 | ||
2493 | /* Record info we need */ | 2478 | /* Record info we need */ |
@@ -2513,13 +2498,8 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2513 | while (i--) | 2498 | while (i--) |
2514 | free_netdev(card->ports[i].dev); | 2499 | free_netdev(card->ports[i].dev); |
2515 | pr_err("FarSync: out of memory\n"); | 2500 | pr_err("FarSync: out of memory\n"); |
2516 | free_irq(card->irq, card); | 2501 | err = -ENOMEM; |
2517 | pci_release_regions(pdev); | 2502 | goto hdlcdev_fail; |
2518 | pci_disable_device(pdev); | ||
2519 | iounmap(card->ctlmem); | ||
2520 | iounmap(card->mem); | ||
2521 | kfree(card); | ||
2522 | return -ENODEV; | ||
2523 | } | 2503 | } |
2524 | card->ports[i].dev = dev; | 2504 | card->ports[i].dev = dev; |
2525 | card->ports[i].card = card; | 2505 | card->ports[i].card = card; |
@@ -2565,9 +2545,16 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2565 | pci_set_drvdata(pdev, card); | 2545 | pci_set_drvdata(pdev, card); |
2566 | 2546 | ||
2567 | /* Remainder of card setup */ | 2547 | /* Remainder of card setup */ |
2548 | if (no_of_cards_added >= FST_MAX_CARDS) { | ||
2549 | pr_err("FarSync: too many cards\n"); | ||
2550 | err = -ENOMEM; | ||
2551 | goto card_array_fail; | ||
2552 | } | ||
2568 | fst_card_array[no_of_cards_added] = card; | 2553 | fst_card_array[no_of_cards_added] = card; |
2569 | card->card_no = no_of_cards_added++; /* Record instance and bump it */ | 2554 | card->card_no = no_of_cards_added++; /* Record instance and bump it */ |
2570 | fst_init_card(card); | 2555 | err = fst_init_card(card); |
2556 | if (err) | ||
2557 | goto init_card_fail; | ||
2571 | if (card->family == FST_FAMILY_TXU) { | 2558 | if (card->family == FST_FAMILY_TXU) { |
2572 | /* | 2559 | /* |
2573 | * Allocate a dma buffer for transmit and receives | 2560 | * Allocate a dma buffer for transmit and receives |
@@ -2577,29 +2564,46 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2577 | &card->rx_dma_handle_card); | 2564 | &card->rx_dma_handle_card); |
2578 | if (card->rx_dma_handle_host == NULL) { | 2565 | if (card->rx_dma_handle_host == NULL) { |
2579 | pr_err("Could not allocate rx dma buffer\n"); | 2566 | pr_err("Could not allocate rx dma buffer\n"); |
2580 | fst_disable_intr(card); | 2567 | err = -ENOMEM; |
2581 | pci_release_regions(pdev); | 2568 | goto rx_dma_fail; |
2582 | pci_disable_device(pdev); | ||
2583 | iounmap(card->ctlmem); | ||
2584 | iounmap(card->mem); | ||
2585 | kfree(card); | ||
2586 | return -ENOMEM; | ||
2587 | } | 2569 | } |
2588 | card->tx_dma_handle_host = | 2570 | card->tx_dma_handle_host = |
2589 | pci_alloc_consistent(card->device, FST_MAX_MTU, | 2571 | pci_alloc_consistent(card->device, FST_MAX_MTU, |
2590 | &card->tx_dma_handle_card); | 2572 | &card->tx_dma_handle_card); |
2591 | if (card->tx_dma_handle_host == NULL) { | 2573 | if (card->tx_dma_handle_host == NULL) { |
2592 | pr_err("Could not allocate tx dma buffer\n"); | 2574 | pr_err("Could not allocate tx dma buffer\n"); |
2593 | fst_disable_intr(card); | 2575 | err = -ENOMEM; |
2594 | pci_release_regions(pdev); | 2576 | goto tx_dma_fail; |
2595 | pci_disable_device(pdev); | ||
2596 | iounmap(card->ctlmem); | ||
2597 | iounmap(card->mem); | ||
2598 | kfree(card); | ||
2599 | return -ENOMEM; | ||
2600 | } | 2577 | } |
2601 | } | 2578 | } |
2602 | return 0; /* Success */ | 2579 | return 0; /* Success */ |
2580 | |||
2581 | tx_dma_fail: | ||
2582 | pci_free_consistent(card->device, FST_MAX_MTU, | ||
2583 | card->rx_dma_handle_host, | ||
2584 | card->rx_dma_handle_card); | ||
2585 | rx_dma_fail: | ||
2586 | fst_disable_intr(card); | ||
2587 | for (i = 0 ; i < card->nports ; i++) | ||
2588 | unregister_hdlc_device(card->ports[i].dev); | ||
2589 | init_card_fail: | ||
2590 | fst_card_array[card->card_no] = NULL; | ||
2591 | card_array_fail: | ||
2592 | for (i = 0 ; i < card->nports ; i++) | ||
2593 | free_netdev(card->ports[i].dev); | ||
2594 | hdlcdev_fail: | ||
2595 | free_irq(card->irq, card); | ||
2596 | irq_fail: | ||
2597 | iounmap(card->ctlmem); | ||
2598 | ioremap_ctlmem_fail: | ||
2599 | iounmap(card->mem); | ||
2600 | ioremap_physmem_fail: | ||
2601 | pci_release_regions(pdev); | ||
2602 | regions_fail: | ||
2603 | pci_disable_device(pdev); | ||
2604 | enable_fail: | ||
2605 | kfree(card); | ||
2606 | return err; | ||
2603 | } | 2607 | } |
2604 | 2608 | ||
2605 | /* | 2609 | /* |