Skip to content

mail auth HTTP can leave a stale session ctx after temp-pool destroy #23

@xintenseapple

Description

@xintenseapple

Finding: mail auth HTTP can leave a stale session ctx after temp-pool destroy

Summary

In freenginx, mail auth HTTP stores a temporary auth context in the mail session. Many error paths destroy the context pool without clearing the session module context slot. The client read handler can later fetch the stale context and use fields from freed pool memory on rare read-event failure paths.

Affected Area

  • src/mail/ngx_mail_auth_http_module.c
  • Functions: ngx_mail_auth_http_init(), auth HTTP read/write error paths, and ngx_mail_auth_http_block_read()

Source Evidence

The auth HTTP initialization path allocates a temporary pool and stores the context in the session:

ctx = ngx_pcalloc(pool, sizeof(ngx_mail_auth_http_ctx_t));
...
ctx->pool = pool;
...
ngx_mail_set_ctx(s, ctx, ngx_mail_auth_http_module);

Multiple error paths later close the auth HTTP peer and destroy ctx->pool without clearing that session context slot. One representative pattern is:

ngx_close_connection(c);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
return;

The client-side read handler can later fetch the module context and use it if read-event rearming fails:

if (ngx_handle_read_event(rev, 0) != NGX_OK) {
    c = rev->data;
    s = c->data;

    ctx = ngx_mail_get_module_ctx(s, ngx_mail_auth_http_module);

    ngx_close_connection(ctx->peer.connection);
    ngx_destroy_pool(ctx->pool);
    ngx_mail_session_internal_server_error(s);
}

If an auth HTTP error already destroyed the temporary pool while the client session remained alive, ngx_mail_get_module_ctx() can return a stale pointer.

Expected Behavior

Before destroying the temporary auth HTTP pool, freenginx should clear the mail session module context slot or otherwise make later handlers treat auth HTTP state as absent.

Impact

Potential use-after-free of mail auth HTTP context memory on an error path. The path requires an auth HTTP upstream error followed by a client-side read-event rearm failure, so the trigger is rare, but the cleanup invariant is weak because many error paths duplicate the same pool-destroy sequence.

Reproduction Strategy

Inject failure into ngx_handle_read_event() after an auth HTTP upstream error path that destroys ctx->pool while the client session remains open. Run under a memory-safety build or add assertions that the mail auth HTTP module context is NULL before pool destruction.

Suggested Fix

Introduce a shared mail auth HTTP cleanup helper that clears the session module context before destroying ctx->pool, and guard ngx_mail_auth_http_block_read() against a NULL context.

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