From ec158a2e19c9f81b3676e157652d93955789f423 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 18 Jan 2025 11:03:24 +0000 Subject: [PATCH] Pageant: call signop_unlink from signop_free. A user reported that the following sequence of events leads to Pageant crashing: - load an encrypted key into Pageant for decryption later - attempt to use the key, so that Pageant prompts for the passphrase - before entering the passphrase, abort the attempt to use the key (e.g. by closing the PuTTY that was trying to use it) - now enter the passphrase at the Pageant prompt, once the need for it has gone away. Once the key is decrypted, unblock_requests_for_key() goes through the linked list of blocked PageantSignOp attached to the private key record it's just decrypted, and tries to unblock them. The PageantSignOp belonging to the aborted Pageant request is still linked on that list, which it shouldn't be, because it's also been freed by pageant_unregister_client when that traversed the separate linked list of PageantAsyncOp associated with that client connection. So the private key's list of blocked requests contained a stale pointer. Now PageantSignOp's implementation of the PageantAsyncOp free method makes sure to unlink the signop from any list it's on before freeing it. --- pageant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pageant.c b/pageant.c index 961e1f03..6d6f70e1 100644 --- a/pageant.c +++ b/pageant.c @@ -648,6 +648,7 @@ static void signop_unlink(PageantSignOp *so) static void signop_free(PageantAsyncOp *pao) { PageantSignOp *so = container_of(pao, PageantSignOp, pao); + signop_unlink(so); strbuf_free(so->data_to_sign); sfree(so); }