mirror of
https://github.com/nginx/nginx.git
synced 2026-10-21 03:21:08 +00:00
Event pipe: do not free buffers still used by the downstream
When a body filter returned an error, ngx_event_pipe_drain_chains() returned all buffers to p->free_raw_bufs, including those in p->busy, which are still owned by the downstream. If upstream EOF was detected in the same ngx_event_pipe() pass, ngx_event_pipe_read_upstream() then freed them while still referenced. With HTTP/2 only the stream's fake connection is marked on error, so ngx_http_v2_send_output_queue() kept sending DATA frames pointing at the freed buffers, a use-after-free. Fixed by keeping the p->busy chains intact, the buffers are freed with the request pool. This also stops the pipe from reusing them for new upstream reads, which previously could overwrite response body data still queued for the client. Additionally, the pipe no longer treats a downstream it has given up on as merely blocked, so the loop is still guaranteed to terminate. Co-authored-by: Roman Arutyunyan <arut@nginx.com>
This commit is contained in:
parent
028c0fab84
commit
8fa349cef4
1 changed files with 2 additions and 5 deletions
|
|
@ -253,6 +253,7 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
|
|||
chain->next = NULL;
|
||||
|
||||
} else if (!p->cacheable
|
||||
&& !p->downstream_error
|
||||
&& p->downstream->data == p->output_ctx
|
||||
&& p->downstream->write->ready
|
||||
&& !p->downstream->write->delayed)
|
||||
|
|
@ -1111,11 +1112,7 @@ ngx_event_pipe_drain_chains(ngx_event_pipe_t *p)
|
|||
ngx_chain_t *cl, *tl;
|
||||
|
||||
for ( ;; ) {
|
||||
if (p->busy) {
|
||||
cl = p->busy;
|
||||
p->busy = NULL;
|
||||
|
||||
} else if (p->out) {
|
||||
if (p->out) {
|
||||
cl = p->out;
|
||||
p->out = NULL;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue