ITADN

Nginx Worker Process SIGSEGV (Signal 11) with Passenger Module

#2664Openarch3x 创建于 2026-06-26
A
arch3xcommented
# Nginx Worker Process SIGSEGV (Signal 11) with Passenger Module **Date:** 2026-06-25 **Platform:** RHEL 9.8, CIS Benchmark Level 1, AWS EC2 --- ## Symptoms - Nginx worker processes crash immediately on first HTTP request with `signal 11 (SIGSEGV)` - Core dump shows crash in `ngx_escape_uri()` called from Passenger's `prepare_request_buffer_construction()` - Passenger watchdog/core start fine, but workers die on any request ## Root Cause **ABI mismatch between RHEL's nginx binary and Phusion's pre-built `mod_passenger` RPM.** RHEL 9's nginx (`nginx-core-1.26.3-9.module+el9.8.0`) is compiled with `NGX_HTTP_CACHE=1`, which adds an 8-byte pointer field (`ngx_http_cache_t *cache`) at offset 64 in `struct ngx_http_request_s`. Phusion's `nginx-mod-http-passenger-6.1.5-1.el9` RPM was compiled against nginx headers **without** `NGX_HTTP_CACHE` defined. This causes every struct field after offset 64 to be shifted by 8 bytes in the module's compiled code vs. the actual runtime binary layout. **Effect:** When Passenger reads `r->uri.data`, it actually reads `r->request_line.len` (garbage pointer). Passing this to `ngx_escape_uri()` causes the segfault. | Field | Binary (actual) | Passenger module (expected) | Delta | |-------|----------------|-----------------------------|-------| | `cache` | offset 64 | *not present* | +8 | | `method` | offset 856 | offset 848 | +8 | | `uri` | offset 888 | offset 880 | +8 | ## Fix (Manual CLI Procedure) Recompile the Passenger nginx module from gem source against RHEL's actual nginx source+config: ```bash # 1. Install build dependencies dnf install -y gcc gcc-c++ make pcre2-devel openssl-devel zlib-devel \ libxml2-devel libxslt-devel gd-devel perl-ExtUtils-Embed \ gperftools-devel ruby-devel curl-devel # 2. Download and prep RHEL nginx SRPM yumdownloader --source nginx-core rpm -ivh nginx-core-*.src.rpm cd ~/rpmbuild rpmbuild -bp SPECS/nginx.spec # 3. Configure with RHEL's exact flags + Passenger dynamic module cd ~/rpmbuild/BUILD/nginx-1.26.3 eval ./configure $(nginx -V 2>&1 | grep -oP '(?<=configure arguments: ).*') \ --add-dynamic-module=/usr/local/rvm/gems/ruby-3.4.2/gems/passenger-6.1.5/src/nginx_module # 4. Build just the modules make modules # 5. Install the correctly-compiled module cp objs/ngx_http_passenger_module.so /usr/lib64/nginx/modules/ngx_http_passenger_module.so cp objs/ngx_http_passenger_module.so /usr/share/nginx/modules/ngx_http_passenger_module.so # 6. Restart nginx nginx -t && systemctl restart nginx ``` ## Verification ```bash # Confirm no SIGSEGV in logs tail -20 /var/log/nginx/error.log | grep -c 'signal 11' # should be 0 # Confirm app responds curl -sk https://localhost/ | head -1 # should return HTML ``` ## Prevention - Do NOT use Phusion's pre-built `nginx-mod-http-passenger` RPM on RHEL 9 — it has an ABI mismatch - Always compile the Passenger nginx module from source against the installed RHEL nginx source - Pin nginx and passenger versions in Ansible; recompile module on any nginx update - Consider adding a molecule test that verifies nginx workers remain stable after startup ## Affected Packages | Package | Version | Source | |---------|---------|--------| | nginx-core | 1.26.3-9.module+el9.8.0+24374+c0e15309.1 | RHEL AppStream | | passenger | 6.1.5-1.el9 | Phusion repo | | nginx-mod-http-passenger | 6.1.5-1.el9 | Phusion repo (BROKEN) | | passenger gem | 6.1.5 | RVM ruby-3.4.2 |
2 条评论