1 From 7a52d6ee03c768885b211035c04a1de160575705 Mon Sep 17 00:00:00 2001
2 From: Julian Wiedmann <jwi@linux.ibm.com>
3 Date: Mon, 4 Feb 2019 17:40:07 +0100
4 Subject: s390/qeth: fix use-after-free in error path
6 [ Upstream commit afa0c5904ba16d59b0454f7ee4c807dae350f432 ]
8 The error path in qeth_alloc_qdio_buffers() that takes care of
9 cleaning up the Output Queues is buggy. It first frees the queue, but
10 then calls qeth_clear_outq_buffers() with that very queue struct.
12 Make the call to qeth_clear_outq_buffers() part of the free action
13 (in the correct order), and while at it fix the naming of the helper.
15 Fixes: 0da9581ddb0f ("qeth: exploit asynchronous delivery of storage blocks")
16 Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
17 Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
18 Signed-off-by: David S. Miller <davem@davemloft.net>
19 Signed-off-by: Sasha Levin <sashal@kernel.org>
21 drivers/s390/net/qeth_core_main.c | 15 ++++++---------
22 1 file changed, 6 insertions(+), 9 deletions(-)
24 diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
25 index 533bd2467910..b40604d0126f 100644
26 --- a/drivers/s390/net/qeth_core_main.c
27 +++ b/drivers/s390/net/qeth_core_main.c
28 @@ -2452,11 +2452,12 @@ static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx)
32 -static void qeth_free_qdio_out_buf(struct qeth_qdio_out_q *q)
33 +static void qeth_free_output_queue(struct qeth_qdio_out_q *q)
38 + qeth_clear_outq_buffers(q, 1);
39 qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
42 @@ -2529,10 +2530,8 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
43 card->qdio.out_qs[i]->bufs[j] = NULL;
47 - qeth_free_qdio_out_buf(card->qdio.out_qs[--i]);
48 - qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
51 + qeth_free_output_queue(card->qdio.out_qs[--i]);
52 kfree(card->qdio.out_qs);
53 card->qdio.out_qs = NULL;
55 @@ -2565,10 +2564,8 @@ static void qeth_free_qdio_buffers(struct qeth_card *card)
56 qeth_free_buffer_pool(card);
57 /* free outbound qdio_qs */
58 if (card->qdio.out_qs) {
59 - for (i = 0; i < card->qdio.no_out_queues; ++i) {
60 - qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
61 - qeth_free_qdio_out_buf(card->qdio.out_qs[i]);
63 + for (i = 0; i < card->qdio.no_out_queues; i++)
64 + qeth_free_output_queue(card->qdio.out_qs[i]);
65 kfree(card->qdio.out_qs);
66 card->qdio.out_qs = NULL;