[PATCH] Filtering duplicate addresses in listen (ticket #2400)
Sergey Kandaurov
pluknet at nginx.com
Wed Nov 23 15:03:32 UTC 2022
> 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.
--
Sergey Kandaurov
More information about the nginx-devel
mailing list