Segfault when interpreting cached X-Accel-Redirect response

Jiří Setnička jiri.setnicka at cdn77.com
Fri Feb 2 11:48:19 UTC 2024


Hello,

I came across a situation when using X-Accel-Redirect could lead to a 
segfault (tested on the latest version - hg changeset 9207:73eb75bee30f 
but I believe this has been there for a long time).

It occurs only if the response with the X-Accel-Redirect header is 
firstly cached (when using proxy_ignore_headers to not interpret this 
header) and later this cached response is interpreted (after removing 
the X-Accel-Redirect from the proxy_ignore_headers directive). I 
prepared a simple testcase to reproduce it: use the attached nginx.conf 
file and run this curl (the first request caches the response, the 
second one tries to interpret it):

     curl localhost:1080 localhost:1081

Also, I believe that the core of the problem is because of the 
ngx_http_finalize_request(r, NGX_DONE); call in the 
ngx_http_upstream_process_headers function. This call is needed when 
doing an internal redirect after the real upstream request (to close the 
upstream request), but when serving from the cache, there is no upstream 
request to close and this call causes ngx_http_set_lingering_close to be 
called from the ngx_http_finalize_connection with no active request on 
the connection yielding to the segfault.

See the attached patch. Tested on our side and this fix works, also run 
through the nginx-tests and ok,  but I am not thoroughly sure that I am 
not forgetting some cases.

Thank you for your review.

Sincerely
Jiří Setnička
-------------- next part --------------
daemon off;

events {
    worker_connections 768;
}

http {
    proxy_cache_path    /usr/local/nginx/cache levels=1:2 keys_zone=cache:64m;
    proxy_cache         cache;
    proxy_buffering     on;
    proxy_cache_valid   200 1d;

    server {
        listen 1080;
        location / {
            proxy_ignore_headers X-Accel-Redirect;
            proxy_pass http://localhost:1082;
        }
    }

    server {
        listen 1081;
        location / {
            proxy_pass http://localhost:1082;
        }
    }

    server {
        listen 1082;
        location / {
            add_header X-Accel-Redirect "/redirected";
            return 200 "ORIG";
        }
        location /redirected {
            return 200 "REDIRECTED";
        }
    }
}

-------------- next part --------------
A non-text attachment was scrubbed...
Name: x-accel-redirect-fix.patch
Type: text/x-patch
Size: 1841 bytes
Desc: not available
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20240202/af6e90e0/attachment.bin>


More information about the nginx-devel mailing list