[PATCH] qed: Track allocation size of qed_ll2_buffer

From: Kees Cook
Date: Tue Oct 18 2022 - 05:01:03 EST


In preparation for requiring that build_skb() have a non-zero size
argument, track the qed_ll2_buffer data allocation size explicitly
and pass it into build_skb(). To retain the original result of using
the ksize() side-effect on the skb size, explicitly round up the size
during allocation.

Cc: Ariel Elior <aelior@xxxxxxxxxxx>
Cc: Manish Chopra <manishc@xxxxxxxxxxx>
Cc: "David S. Miller" <davem@xxxxxxxxxxxxx>
Cc: Eric Dumazet <edumazet@xxxxxxxxxx>
Cc: Jakub Kicinski <kuba@xxxxxxxxxx>
Cc: Paolo Abeni <pabeni@xxxxxxxxxx>
Cc: netdev@xxxxxxxxxxxxxxx
Signed-off-by: Kees Cook <keescook@xxxxxxxxxxxx>
---
drivers/net/ethernet/qlogic/qed/qed_ll2.c | 37 ++++++++++++-----------
1 file changed, 20 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
index ed274f033626..750391e4d80a 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
@@ -62,6 +62,7 @@ struct qed_cb_ll2_info {
struct qed_ll2_buffer {
struct list_head list;
void *data;
+ u32 len;
dma_addr_t phys_addr;
};

@@ -111,20 +112,23 @@ static void qed_ll2b_complete_tx_packet(void *cxt,
}

static int qed_ll2_alloc_buffer(struct qed_dev *cdev,
- u8 **data, dma_addr_t *phys_addr)
+ struct qed_ll2_buffer *buffer)
{
- *data = kmalloc(cdev->ll2->rx_size, GFP_ATOMIC);
- if (!(*data)) {
+ buffer->len = kmalloc_size_roundup(cdev->ll2->rx_size);
+ buffer->data = kmalloc(buffer->len, GFP_ATOMIC);
+ if (!buffer->data) {
DP_INFO(cdev, "Failed to allocate LL2 buffer data\n");
+ buffer->len = 0;
return -ENOMEM;
}

- *phys_addr = dma_map_single(&cdev->pdev->dev,
- ((*data) + NET_SKB_PAD),
- cdev->ll2->rx_size, DMA_FROM_DEVICE);
- if (dma_mapping_error(&cdev->pdev->dev, *phys_addr)) {
+ buffer->phys_addr = dma_map_single(&cdev->pdev->dev,
+ buffer->data + NET_SKB_PAD,
+ buffer->len, DMA_FROM_DEVICE);
+ if (dma_mapping_error(&cdev->pdev->dev, buffer->phys_addr)) {
DP_INFO(cdev, "Failed to map LL2 buffer data\n");
- kfree((*data));
+ kfree(buffer->data);
+ buffer->len = 0;
return -ENOMEM;
}

@@ -139,6 +143,7 @@ static int qed_ll2_dealloc_buffer(struct qed_dev *cdev,
dma_unmap_single(&cdev->pdev->dev, buffer->phys_addr,
cdev->ll2->rx_size, DMA_FROM_DEVICE);
kfree(buffer->data);
+ buffer->len = 0;
list_del(&buffer->list);

cdev->ll2->rx_cnt--;
@@ -164,11 +169,10 @@ static void qed_ll2b_complete_rx_packet(void *cxt,
struct qed_hwfn *p_hwfn = cxt;
struct qed_ll2_buffer *buffer = data->cookie;
struct qed_dev *cdev = p_hwfn->cdev;
- dma_addr_t new_phys_addr;
+ struct qed_ll2_buffer new_buffer = { };
struct sk_buff *skb;
bool reuse = false;
int rc = -EINVAL;
- u8 *new_data;

DP_VERBOSE(p_hwfn,
(NETIF_MSG_RX_STATUS | QED_MSG_STORAGE | NETIF_MSG_PKTDATA),
@@ -191,8 +195,7 @@ static void qed_ll2b_complete_rx_packet(void *cxt,

/* Allocate a replacement for buffer; Reuse upon failure */
if (!reuse)
- rc = qed_ll2_alloc_buffer(p_hwfn->cdev, &new_data,
- &new_phys_addr);
+ rc = qed_ll2_alloc_buffer(p_hwfn->cdev, &new_buffer);

/* If need to reuse or there's no replacement buffer, repost this */
if (rc)
@@ -200,7 +203,7 @@ static void qed_ll2b_complete_rx_packet(void *cxt,
dma_unmap_single(&cdev->pdev->dev, buffer->phys_addr,
cdev->ll2->rx_size, DMA_FROM_DEVICE);

- skb = build_skb(buffer->data, 0);
+ skb = build_skb(buffer->data, buffer->len);
if (!skb) {
DP_INFO(cdev, "Failed to build SKB\n");
kfree(buffer->data);
@@ -235,8 +238,9 @@ static void qed_ll2b_complete_rx_packet(void *cxt,

out_post1:
/* Update Buffer information and update FW producer */
- buffer->data = new_data;
- buffer->phys_addr = new_phys_addr;
+ buffer->data = new_buffer.data;
+ buffer->len = new_buffer.len;
+ buffer->phys_addr = new_buffer.phys_addr;

out_post:
rc = qed_ll2_post_rx_buffer(p_hwfn, cdev->ll2->handle,
@@ -2608,8 +2612,7 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
goto err0;
}

- rc = qed_ll2_alloc_buffer(cdev, (u8 **)&buffer->data,
- &buffer->phys_addr);
+ rc = qed_ll2_alloc_buffer(cdev, buffer);
if (rc) {
kfree(buffer);
goto err0;
--
2.34.1