| From f4edc50c768db85471c26e37c706e52c4407e8aa Mon Sep 17 00:00:00 2001 |
| From: Sameeh Jubran <sameehj@amazon.com> |
| Date: Wed, 1 May 2019 16:47:04 +0300 |
| Subject: net: ena: fix: set freed objects to NULL to avoid failing future |
| allocations |
| |
| [ Upstream commit 8ee8ee7fe87bf64738ab4e31be036a7165608b27 ] |
| |
| In some cases when a queue related allocation fails, successful past |
| allocations are freed but the pointer that pointed to them is not |
| set to NULL. This is a problem for 2 reasons: |
| 1. This is generally a bad practice since this pointer might be |
| accidentally accessed in the future. |
| 2. Future allocations using the same pointer check if the pointer |
| is NULL and fail if it is not. |
| |
| Fixed this by setting such pointers to NULL in the allocation of |
| queue related objects. |
| |
| Also refactored the code of ena_setup_tx_resources() to goto-style |
| error handling to avoid code duplication of resource freeing. |
| |
| Fixes: 1738cd3ed342 ("net: ena: Add a driver for Amazon Elastic Network Adapters (ENA)") |
| Signed-off-by: Arthur Kiyanovski <akiyano@amazon.com> |
| Signed-off-by: Sameeh Jubran <sameehj@amazon.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/ethernet/amazon/ena/ena_netdev.c | 25 ++++++++++++-------- |
| 1 file changed, 15 insertions(+), 10 deletions(-) |
| |
| diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c |
| index 41c1c9acb3246..9b03d7e404f83 100644 |
| --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c |
| +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c |
| @@ -224,28 +224,23 @@ static int ena_setup_tx_resources(struct ena_adapter *adapter, int qid) |
| if (!tx_ring->tx_buffer_info) { |
| tx_ring->tx_buffer_info = vzalloc(size); |
| if (!tx_ring->tx_buffer_info) |
| - return -ENOMEM; |
| + goto err_tx_buffer_info; |
| } |
| |
| size = sizeof(u16) * tx_ring->ring_size; |
| tx_ring->free_tx_ids = vzalloc_node(size, node); |
| if (!tx_ring->free_tx_ids) { |
| tx_ring->free_tx_ids = vzalloc(size); |
| - if (!tx_ring->free_tx_ids) { |
| - vfree(tx_ring->tx_buffer_info); |
| - return -ENOMEM; |
| - } |
| + if (!tx_ring->free_tx_ids) |
| + goto err_free_tx_ids; |
| } |
| |
| size = tx_ring->tx_max_header_size; |
| tx_ring->push_buf_intermediate_buf = vzalloc_node(size, node); |
| if (!tx_ring->push_buf_intermediate_buf) { |
| tx_ring->push_buf_intermediate_buf = vzalloc(size); |
| - if (!tx_ring->push_buf_intermediate_buf) { |
| - vfree(tx_ring->tx_buffer_info); |
| - vfree(tx_ring->free_tx_ids); |
| - return -ENOMEM; |
| - } |
| + if (!tx_ring->push_buf_intermediate_buf) |
| + goto err_push_buf_intermediate_buf; |
| } |
| |
| /* Req id ring for TX out of order completions */ |
| @@ -259,6 +254,15 @@ static int ena_setup_tx_resources(struct ena_adapter *adapter, int qid) |
| tx_ring->next_to_clean = 0; |
| tx_ring->cpu = ena_irq->cpu; |
| return 0; |
| + |
| +err_push_buf_intermediate_buf: |
| + vfree(tx_ring->free_tx_ids); |
| + tx_ring->free_tx_ids = NULL; |
| +err_free_tx_ids: |
| + vfree(tx_ring->tx_buffer_info); |
| + tx_ring->tx_buffer_info = NULL; |
| +err_tx_buffer_info: |
| + return -ENOMEM; |
| } |
| |
| /* ena_free_tx_resources - Free I/O Tx Resources per Queue |
| @@ -378,6 +382,7 @@ static int ena_setup_rx_resources(struct ena_adapter *adapter, |
| rx_ring->free_rx_ids = vzalloc(size); |
| if (!rx_ring->free_rx_ids) { |
| vfree(rx_ring->rx_buffer_info); |
| + rx_ring->rx_buffer_info = NULL; |
| return -ENOMEM; |
| } |
| } |
| -- |
| 2.20.1 |
| |