Skip to content

mail proxy leaves a stale upstream connection pointer after close #24

@xintenseapple

Description

@xintenseapple

Finding: mail proxy leaves a stale upstream connection pointer after close

Summary

In freenginx, the mail proxy closes s->proxy->upstream.connection on upstream-error and session-close paths but does not clear the pointer. The closed ngx_connection_t is returned to the global free list, leaving the mail session with a non-NULL alias to a reusable connection object.

Affected Area

  • src/mail/ngx_mail_proxy_module.c
  • Functions: ngx_mail_proxy_upstream_error(), ngx_mail_proxy_internal_server_error(), and ngx_mail_proxy_close_session()

Source Evidence

Several paths close the upstream connection without clearing the session pointer:

if (s->proxy->upstream.connection) {
    ngx_log_debug1(NGX_LOG_DEBUG_MAIL, s->connection->log, 0,
                   "close mail proxy connection: %d",
                   s->proxy->upstream.connection->fd);

    ngx_close_connection(s->proxy->upstream.connection);
}

The same pattern appears in the upstream-error, internal-server-error, and close-session paths. After ngx_close_connection(), the connection object can be reused for another accepted or upstream connection while the mail session still has a non-NULL pointer to it.

Expected Behavior

After closing the upstream connection, the mail proxy session should clear s->proxy->upstream.connection so later logic cannot observe a stale alias to a reusable connection object.

Impact

Potential stale pointer to a reused ngx_connection_t. Follow-on reads of the non-NULL upstream connection field can observe unrelated connection state after connection reuse. This needs timing validation to demonstrate a later dereference after reuse.

Reproduction Strategy

Force upstream proxy failures while keeping the client-side mail session alive, then churn connections so the closed upstream ngx_connection_t is reused. Add an assertion or poison check that s->proxy->upstream.connection is NULL after upstream close.

Suggested Fix

Set s->proxy->upstream.connection = NULL immediately after every close of that pointer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions