Skip to content

Commit e54e478

Browse files
julianwiedmannVasily Gorbik
authored andcommitted
s390/qdio: (re-)initialize tiqdio list entries
When tiqdio_remove_input_queues() removes a queue from the tiq_list as part of qdio_shutdown(), it doesn't re-initialize the queue's list entry and the prev/next pointers go stale. If a subsequent qdio_establish() fails while sending the ESTABLISH cmd, it calls qdio_shutdown() again in QDIO_IRQ_STATE_ERR state and tiqdio_remove_input_queues() will attempt to remove the queue entry a second time. This dereferences the stale pointers, and bad things ensue. Fix this by re-initializing the list entry after removing it from the list. For good practice also initialize the list entry when the queue is first allocated, and remove the quirky checks that papered over this omission. Note that prior to commit e521813 ("s390/qdio: fix access to uninitialized qdio_q fields"), these checks were bogus anyway. setup_queues_misc() clears the whole queue struct, and thus needs to re-init the prev/next pointers as well. Fixes: 779e6e1 ("[S390] qdio: new qdio driver.") Cc: <[email protected]> Signed-off-by: Julian Wiedmann <[email protected]> Signed-off-by: Vasily Gorbik <[email protected]>
1 parent 83eb1a4 commit e54e478

File tree

2 files changed

+4
-2
lines changed

2 files changed

+4
-2
lines changed

drivers/s390/cio/qdio_setup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues)
150150
return -ENOMEM;
151151
}
152152
irq_ptr_qs[i] = q;
153+
INIT_LIST_HEAD(&q->entry);
153154
}
154155
return 0;
155156
}
@@ -178,6 +179,7 @@ static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr,
178179
q->mask = 1 << (31 - i);
179180
q->nr = i;
180181
q->handler = handler;
182+
INIT_LIST_HEAD(&q->entry);
181183
}
182184

183185
static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr,

drivers/s390/cio/qdio_thinint.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,14 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
8787
struct qdio_q *q;
8888

8989
q = irq_ptr->input_qs[0];
90-
/* if establish triggered an error */
91-
if (!q || !q->entry.prev || !q->entry.next)
90+
if (!q)
9291
return;
9392

9493
mutex_lock(&tiq_list_lock);
9594
list_del_rcu(&q->entry);
9695
mutex_unlock(&tiq_list_lock);
9796
synchronize_rcu();
97+
INIT_LIST_HEAD(&q->entry);
9898
}
9999

100100
static inline int has_multiple_inq_on_dsci(struct qdio_irq *irq_ptr)

0 commit comments

Comments
 (0)