comparison src/event/ngx_event_quic.c @ 8501:fc16e303003a quic

QUIC: fixed possible use-after-free on stream cleanup. A QUIC stream could be destroyed by handler while in ngx_quic_stream_input(). To detect this, ngx_quic_find_stream() is used to check that it still exists. Previously, a stream id was passed to this routine off the frame structure. In case of stream cleanup, it is freed along with other frames belonging to the stream on cleanup. Then, a cleanup handler reuses last frames to update MAX_STREAMS and serve other purpose. Thus, ngx_quic_find_stream() is passed a reused frame with zeroed out part pointed by stream_id. If a stream with id 0x0 still exists, this leads to use-after-free.
author Sergey Kandaurov <pluknet@nginx.com>
date Fri, 07 Aug 2020 12:34:11 +0300
parents 12576ac9556d
children 69033a50c3ae
comparison
equal deleted inserted replaced
8500:12576ac9556d 8501:fc16e303003a
3004 3004
3005 3005
3006 static ngx_int_t 3006 static ngx_int_t
3007 ngx_quic_stream_input(ngx_connection_t *c, ngx_quic_frame_t *frame, void *data) 3007 ngx_quic_stream_input(ngx_connection_t *c, ngx_quic_frame_t *frame, void *data)
3008 { 3008 {
3009 uint64_t id;
3009 ngx_buf_t *b; 3010 ngx_buf_t *b;
3010 ngx_event_t *rev; 3011 ngx_event_t *rev;
3011 ngx_quic_stream_t *sn; 3012 ngx_quic_stream_t *sn;
3012 ngx_quic_connection_t *qc; 3013 ngx_quic_connection_t *qc;
3013 ngx_quic_stream_frame_t *f; 3014 ngx_quic_stream_frame_t *f;
3014 3015
3015 qc = c->quic; 3016 qc = c->quic;
3016 sn = data; 3017 sn = data;
3017 3018
3018 f = &frame->u.stream; 3019 f = &frame->u.stream;
3020 id = f->stream_id;
3019 3021
3020 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic existing stream"); 3022 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic existing stream");
3021 3023
3022 b = sn->b; 3024 b = sn->b;
3023 3025
3044 if (rev->active) { 3046 if (rev->active) {
3045 rev->handler(rev); 3047 rev->handler(rev);
3046 } 3048 }
3047 3049
3048 /* check if stream was destroyed by handler */ 3050 /* check if stream was destroyed by handler */
3049 if (ngx_quic_find_stream(&qc->streams.tree, f->stream_id) == NULL) { 3051 if (ngx_quic_find_stream(&qc->streams.tree, id) == NULL) {
3050 return NGX_DONE; 3052 return NGX_DONE;
3051 } 3053 }
3052 3054
3053 return NGX_OK; 3055 return NGX_OK;
3054 } 3056 }