From 920234769e1d1934e101a58c350f7740b0550d84 Mon Sep 17 00:00:00 2001 From: shenjian Date: Sat, 11 May 2019 09:26:15 +0800 Subject: [PATCH] net: hns3: fix cpu rmap handle issue driver inclusion category: bugfix bugzilla: NA CVE: NA Currently, driver regists affinity notifier twice for each irq, which may case use-afer-free and double free issue. This patch fixes it. Feature or Bugfix:Bugfix Signed-off-by: shenjian (K) Reviewed-by: lipeng Reviewed-by: Yang Yingliang Signed-off-by: Yang Yingliang --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 67 ++++++------------- 1 file changed, 19 insertions(+), 48 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index a13534013e70..301cc45c270d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -82,22 +82,6 @@ static irqreturn_t hns3_irq_handle(int irq, void *vector) return IRQ_HANDLED; } -/* This callback function is used to set affinity changes to the irq affinity - * masks when the irq_set_affinity_notifier function is used. - */ -static void hns3_nic_irq_affinity_notify(struct irq_affinity_notify *notify, - const cpumask_t *mask) -{ - struct hns3_enet_tqp_vector *tqp_vectors = - container_of(notify, struct hns3_enet_tqp_vector, - affinity_notify); - - tqp_vectors->affinity_mask = *mask; -} - -static void hns3_nic_irq_affinity_release(struct kref *ref) -{ -} static void hns3_nic_uninit_irq(struct hns3_nic_priv *priv) { @@ -110,8 +94,7 @@ static void hns3_nic_uninit_irq(struct hns3_nic_priv *priv) if (tqp_vectors->irq_init_flag != HNS3_VECTOR_INITED) continue; - /* clear the affinity notifier and affinity mask */ - irq_set_affinity_notifier(tqp_vectors->vector_irq, NULL); + /* clear the affinity mask */ irq_set_affinity_hint(tqp_vectors->vector_irq, NULL); /* release the irq resource */ @@ -163,14 +146,8 @@ static int hns3_nic_init_irq(struct hns3_nic_priv *priv) return ret; } - tqp_vectors->affinity_notify.notify = - hns3_nic_irq_affinity_notify; - tqp_vectors->affinity_notify.release = - hns3_nic_irq_affinity_release; irq_set_affinity_hint(tqp_vectors->vector_irq, &tqp_vectors->affinity_mask); - irq_set_affinity_notifier(tqp_vectors->vector_irq, - &tqp_vectors->affinity_notify); tqp_vectors->irq_init_flag = HNS3_VECTOR_INITED; } @@ -341,28 +318,33 @@ static void hns3_tqp_disable(struct hnae3_queue *tqp) hns3_write_dev(tqp, HNS3_RING_EN_REG, rcb_reg); } -static int hns3_set_rx_cpu_rmap(struct hnae3_handle *h) +static void hns3_free_rx_cpu_rmap(struct net_device *netdev) +{ +#ifdef CONFIG_RFS_ACCEL + free_irq_cpu_rmap(netdev->rx_cpu_rmap); + netdev->rx_cpu_rmap = NULL; +#endif +} + +static int hns3_set_rx_cpu_rmap(struct net_device *netdev) { #ifdef CONFIG_RFS_ACCEL - struct net_device *netdev = h->kinfo.netdev; struct hns3_nic_priv *priv = netdev_priv(netdev); struct hns3_enet_tqp_vector *tqp_vector; int i, ret; if (!netdev->rx_cpu_rmap) { - netdev->rx_cpu_rmap = alloc_irq_cpu_rmap(h->kinfo.num_tqps); + netdev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->vector_num); if (!netdev->rx_cpu_rmap) return -ENOMEM; } - for (i = 0; i < h->kinfo.num_tqps; i++) { - tqp_vector = - priv->ring_data[i + h->kinfo.num_tqps].ring->tqp_vector; + for (i = 0; i < priv->vector_num; i++) { + tqp_vector = &priv->tqp_vector[i]; ret = irq_cpu_rmap_add(netdev->rx_cpu_rmap, tqp_vector->vector_irq); if (ret) { - free_irq_cpu_rmap(netdev->rx_cpu_rmap); - netdev->rx_cpu_rmap = NULL; + hns3_free_rx_cpu_rmap(netdev); return ret; } } @@ -370,18 +352,6 @@ static int hns3_set_rx_cpu_rmap(struct hnae3_handle *h) return 0; } -static void hns3_free_rx_cpu_rmap(struct hnae3_handle *h) -{ -#ifdef CONFIG_RFS_ACCEL - struct net_device *netdev = h->kinfo.netdev; - - if (netdev->rx_cpu_rmap) { - free_irq_cpu_rmap(netdev->rx_cpu_rmap); - netdev->rx_cpu_rmap = NULL; - } -#endif -} - static int hns3_nic_net_up(struct net_device *netdev) { struct hns3_nic_priv *priv = netdev_priv(netdev); @@ -394,7 +364,7 @@ static int hns3_nic_net_up(struct net_device *netdev) return ret; /* the device can work without cpu rmap, only aRFS needs it */ - ret = hns3_set_rx_cpu_rmap(h); + ret = hns3_set_rx_cpu_rmap(netdev); if (ret) netdev_warn(netdev, "set rx cpu rmap fail, ret=%d!\n", ret); @@ -402,7 +372,7 @@ static int hns3_nic_net_up(struct net_device *netdev) ret = hns3_nic_init_irq(priv); if (ret) { netdev_err(netdev, "init irq failed! ret=%d\n", ret); - return ret; + goto free_rmap; } /* enable the vectors */ @@ -428,7 +398,8 @@ static int hns3_nic_net_up(struct net_device *netdev) hns3_vector_disable(&priv->tqp_vector[j]); hns3_nic_uninit_irq(priv); - +free_rmap: + hns3_free_rx_cpu_rmap(netdev); return ret; } @@ -511,7 +482,7 @@ static void hns3_nic_net_down(struct net_device *netdev) if (ops->stop) ops->stop(priv->ae_handle); - hns3_free_rx_cpu_rmap(h); + hns3_free_rx_cpu_rmap(netdev); /* free irq resources */ hns3_nic_uninit_irq(priv); -- GitLab