[PATCH] Filtering duplicate addresses in listen (ticket #2400)
Maxim Dounin
mdounin at mdounin.ru
Thu Nov 24 18:25:11 UTC 2022
Hello!
On Wed, Nov 23, 2022 at 07:03:32PM +0400, Sergey Kandaurov wrote:
>
> > On 23 Nov 2022, at 18:46, Maxim Dounin <mdounin at mdounin.ru> wrote:
> >
> > 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 <mdounin at 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 <mdounin at 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
> >
>
> [..]
>
> Looks good.
Pushed to http://mdounin.ru/hg/nginx, thanks.
--
Maxim Dounin
http://mdounin.ru/
More information about the nginx-devel
mailing list