mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Avoid duplicate random_unref on freeing an Ssh.
If ssh_init encounters a synchronous error, it will call random_unref before returning. But the Ssh structure it created will still exist, and if the caller (sensibly) responds by freeing it, then that will cause a second random_unref, leading to the RNG's refcount going below zero and failing an assertion. We never noticed this before because with only one PuTTY connection per process it was easier to just exit(1) without bothering to clean things up. Now, with all the multi-sessions-per-process fixes I'm doing, this has shown up as a problem. But other front ends may legitimately still just exit - I don't think I can sensibly enforce _not_ doing so at this late stage - so I've had to arrange to set a flag in the Ssh saying whether a random_unref is still pending or not.
This commit is contained in:
parent
71b00097dd
commit
28145fe21a
13
ssh.c
13
ssh.c
@ -991,6 +991,8 @@ struct ssh_tag {
|
||||
* agent-forwarding channels live in their channel structure.)
|
||||
*/
|
||||
agent_pending_query *auth_agent_query;
|
||||
|
||||
int need_random_unref;
|
||||
};
|
||||
|
||||
static const char *ssh_pkt_type(Ssh ssh, int type)
|
||||
@ -11316,9 +11318,15 @@ static const char *ssh_init(void *frontend_handle, void **backend_handle,
|
||||
#endif
|
||||
|
||||
random_ref(); /* do this now - may be needed by sharing setup code */
|
||||
ssh->need_random_unref = TRUE;
|
||||
|
||||
p = connect_to_host(ssh, host, port, realhost, nodelay, keepalive);
|
||||
if (p != NULL) {
|
||||
/* Call random_unref now instead of waiting until the caller
|
||||
* frees this useless Ssh object, in case the caller is
|
||||
* impatient and just exits without bothering, in which case
|
||||
* the random seed won't be re-saved. */
|
||||
ssh->need_random_unref = FALSE;
|
||||
random_unref();
|
||||
return p;
|
||||
}
|
||||
@ -11332,6 +11340,7 @@ static void ssh_free(void *handle)
|
||||
struct ssh_channel *c;
|
||||
struct ssh_rportfwd *pf;
|
||||
struct X11FakeAuth *auth;
|
||||
int need_random_unref;
|
||||
|
||||
if (ssh->v1_cipher_ctx)
|
||||
ssh->cipher->free_context(ssh->v1_cipher_ctx);
|
||||
@ -11434,9 +11443,11 @@ static void ssh_free(void *handle)
|
||||
if (ssh->gsslibs)
|
||||
ssh_gss_cleanup(ssh->gsslibs);
|
||||
#endif
|
||||
need_random_unref = ssh->need_random_unref;
|
||||
sfree(ssh);
|
||||
|
||||
random_unref();
|
||||
if (need_random_unref)
|
||||
random_unref();
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user