Both loops that drain the local packet lists in ssh_ptl_shutdown() call ssh_packet_put() on the loop variable. This drops the reference that the queue or the pending set held on the packet, which can be the last one, so the packet may be freed before the iterator advances to the next entry. The iterator then reads the list node of the freed packet to do so. Use list_for_each_entry_safe() for both loops, which caches the next entry while the current packet is still alive. Fixes: c167b9c7e3d6 ("platform/surface: Add Surface Aggregator subsystem") Cc: stable@vger.kernel.org Acked-by: Maximilian Luz Signed-off-by: Wentao Liang --- drivers/platform/surface/aggregator/ssh_packet_layer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.c b/drivers/platform/surface/aggregator/ssh_packet_layer.c index a51395942747..871780828419 100644 --- a/drivers/platform/surface/aggregator/ssh_packet_layer.c +++ b/drivers/platform/surface/aggregator/ssh_packet_layer.c @@ -1989,7 +1989,7 @@ void ssh_ptl_shutdown(struct ssh_ptl *ptl) spin_unlock(&ptl->pending.lock); /* Complete and drop packets on complete_q. */ - list_for_each_entry(p, &complete_q, queue_node) { + list_for_each_entry_safe(p, n, &complete_q, queue_node) { if (!test_and_set_bit(SSH_PACKET_SF_COMPLETED_BIT, &p->state)) __ssh_ptl_complete(p, -ESHUTDOWN); @@ -1997,7 +1997,7 @@ void ssh_ptl_shutdown(struct ssh_ptl *ptl) } /* Complete and drop packets on complete_p. */ - list_for_each_entry(p, &complete_p, pending_node) { + list_for_each_entry_safe(p, n, &complete_p, pending_node) { if (!test_and_set_bit(SSH_PACKET_SF_COMPLETED_BIT, &p->state)) __ssh_ptl_complete(p, -ESHUTDOWN); -- 2.34.1