Skip to content

Fix segfault when fake request interacts with ngx_http_realip_module#712

Open
DenGontsov wants to merge 1 commit into
slact:masterfrom
DenGontsov:fix/realip-null-sockaddr
Open

Fix segfault when fake request interacts with ngx_http_realip_module#712
DenGontsov wants to merge 1 commit into
slact:masterfrom
DenGontsov:fix/realip-null-sockaddr

Conversation

@DenGontsov
Copy link
Copy Markdown

@DenGontsov DenGontsov commented May 19, 2026

Problem

Nchan creates fake requests with r->connection->sockaddr == NULL. When any module that performs IP-based access checks processes such a request (e.g., ngx_http_access_module with allow/deny, ngx_http_realip_module, ngx_http_geo_module), it calls ngx_cidr_match(sa=0x0), causing a segmentation fault.

Steps to Reproduce

  1. Configure nchan subscriber location with allow 1.1.1.1; deny all;
  2. Send a request to the subscriber endpoint
  3. Nginx segfaults with backtrace showing ngx_cidr_match (sa=0x0, ...)

Backtrace (GDB)

#0  ngx_cidr_match (sa=0x0, cidrs=0x5b7479b114b8) at src/core/ngx_inet.c:495
#1  ngx_http_get_forwarded_addr_internal (r=r@entry=0x5b7479bf4160, addr=addr@entry=0x7fff10016b80, xff=0x5b7479af3290 "212.42.XX.XX", xfflen=13, proxies=proxies@entry=0x5b7479b114b8, recursive=recursive@entry=1) at src/http/ngx_http_core_module.c:2847
#2  ngx_http_get_forwarded_addr (r=r@entry=0x5b7479bf4160, addr=addr@entry=0x7fff10016b80, headers=headers@entry=0x5b7479b037b8, value=<optimized out>, proxies=0x5b7479b114b8, recursive=1) at src/http/ngx_http_core_module.c:2803
#3  ngx_http_realip_handler (r=0x5b7479bf4160) at src/http/modules/ngx_http_realip_module.c:234
#4  ngx_http_core_generic_phase (r=0x5b7479bf4160, ph=0x5b7479b7e378) at src/http/ngx_http_core_module.c:918
#5  ngx_http_core_run_phases (r=0x5b7479bf4160) at src/http/ngx_http_core_module.c:896
#6  ngx_http_handler (r=<optimized out>) at src/http/ngx_http_core_module.c:879
#7  ngx_http_run_posted_requests (c=0x5b7479b84150) at src/http/ngx_http_request.c:2621
#8  nchan_requestmachine_run (rm=0x5b7479b04b00) at /root/nginx/nchan/src/util/nchan_fake_request.c:326
#9  nchan_requestmachine_request (rm=0x5b7479b04b00, params=params@entry=0x7fff10016d50) at /root/nginx/nchan/src/util/nchan_fake_request.c:489

Root Cause

The allow/deny directive from ngx_http_access_module (and similar IP-checking modules like realip, geo) calls ngx_cidr_match() to validate the client IP address. When Nchan creates a fake request for internal subrequests, the sockaddr field of the connection is NULL. This causes a null pointer dereference in ngx_cidr_match() when it attempts to access sa->sa_family.

Solution

Initialize sockaddr for fake connections in nchan_create_fake_connection() to a valid loopback address:

  • Allocate struct sockaddr_in from the connection pool
  • Set sin_family = AF_INET
  • Set sin_addr.s_addr = htonl(INADDR_LOOPBACK) (127.0.0.1)
  • Set c->socklen = sizeof(struct sockaddr_in)

This ensures that any module calling ngx_cidr_match() receives a valid sockaddr pointer instead of NULL.

Testing

Configuration Result
Without patch + allow/deny ❌ Segfault on every request
Without patch + no allow/deny ✅ Works (no IP checks triggered)
With patch + allow/deny No segfault, pub/sub works correctly
With patch + realip enabled ✅ No segfault

Test Environment

  • nginx 1.30.1
  • nchan 1.3.8
  • Ubuntu 24.04

Affected Versions

All nchan versions that create fake requests with sockaddr == NULL (likely all versions) are affected when used with:

  • ngx_http_access_module (allow/deny)
  • ngx_http_realip_module
  • ngx_http_geo_module
  • Any other module that calls ngx_cidr_match() or accesses r->connection->sockaddr

Additional Notes

This fix is backward compatible and does not affect existing functionality. The loopback address is a safe dummy value because fake requests are internal and their IP address is never used for actual network routing.

Please also give credit to Nazim Khalilov for researching this bug.

Initialize sockaddr for fake connection to prevent null pointer dereference
in ngx_cidr_match() called by ngx_http_realip_module.

Problem:
- nchan creates fake requests with sockaddr == NULL
- realip module calls ngx_cidr_match(sa=0x0) causing segfault

Solution:
- Allocate and initialize sockaddr in nchan_create_fake_connection()
- Use loopback address (127.0.0.1) as dummy sockaddr

Tested with:
- nginx 1.30.1
- nchan 1.3.8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant