FAILED: patch "[PATCH] s390/qeth: fix memory leak after failed TX Buffer allocation" failed to apply to 4.9-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From e7a36d27f6b9f389e41d8189a8a08919c6835732 Mon Sep 17 00:00:00 2001
From: Julian Wiedmann <[email protected]>
Date: Tue, 9 Mar 2021 17:52:18 +0100
Subject: [PATCH] s390/qeth: fix memory leak after failed TX Buffer allocation
When qeth_alloc_qdio_queues() fails to allocate one of the buffers that back an Output Queue, the 'out_freeoutqbufs' path will free all previously allocated buffers for this queue. But it misses to free the half-finished queue struct itself.
Move the buffer allocation into qeth_alloc_output_queue(), and deal with such errors internally.
drivers/s390/net/qeth_core_main.c +17 -18
@@ -2634,15 +2634,28 @@ static void qeth_free_output_queue(struct qeth_qdio_out_q *q)static struct qeth_qdio_out_q *qeth_alloc_output_queue (void ) {struct qeth_qdio_out_q *q =kzalloc (sizeof (*q),GFP_KERNEL ); +unsigned int i;if (!q)return NULL ; -if (qdio_alloc_buffers (q->qdio_bufs,QDIO_MAX_BUFFERS_PER_Q )) { -kfree (q); -return NULL ; +if (qdio_alloc_buffers (q->qdio_bufs,QDIO_MAX_BUFFERS_PER_Q )) + goto err_qdio_bufs; + +for (i =0 ; i <QDIO_MAX_BUFFERS_PER_Q ; i++) { +if (qeth_init_qdio_out_buf (q, i)) + goto err_out_bufs; } +return q; + +err_out_bufs: +while (i >0 ) +kmem_cache_free (qeth_qdio_outbuf_cache, q->bufs[--i]); +qdio_free_buffers (q->qdio_bufs,QDIO_MAX_BUFFERS_PER_Q ); +err_qdio_bufs: +kfree (q); +return NULL ; }static void qeth_tx_completion_timer (struct timer_list *timer)
@@ -2655,7 +2668,7 @@ static void qeth_tx_completion_timer(struct timer_list *timer)static int qeth_alloc_qdio_queues (struct qeth_card *card) { -int i, j; +unsigned int i;QETH_CARD_TEXT (card,2 ,"allcqdbf" );
@@ -2689,13 +2702,6 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card) queue->coalesce_usecs =QETH_TX_COALESCE_USECS ; queue->max_coalesced_frames =QETH_TX_MAX_COALESCED_FRAMES ; queue->priority =QETH_QIB_PQUE_PRIO_DEFAULT ; - -/* give outbound qeth_qdio_buffers their qdio_buffers */ -for (j =0 ; j <QDIO_MAX_BUFFERS_PER_Q ; ++j) { -WARN_ON (queue->bufs[j]); -if (qeth_init_qdio_out_buf (queue, j)) - goto out_freeoutqbufs; - } }/* completion */
@@ -2704,13 +2710,6 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card)return 0 ; -out_freeoutqbufs: -while (j >0 ) { - --j; -kmem_cache_free (qeth_qdio_outbuf_cache, - card->qdio.out_qs[i]->bufs[j]); - card->qdio.out_qs[i]->bufs[j] =NULL ; - } out_freeoutq:while (i >0 ) {qeth_free_output_queue (card->qdio.out_qs[--i]);