| From 7448aacf631f6e6a68940f1e51a01d63e1fab346 Mon Sep 17 00:00:00 2001 |
| From: Edwin Peer <edwin.peer@broadcom.com> |
| Date: Sun, 22 Mar 2020 16:40:02 -0400 |
| Subject: [PATCH] bnxt_en: fix memory leaks in bnxt_dcbnl_ieee_getets() |
| |
| commit 62d4073e86e62e316bea2c53e77db10418fd5dd7 upstream. |
| |
| The allocated ieee_ets structure goes out of scope without being freed, |
| leaking memory. Appropriate result codes should be returned so that |
| callers do not rely on invalid data passed by reference. |
| |
| Also cache the ETS config retrieved from the device so that it doesn't |
| need to be freed. The balance of the code was clearly written with the |
| intent of having the results of querying the hardware cached in the |
| device structure. The commensurate store was evidently missed though. |
| |
| Fixes: 7df4ae9fe855 ("bnxt_en: Implement DCBNL to support host-based DCBX.") |
| Signed-off-by: Edwin Peer <edwin.peer@broadcom.com> |
| Signed-off-by: Michael Chan <michael.chan@broadcom.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c |
| index 70775158c8c4..1c6198c53b5d 100644 |
| --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c |
| +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c |
| @@ -482,24 +482,26 @@ static int bnxt_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets) |
| { |
| struct bnxt *bp = netdev_priv(dev); |
| struct ieee_ets *my_ets = bp->ieee_ets; |
| + int rc; |
| |
| ets->ets_cap = bp->max_tc; |
| |
| if (!my_ets) { |
| - int rc; |
| - |
| if (bp->dcbx_cap & DCB_CAP_DCBX_HOST) |
| return 0; |
| |
| my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL); |
| if (!my_ets) |
| - return 0; |
| + return -ENOMEM; |
| rc = bnxt_hwrm_queue_cos2bw_qcfg(bp, my_ets); |
| if (rc) |
| - return 0; |
| + goto error; |
| rc = bnxt_hwrm_queue_pri2cos_qcfg(bp, my_ets); |
| if (rc) |
| - return 0; |
| + goto error; |
| + |
| + /* cache result */ |
| + bp->ieee_ets = my_ets; |
| } |
| |
| ets->cbs = my_ets->cbs; |
| @@ -508,6 +510,9 @@ static int bnxt_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets) |
| memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa)); |
| memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc)); |
| return 0; |
| +error: |
| + kfree(my_ets); |
| + return rc; |
| } |
| |
| static int bnxt_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets) |
| -- |
| 2.7.4 |
| |