Hello! On Wed, Nov 23, 2022 at 04:56:10PM +0400, Sergey Kandaurov wrote:
> On Sun, Oct 30, 2022 at 05:41:00AM +0300, Maxim Dounin wrote: > > # HG changeset patch > > # User Maxim Dounin <mdou...@mdounin.ru> > > # Date 1667097653 -10800 > > # Sun Oct 30 05:40:53 2022 +0300 > > # Node ID 55bcf8dc4ee35ccf40f5b8a7cffde63e7edb9494 > > # Parent 1ae25660c0c76edef14121ca64362f28b9d57a70 > > Filtering duplicate addresses in listen (ticket #2400). > > > > Due to the glibc bug[1], getaddrinfo("localhost") with AI_ADDRCONFIG > > on a typical host with glibc and without IPv6 returns two 127.0.0.1 > > addresses, and therefore "listen localhost:80;" used to result the > > result in ? Fixed, thnx. > > "duplicate ... address and port pair" after 4f9b72a229c1. > > > > Fix is to explicitly filter out duplicate addresses returned during > > resolution of a name. > > > > [1] https://sourceware.org/bugzilla/show_bug.cgi?id=14969 > > > > diff --git a/src/http/ngx_http_core_module.c > > b/src/http/ngx_http_core_module.c > > --- a/src/http/ngx_http_core_module.c > > +++ b/src/http/ngx_http_core_module.c > > @@ -3963,7 +3963,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx > > > > ngx_str_t *value, size; > > ngx_url_t u; > > - ngx_uint_t n; > > + ngx_uint_t n, i; > > ngx_http_listen_opt_t lsopt; > > > > cscf->listen = 1; > > @@ -4289,6 +4289,16 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx > > } > > > > for (n = 0; n < u.naddrs; n++) { > > + > > + for (i = 0; i < n; i++) { > > + if (ngx_cmp_sockaddr(u.addrs[n].sockaddr, u.addrs[n].socklen, > > + u.addrs[i].sockaddr, u.addrs[i].socklen, > > 0) > > + == NGX_OK) > > + { > > + goto next; > > + } > > + } > > + > > lsopt.sockaddr = u.addrs[n].sockaddr; > > lsopt.socklen = u.addrs[n].socklen; > > lsopt.addr_text = u.addrs[n].name; > > @@ -4297,6 +4307,9 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx > > if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) { > > return NGX_CONF_ERROR; > > } > > + > > + next: > > + continue; > > } > > > > return NGX_CONF_OK; > > diff --git a/src/mail/ngx_mail_core_module.c > > b/src/mail/ngx_mail_core_module.c > > --- a/src/mail/ngx_mail_core_module.c > > +++ b/src/mail/ngx_mail_core_module.c > > @@ -308,7 +308,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx > > ngx_str_t *value, size; > > ngx_url_t u; > > ngx_uint_t i, n, m; > > - ngx_mail_listen_t *ls, *als; > > + ngx_mail_listen_t *ls, *als, *nls; > > ngx_mail_module_t *module; > > ngx_mail_core_main_conf_t *cmcf; > > > > @@ -333,7 +333,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx > > > > cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module); > > > > - ls = ngx_array_push_n(&cmcf->listen, u.naddrs); > > + ls = ngx_array_push(&cmcf->listen); > > if (ls == NULL) { > > return NGX_CONF_ERROR; > > } > > @@ -571,17 +571,37 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx > > als = cmcf->listen.elts; > > With push of additional cmcf->listen elements moved inside loop, > als can become a stale pointer due to reallocation in ngx_array_push(). > As such, als assignment should be kept updated (here and in stream). > > Otherwise, looks good. Sure, thanks for catching this. Updated with the following additional change: diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -568,8 +568,6 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx return NGX_CONF_ERROR; } - als = cmcf->listen.elts; - for (n = 0; n < u.naddrs; n++) { for (i = 0; i < n; i++) { @@ -598,6 +596,8 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx nls->addr_text = u.addrs[n].name; nls->wildcard = ngx_inet_wildcard(nls->sockaddr); + als = cmcf->listen.elts; + for (i = 0; i < cmcf->listen.nelts - 1; i++) { if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen, diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c +++ b/src/stream/ngx_stream_core_module.c @@ -886,8 +886,6 @@ ngx_stream_core_listen(ngx_conf_t *cf, n #endif } - als = cmcf->listen.elts; - for (n = 0; n < u.naddrs; n++) { for (i = 0; i < n; i++) { @@ -916,6 +914,8 @@ ngx_stream_core_listen(ngx_conf_t *cf, n nls->addr_text = u.addrs[n].name; nls->wildcard = ngx_inet_wildcard(nls->sockaddr); + als = cmcf->listen.elts; + for (i = 0; i < cmcf->listen.nelts - 1; i++) { if (nls->type != als[i].type) { continue; Full patch: # HG changeset patch # User Maxim Dounin <mdou...@mdounin.ru> # Date 1669213808 -10800 # Wed Nov 23 17:30:08 2022 +0300 # Node ID 4cc2bfeff46c7b7ee2b098f39ebfc1e44754df1e # Parent b809f53d3f5bd04df36ac338845289d8e60a888b Filtering duplicate addresses in listen (ticket #2400). Due to the glibc bug[1], getaddrinfo("localhost") with AI_ADDRCONFIG on a typical host with glibc and without IPv6 returns two 127.0.0.1 addresses, and therefore "listen localhost:80;" used to result in "duplicate ... address and port pair" after 4f9b72a229c1. Fix is to explicitly filter out duplicate addresses returned during resolution of a name. [1] https://sourceware.org/bugzilla/show_bug.cgi?id=14969 diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -3963,7 +3963,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx ngx_str_t *value, size; ngx_url_t u; - ngx_uint_t n; + ngx_uint_t n, i; ngx_http_listen_opt_t lsopt; cscf->listen = 1; @@ -4289,6 +4289,16 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx } for (n = 0; n < u.naddrs; n++) { + + for (i = 0; i < n; i++) { + if (ngx_cmp_sockaddr(u.addrs[n].sockaddr, u.addrs[n].socklen, + u.addrs[i].sockaddr, u.addrs[i].socklen, 0) + == NGX_OK) + { + goto next; + } + } + lsopt.sockaddr = u.addrs[n].sockaddr; lsopt.socklen = u.addrs[n].socklen; lsopt.addr_text = u.addrs[n].name; @@ -4297,6 +4307,9 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) { return NGX_CONF_ERROR; } + + next: + continue; } return NGX_CONF_OK; diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -308,7 +308,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx ngx_str_t *value, size; ngx_url_t u; ngx_uint_t i, n, m; - ngx_mail_listen_t *ls, *als; + ngx_mail_listen_t *ls, *als, *nls; ngx_mail_module_t *module; ngx_mail_core_main_conf_t *cmcf; @@ -333,7 +333,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module); - ls = ngx_array_push_n(&cmcf->listen, u.naddrs); + ls = ngx_array_push(&cmcf->listen); if (ls == NULL) { return NGX_CONF_ERROR; } @@ -568,20 +568,40 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx return NGX_CONF_ERROR; } - als = cmcf->listen.elts; + for (n = 0; n < u.naddrs; n++) { - for (n = 0; n < u.naddrs; n++) { - ls[n] = ls[0]; + for (i = 0; i < n; i++) { + if (ngx_cmp_sockaddr(u.addrs[n].sockaddr, u.addrs[n].socklen, + u.addrs[i].sockaddr, u.addrs[i].socklen, 0) + == NGX_OK) + { + goto next; + } + } - ls[n].sockaddr = u.addrs[n].sockaddr; - ls[n].socklen = u.addrs[n].socklen; - ls[n].addr_text = u.addrs[n].name; - ls[n].wildcard = ngx_inet_wildcard(ls[n].sockaddr); + if (n != 0) { + nls = ngx_array_push(&cmcf->listen); + if (nls == NULL) { + return NGX_CONF_ERROR; + } + + *nls = *ls; - for (i = 0; i < cmcf->listen.nelts - u.naddrs + n; i++) { + } else { + nls = ls; + } + + nls->sockaddr = u.addrs[n].sockaddr; + nls->socklen = u.addrs[n].socklen; + nls->addr_text = u.addrs[n].name; + nls->wildcard = ngx_inet_wildcard(nls->sockaddr); + + als = cmcf->listen.elts; + + for (i = 0; i < cmcf->listen.nelts - 1; i++) { if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen, - ls[n].sockaddr, ls[n].socklen, 1) + nls->sockaddr, nls->socklen, 1) != NGX_OK) { continue; @@ -589,9 +609,12 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate \"%V\" address and port pair", - &ls[n].addr_text); + &nls->addr_text); return NGX_CONF_ERROR; } + + next: + continue; } return NGX_CONF_OK; diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c +++ b/src/stream/ngx_stream_core_module.c @@ -578,7 +578,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n ngx_str_t *value, size; ngx_url_t u; ngx_uint_t i, n, backlog; - ngx_stream_listen_t *ls, *als; + ngx_stream_listen_t *ls, *als, *nls; ngx_stream_core_main_conf_t *cmcf; cscf->listen = 1; @@ -602,7 +602,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); - ls = ngx_array_push_n(&cmcf->listen, u.naddrs); + ls = ngx_array_push(&cmcf->listen); if (ls == NULL) { return NGX_CONF_ERROR; } @@ -886,23 +886,43 @@ ngx_stream_core_listen(ngx_conf_t *cf, n #endif } - als = cmcf->listen.elts; + for (n = 0; n < u.naddrs; n++) { - for (n = 0; n < u.naddrs; n++) { - ls[n] = ls[0]; + for (i = 0; i < n; i++) { + if (ngx_cmp_sockaddr(u.addrs[n].sockaddr, u.addrs[n].socklen, + u.addrs[i].sockaddr, u.addrs[i].socklen, 0) + == NGX_OK) + { + goto next; + } + } - ls[n].sockaddr = u.addrs[n].sockaddr; - ls[n].socklen = u.addrs[n].socklen; - ls[n].addr_text = u.addrs[n].name; - ls[n].wildcard = ngx_inet_wildcard(ls[n].sockaddr); + if (n != 0) { + nls = ngx_array_push(&cmcf->listen); + if (nls == NULL) { + return NGX_CONF_ERROR; + } + + *nls = *ls; - for (i = 0; i < cmcf->listen.nelts - u.naddrs + n; i++) { - if (ls[n].type != als[i].type) { + } else { + nls = ls; + } + + nls->sockaddr = u.addrs[n].sockaddr; + nls->socklen = u.addrs[n].socklen; + nls->addr_text = u.addrs[n].name; + nls->wildcard = ngx_inet_wildcard(nls->sockaddr); + + als = cmcf->listen.elts; + + for (i = 0; i < cmcf->listen.nelts - 1; i++) { + if (nls->type != als[i].type) { continue; } if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen, - ls[n].sockaddr, ls[n].socklen, 1) + nls->sockaddr, nls->socklen, 1) != NGX_OK) { continue; @@ -910,9 +930,12 @@ ngx_stream_core_listen(ngx_conf_t *cf, n ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate \"%V\" address and port pair", - &ls[n].addr_text); + &nls->addr_text); return NGX_CONF_ERROR; } + + next: + continue; } return NGX_CONF_OK; -- Maxim Dounin http://mdounin.ru/ _______________________________________________ nginx-devel mailing list -- nginx-devel@nginx.org To unsubscribe send an email to nginx-devel-le...@nginx.org