diff options
-rw-r--r-- | daemon/logind/logind.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/daemon/logind/logind.c b/daemon/logind/logind.c index 4e8149ef..e2e66db5 100644 --- a/daemon/logind/logind.c +++ b/daemon/logind/logind.c @@ -391,7 +391,9 @@ ackq_del(login_conn_ctx *conn) { size_t i; - assert(conn && conn->cb == sizeof(login_conn_ctx)); + // XXX in current implementation, the conn pointer may be + // destroyed before getting acks, so don't check its validness. + // assert(conn && conn->cb == sizeof(login_conn_ctx)); for (i = 0; i < g_ack_queue.size; i++) { if (g_ack_queue.queue[i] != conn) @@ -1465,24 +1467,29 @@ ack_cb(int tunnel, short event, void *arg) return; } - if (conn->cb != sizeof(login_conn_ctx)) + // some connections may be removed (for example, socket close) before being acked. + // XXX FIXME if someone created a new connection before ack comes and re-used + // the memory location of previous destroyed one, we'd have problem here. + if (!ackq_del(conn)) { - fprintf(stderr, LOG_PREFIX "warning: tunnel returned invalid ack. abort?\r\n"); - // assert(conn && conn->cb == sizeof(login_conn_ctx)); + if (g_verbose > VERBOSE_ERROR) fprintf(stderr, LOG_PREFIX + "drop abandoned ack connection: %p.\r\n", conn); return; } - // XXX success connection. - if (ackq_del(conn)) + // check connection + if (conn->cb != sizeof(login_conn_ctx)) { - // reset the state to prevent processing ackq again - conn->ctx.state = LOGIN_STATE_AUTH; - // this event is still in queue. - login_conn_remove(conn, conn->telnet.fd, 0); - } else { - if (g_verbose > VERBOSE_ERROR) fprintf(stderr, LOG_PREFIX - "got invalid ack connection: %p.\r\n", conn); + fprintf(stderr, LOG_PREFIX + "warning: received invalid ack from tunnel. abort/reset tunnel?\r\n"); + // assert(conn && conn->cb == sizeof(login_conn_ctx)); + return; } + + // reset the state to prevent processing ackq again + conn->ctx.state = LOGIN_STATE_AUTH; + // this event is still in queue. + login_conn_remove(conn, conn->telnet.fd, 0); } |