[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#780524: marked as done (libresolv res_init() does not correctly initialize internals)



Your message dated Sun, 19 Nov 2017 13:41:05 +0100
with message-id <20171119124105.jv6nqupn7ycelh5v@aurel32.net>
and subject line Re: Bug#780524: libresolv res_init() does not correctly initialize internals
has caused the Debian Bug report #780524,
regarding libresolv res_init() does not correctly initialize internals
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
780524: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=780524
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: glibc
Severity: normal



As reported here: https://sourceware.org/bugzilla/show_bug.cgi?id=18126

The bug, however, is not in the sourceware sourcecode, but in the eglibc
one.

https://sourceware.org/git/?p=glibc.git;a=blob;f=resolv/res_libc.c;h=ee3fa2114b7051b86f6f9676f1151d1435dedb9d;hb=HEAD#l97

Contrary to what one would think, res_init() does not correctly
inititialize the internals for further use by the libresolv family, and
others.

When you call res_init(), it correctly "keeps" these:

        if (!_res.retrans)
                _res.retrans = RES_TIMEOUT;
        if (!_res.retry)
                _res.retry = 4;
        if (!(_res.options & RES_INIT))
                _res.options = RES_DEFAULT;
        else if (_res.nscount > 0)
                __res_iclose (&_res, true); /* Close any VC sockets. */

then calls __res_vinit():

        return (__res_vinit(&_res, 1));

However, programs that use the libresolv family and others, use the
hidden function, "__res_maybe_init".

__res_maybe_init determines if res_init(__res_vinit()) needs to be
called or not.

It does this:

        static time_t last_mtime;
        struct stat statbuf;
        int ret;

        if (resp->options & RES_INIT) {
                ret = stat (_PATH_RESCONF, &statbuf);
                __libc_lock_lock (lock);
                if ((ret == 0) && (last_mtime != statbuf.st_mtime)) {
                        last_mtime = statbuf.st_mtime;
                        atomicinc (__res_initstamp);
                }
                __libc_lock_unlock (lock);
                if (__res_initstamp != resp->_u._ext.initstamp) {
                        if (resp->nscount > 0)
                                __res_iclose (resp, true);
                        return __res_vinit (resp, 1);
                }
                return 0;

Since the internals have been initialized by res_init(), we don't need
to reinitalize, normally. The program checks if we do need to
reinitalize, such as due to the change in modifcation date of
/etc/resolv.conf.

However, "last_mtime" is never set when using res_init(), so upon the
first run of __res_maybe_init(), it will always run __res_vinit(). This
will wipe all changes except for the ones that are kept, mentioned above.

"last_mtime" should be taken into consideration and handled, when
calling res_init().

(for reference)
Only these are kept on res_init(), and thus are only kept with the first
call to __res_maybe_init:
        int retrans; /* retransmition time interval */
        int retry; /* number of times to retransmit */
        u_long options; /* option flags - see below. */

These are wiped, due to this bug:

        int nscount; /* number of name servers */
        struct sockaddr_in
                nsaddr_list[MAXNS]; /* address of name server */
# define nsaddr nsaddr_list[0] /* for backward compatibility */
        u_short id; /* current message id */
        /* 2 byte hole here. */
        char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */
        char defdname[256]; /* default domain (deprecated) */
        u_long pfcode; /* RES_PRF_ flags - see below. */
        unsigned ndots:4; /* threshold for initial abs. query */
        unsigned nsort:4; /* number of elements in sort_list[] */
        unsigned ipv6_unavail:1; /* connecting to IPv6 server failed */


Here is a link to the eglibc source:
http://www.eglibc.org/cgi-bin/viewvc.cgi/branches/eglibc-2_19/libc/resolv/res_libc.c?view=markup


The bug was introduced into Debian here:
https://lists.debian.org/debian-glibc/2014/05/msg00171.html


tl;dr: since res_init() does not set 'last_mtime', it does not
initialize the internals, for libresolv to be used by the likes of
getaddrinfo, gethostbyname, res_query, etc. etc..



Thanks,
-- 
-- Joshua Rogers <https://internot.info/>

Attachment: signature.asc
Description: OpenPGP digital signature


--- End Message ---
--- Begin Message ---
Version: 2.26-0experimental0

On 2015-03-16 02:57, Joshua Rogers wrote:
> Package: glibc
> Severity: normal
> 
> 
> 
> As reported here: https://sourceware.org/bugzilla/show_bug.cgi?id=18126
> 
> The bug, however, is not in the sourceware sourcecode, but in the eglibc
> one.
> 
> https://sourceware.org/git/?p=glibc.git;a=blob;f=resolv/res_libc.c;h=ee3fa2114b7051b86f6f9676f1151d1435dedb9d;hb=HEAD#l97
> 
> Contrary to what one would think, res_init() does not correctly
> inititialize the internals for further use by the libresolv family, and
> others.

Support for reloading resolv.conf when it changes has been added
upstream to glibc 2.26. The debian package for this version therefore
doesn't use the patch you mention coming from eglibc, which fixes the
problem you reported. I am therefore marking the bug as fixed for this
version.

Aurelien

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

Attachment: signature.asc
Description: PGP signature


--- End Message ---

Reply to: