Mercurial > hg > nginx
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 } |