s390/qeth: fix use-after-free in error path
[ Upstream commit afa0c5904ba16d59b0454f7ee4c807dae350f432 ]
The error path in qeth_alloc_qdio_buffers() that takes care of
cleaning up the Output Queues is buggy. It first frees the queue, but
then calls qeth_clear_outq_buffers() with that very queue struct.
Make the call to qeth_clear_outq_buffers() part of the free action
(in the correct order), and while at it fix the naming of the helper.
Fixes: 0da9581ddb
("qeth: exploit asynchronous delivery of storage blocks")
Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
683c0116fb
commit
74daf70b85
1 changed files with 6 additions and 9 deletions
|
@ -2452,11 +2452,12 @@ out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qeth_free_qdio_out_buf(struct qeth_qdio_out_q *q)
|
static void qeth_free_output_queue(struct qeth_qdio_out_q *q)
|
||||||
{
|
{
|
||||||
if (!q)
|
if (!q)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
qeth_clear_outq_buffers(q, 1);
|
||||||
qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
|
qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
|
||||||
kfree(q);
|
kfree(q);
|
||||||
}
|
}
|
||||||
|
@ -2529,10 +2530,8 @@ out_freeoutqbufs:
|
||||||
card->qdio.out_qs[i]->bufs[j] = NULL;
|
card->qdio.out_qs[i]->bufs[j] = NULL;
|
||||||
}
|
}
|
||||||
out_freeoutq:
|
out_freeoutq:
|
||||||
while (i > 0) {
|
while (i > 0)
|
||||||
qeth_free_qdio_out_buf(card->qdio.out_qs[--i]);
|
qeth_free_output_queue(card->qdio.out_qs[--i]);
|
||||||
qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
|
|
||||||
}
|
|
||||||
kfree(card->qdio.out_qs);
|
kfree(card->qdio.out_qs);
|
||||||
card->qdio.out_qs = NULL;
|
card->qdio.out_qs = NULL;
|
||||||
out_freepool:
|
out_freepool:
|
||||||
|
@ -2565,10 +2564,8 @@ static void qeth_free_qdio_buffers(struct qeth_card *card)
|
||||||
qeth_free_buffer_pool(card);
|
qeth_free_buffer_pool(card);
|
||||||
/* free outbound qdio_qs */
|
/* free outbound qdio_qs */
|
||||||
if (card->qdio.out_qs) {
|
if (card->qdio.out_qs) {
|
||||||
for (i = 0; i < card->qdio.no_out_queues; ++i) {
|
for (i = 0; i < card->qdio.no_out_queues; i++)
|
||||||
qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
|
qeth_free_output_queue(card->qdio.out_qs[i]);
|
||||||
qeth_free_qdio_out_buf(card->qdio.out_qs[i]);
|
|
||||||
}
|
|
||||||
kfree(card->qdio.out_qs);
|
kfree(card->qdio.out_qs);
|
||||||
card->qdio.out_qs = NULL;
|
card->qdio.out_qs = NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue