1
0
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:
Simon Tatham 2017-11-27 19:29:47 +00:00
parent 71b00097dd
commit 28145fe21a

13
ssh.c
View File

@ -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();
}
/*