diff options
| author | Yinglin Luan <synmyth@gmail.com> | 2011-06-25 14:12:12 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2011-06-29 08:57:35 -0400 |
| commit | 55caa9241ece1c07a930e3d05a624061adcf2653 (patch) | |
| tree | 58747dba1d8c7711f8187216d1e433841bcd91ad /drivers/net | |
| parent | 7ab24bfdf9a9a9f87ac8e5ad9a25f80b5b947be7 (diff) | |
rionet: fix NULL pointer dereference in rionet_remove
Function rionet_remove initializes local variable 'ndev' to NULL
and do nothing changes before the call to unregister_netdev(ndev),
this could cause a NULL pointer dereference.
Reported-by: Jesper Juhl <jj@chaosbits.net>
Signed-off-by: Yinglin Luan <synmyth@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
| -rw-r--r-- | drivers/net/rionet.c | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 77c5092a6a40..5d3436d47edd 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c | |||
| @@ -378,7 +378,7 @@ static int rionet_close(struct net_device *ndev) | |||
| 378 | 378 | ||
| 379 | static void rionet_remove(struct rio_dev *rdev) | 379 | static void rionet_remove(struct rio_dev *rdev) |
| 380 | { | 380 | { |
| 381 | struct net_device *ndev = NULL; | 381 | struct net_device *ndev = rio_get_drvdata(rdev); |
| 382 | struct rionet_peer *peer, *tmp; | 382 | struct rionet_peer *peer, *tmp; |
| 383 | 383 | ||
| 384 | free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ? | 384 | free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ? |
| @@ -433,22 +433,12 @@ static const struct net_device_ops rionet_netdev_ops = { | |||
| 433 | .ndo_set_mac_address = eth_mac_addr, | 433 | .ndo_set_mac_address = eth_mac_addr, |
| 434 | }; | 434 | }; |
| 435 | 435 | ||
| 436 | static int rionet_setup_netdev(struct rio_mport *mport) | 436 | static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev) |
| 437 | { | 437 | { |
| 438 | int rc = 0; | 438 | int rc = 0; |
| 439 | struct net_device *ndev = NULL; | ||
| 440 | struct rionet_private *rnet; | 439 | struct rionet_private *rnet; |
| 441 | u16 device_id; | 440 | u16 device_id; |
| 442 | 441 | ||
| 443 | /* Allocate our net_device structure */ | ||
| 444 | ndev = alloc_etherdev(sizeof(struct rionet_private)); | ||
| 445 | if (ndev == NULL) { | ||
| 446 | printk(KERN_INFO "%s: could not allocate ethernet device.\n", | ||
| 447 | DRV_NAME); | ||
| 448 | rc = -ENOMEM; | ||
| 449 | goto out; | ||
| 450 | } | ||
| 451 | |||
| 452 | rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL, | 442 | rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL, |
| 453 | mport->sys_size ? __fls(sizeof(void *)) + 4 : 0); | 443 | mport->sys_size ? __fls(sizeof(void *)) + 4 : 0); |
| 454 | if (!rionet_active) { | 444 | if (!rionet_active) { |
| @@ -504,11 +494,21 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) | |||
| 504 | int rc = -ENODEV; | 494 | int rc = -ENODEV; |
| 505 | u32 lpef, lsrc_ops, ldst_ops; | 495 | u32 lpef, lsrc_ops, ldst_ops; |
| 506 | struct rionet_peer *peer; | 496 | struct rionet_peer *peer; |
| 497 | struct net_device *ndev = NULL; | ||
| 507 | 498 | ||
| 508 | /* If local device is not rionet capable, give up quickly */ | 499 | /* If local device is not rionet capable, give up quickly */ |
| 509 | if (!rionet_capable) | 500 | if (!rionet_capable) |
| 510 | goto out; | 501 | goto out; |
| 511 | 502 | ||
| 503 | /* Allocate our net_device structure */ | ||
| 504 | ndev = alloc_etherdev(sizeof(struct rionet_private)); | ||
| 505 | if (ndev == NULL) { | ||
| 506 | printk(KERN_INFO "%s: could not allocate ethernet device.\n", | ||
| 507 | DRV_NAME); | ||
| 508 | rc = -ENOMEM; | ||
| 509 | goto out; | ||
| 510 | } | ||
| 511 | |||
| 512 | /* | 512 | /* |
| 513 | * First time through, make sure local device is rionet | 513 | * First time through, make sure local device is rionet |
| 514 | * capable, setup netdev, and set flags so this is skipped | 514 | * capable, setup netdev, and set flags so this is skipped |
| @@ -529,7 +529,7 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) | |||
| 529 | goto out; | 529 | goto out; |
| 530 | } | 530 | } |
| 531 | 531 | ||
| 532 | rc = rionet_setup_netdev(rdev->net->hport); | 532 | rc = rionet_setup_netdev(rdev->net->hport, ndev); |
| 533 | rionet_check = 1; | 533 | rionet_check = 1; |
| 534 | } | 534 | } |
| 535 | 535 | ||
| @@ -546,6 +546,8 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) | |||
| 546 | list_add_tail(&peer->node, &rionet_peers); | 546 | list_add_tail(&peer->node, &rionet_peers); |
| 547 | } | 547 | } |
| 548 | 548 | ||
| 549 | rio_set_drvdata(rdev, ndev); | ||
| 550 | |||
| 549 | out: | 551 | out: |
| 550 | return rc; | 552 | return rc; |
| 551 | } | 553 | } |
