Klaus Demo nginx / abe6606
Mail: fixed duplicate resolving. When using SMTP with SSL and resolver, read events might be enabled during address resolving, leading to duplicate ngx_mail_ssl_handshake_handler() calls if something arrives from the client, and duplicate session initialization - including starting another resolving. This can lead to a segmentation fault if the session is closed after first resolving finished. Fix is to block read events while resolving. Reported by Robert Norris, http://mailman.nginx.org/pipermail/nginx/2019-July/058204.html. Maxim Dounin 1 year, 5 months ago
1 changed file(s) with 43 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
1414 static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx);
1515 static void ngx_mail_smtp_resolve_name(ngx_event_t *rev);
1616 static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx);
17 static void ngx_mail_smtp_block_reading(ngx_event_t *rev);
1718 static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c);
1819 static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev);
1920 static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s,
8788 ctx->data = s;
8889 ctx->timeout = cscf->resolver_timeout;
8990
91 s->resolver_ctx = ctx;
92 c->read->handler = ngx_mail_smtp_block_reading;
93
9094 if (ngx_resolve_addr(ctx) != NGX_OK) {
9195 ngx_mail_close_connection(c);
9296 }
167171 ctx->handler = ngx_mail_smtp_resolve_name_handler;
168172 ctx->data = s;
169173 ctx->timeout = cscf->resolver_timeout;
174
175 s->resolver_ctx = ctx;
176 c->read->handler = ngx_mail_smtp_block_reading;
170177
171178 if (ngx_resolve_name(ctx) != NGX_OK) {
172179 ngx_mail_close_connection(c);
238245
239246
240247 static void
248 ngx_mail_smtp_block_reading(ngx_event_t *rev)
249 {
250 ngx_connection_t *c;
251 ngx_mail_session_t *s;
252 ngx_resolver_ctx_t *ctx;
253
254 c = rev->data;
255 s = c->data;
256
257 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp reading blocked");
258
259 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
260
261 if (s->resolver_ctx) {
262 ctx = s->resolver_ctx;
263
264 if (ctx->handler == ngx_mail_smtp_resolve_addr_handler) {
265 ngx_resolve_addr_done(ctx);
266
267 } else if (ctx->handler == ngx_mail_smtp_resolve_name_handler) {
268 ngx_resolve_name_done(ctx);
269 }
270
271 s->resolver_ctx = NULL;
272 }
273
274 ngx_mail_close_connection(c);
275 }
276 }
277
278
279 static void
241280 ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c)
242281 {
243282 ngx_msec_t timeout;
255294
256295 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
257296 ngx_mail_close_connection(c);
297 }
298
299 if (c->read->ready) {
300 ngx_post_event(c->read, &ngx_posted_events);
258301 }
259302
260303 if (sscf->greeting_delay) {