Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 55caa924 authored by Yinglin Luan's avatar Yinglin Luan Committed by David S. Miller
Browse files

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: default avatarJesper Juhl <jj@chaosbits.net>
Signed-off-by: default avatarYinglin Luan <synmyth@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7ab24bfd
Loading
Loading
Loading
Loading
+15 −13
Original line number Original line Diff line number Diff line
@@ -378,7 +378,7 @@ static int rionet_close(struct net_device *ndev)


static void rionet_remove(struct rio_dev *rdev)
static void rionet_remove(struct rio_dev *rdev)
{
{
	struct net_device *ndev = NULL;
	struct net_device *ndev = rio_get_drvdata(rdev);
	struct rionet_peer *peer, *tmp;
	struct rionet_peer *peer, *tmp;


	free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ?
	free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ?
@@ -433,22 +433,12 @@ static const struct net_device_ops rionet_netdev_ops = {
	.ndo_set_mac_address	= eth_mac_addr,
	.ndo_set_mac_address	= eth_mac_addr,
};
};


static int rionet_setup_netdev(struct rio_mport *mport)
static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
{
{
	int rc = 0;
	int rc = 0;
	struct net_device *ndev = NULL;
	struct rionet_private *rnet;
	struct rionet_private *rnet;
	u16 device_id;
	u16 device_id;


	/* Allocate our net_device structure */
	ndev = alloc_etherdev(sizeof(struct rionet_private));
	if (ndev == NULL) {
		printk(KERN_INFO "%s: could not allocate ethernet device.\n",
		       DRV_NAME);
		rc = -ENOMEM;
		goto out;
	}

	rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL,
	rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL,
			mport->sys_size ? __fls(sizeof(void *)) + 4 : 0);
			mport->sys_size ? __fls(sizeof(void *)) + 4 : 0);
	if (!rionet_active) {
	if (!rionet_active) {
@@ -504,11 +494,21 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
	int rc = -ENODEV;
	int rc = -ENODEV;
	u32 lpef, lsrc_ops, ldst_ops;
	u32 lpef, lsrc_ops, ldst_ops;
	struct rionet_peer *peer;
	struct rionet_peer *peer;
	struct net_device *ndev = NULL;


	/* If local device is not rionet capable, give up quickly */
	/* If local device is not rionet capable, give up quickly */
	if (!rionet_capable)
	if (!rionet_capable)
		goto out;
		goto out;


	/* Allocate our net_device structure */
	ndev = alloc_etherdev(sizeof(struct rionet_private));
	if (ndev == NULL) {
		printk(KERN_INFO "%s: could not allocate ethernet device.\n",
		       DRV_NAME);
		rc = -ENOMEM;
		goto out;
	}

	/*
	/*
	 * First time through, make sure local device is rionet
	 * First time through, make sure local device is rionet
	 * capable, setup netdev,  and set flags so this is skipped
	 * 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)
			goto out;
			goto out;
		}
		}


		rc = rionet_setup_netdev(rdev->net->hport);
		rc = rionet_setup_netdev(rdev->net->hport, ndev);
		rionet_check = 1;
		rionet_check = 1;
	}
	}


@@ -546,6 +546,8 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
		list_add_tail(&peer->node, &rionet_peers);
		list_add_tail(&peer->node, &rionet_peers);
	}
	}


	rio_set_drvdata(rdev, ndev);

      out:
      out:
	return rc;
	return rc;
}
}