Message ID | 20211125201825.22354-1-ps.report@gmx.net |
---|---|
State | Accepted |
Headers | show |
Series | [uclibc-ng-devel,v1] libc/inet/resolv: fix per thread rest_state access | expand |
On Thu, 25 Nov 2021 21:18:25 +0100, Peter Seiderer <ps.report@gmx.net> wrote: > - use the provided __res_state() method instead of direct access > to struct __res_state pointer &_res/*__resp > > - change the __UCLIBC_HAS_TLS__ protected __res_state() implementation > to the one where the comment 'When threaded, _res may be a per-thread > variable.' indicates this should be used with threads/TLS enabled > > Fixes the following segfaults with buildroot raspberrypi3_64_defconfig > (uclibc, -Os, Note: runs fine using the raspberrypi3_defconfig): > > $ /usr/sbin/ntpd -n -d > 1970-01-01T00:01:49 ntpd[249]: INIT: ntpd ntpsec-1.2.0 2021-11-03T20:39:50Z: Starting > 1970-01-01T00:01:49 ntpd[249]: INIT: Command line: /usr/sbin/ntpd -n -d > 1970-01-01T00:01:49 ntpd[249]: INIT: precision = 7.240 usec (-17) > 1970-01-01T00:01:49 ntpd[249]: INIT: successfully locked into RAM > 1970-01-01T00:01:49 ntpd[249]: CONFIG: readconfig: parsing file: /etc/ntp.conf > 1970-01-01T00:01:49 ntpd[249]: CONFIG: restrict nopeer ignored > 1970-01-01T00:01:49 ntpd[249]: INIT: Using SO_TIMESTAMPNS > 1970-01-01T00:01:49 ntpd[249]: IO: Listen and drop on 0 v6wildcard [::]:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listen and drop on 1 v4wildcard 0.0.0.0:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 2 lo 127.0.0.1:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 3 eth0 172.16.0.30:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 4 lo [::1]:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 5 eth0 [fe80::ba27:ebff:fea6:340%2]:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listening on routing socket on fd #22 for interface updates > 1970-01-01T00:01:50 ntpd[249]: SYNC: Found 10 servers, suggest minsane at least 3 > 1970-01-01T00:01:50 ntpd[249]: INIT: MRU 10922 entries, 13 hash bits, 65536 bytes > 1970-01-01T00:01:50 ntpd[249]: statistics directory /var/NTP/ does not exist or is unwriteable, error No such file or directory > 1970-01-01T00:01:51 ntpd[249]: DNS: dns_probe: 0.pool.ntp.org, cast_flags:8, flags:101 > Segmentation fault (core dumped) > > $ ./host/bin/aarch64-buildroot-linux-uclibc-gdb ./build/ntpsec-1_2_0/build/main/ntpd/ntpd core > Core was generated by `/usr/sbin/ntpd -n -d'. > Program terminated with signal SIGSEGV, Segmentation fault. > (gdb) where > #0 0x0000007f8ff1f150 in res_sync_func () at libc/inet/resolv.c:3356 > #1 0x0000007f8ff1c468 in __open_nameservers () at libc/inet/resolv.c:949 > #2 0x0000007f8ff1b498 in __dns_lookup (name=0x55943c67f0 "0.pool.ntp.org", > type=1, outpacket=0x7f8fe91c48, a=0x7f8fe91c08) at libc/inet/resolv.c:1134 > #3 0x0000007f8ff1d744 in __GI_gethostbyname_r ( > name=0x55943c67f0 "0.pool.ntp.org", result_buf=0x7f8fe92628, > buf=0x7f8fe91d90 "", buflen=992, result=0x7f8fe92670, > h_errnop=0x7f8fe92668) at libc/inet/resolv.c:1966 > #4 0x0000007f8ff1d9a0 in __GI_gethostbyname2_r ( > name=0x55943c67f0 "0.pool.ntp.org", family=2, result_buf=0x7f8fe92628, > buf=0x7f8fe91d70 "0.pool.ntp.org", buflen=1024, result=0x7f8fe92670, > h_errnop=0x7f8fe92668) at libc/inet/resolv.c:2065 > #5 0x0000007f8ff16924 in gaih_inet (name=0x55943c67f0 "0.pool.ntp.org", > service=0x7f8fe92828, req=0x7f8fe92890, pai=0x7f8fe92838) > at libc/inet/getaddrinfo.c:596 > #6 0x0000007f8ff17624 in __GI_getaddrinfo ( > name=0x55943c67f0 "0.pool.ntp.org", > service=0x5582eb8acd "\377H\213D$\bL\211\367H\213\260\270", > hints=0x7f8fe92890, pai=0x5582ee1bf8) at libc/inet/getaddrinfo.c:957 > #7 0x0000005582ea60f4 in _start () > (gdb) p _res > $1 = {options = 0, nsaddr_list = {{sin_family = 0, sin_port = 0, sin_addr = { > s_addr = 0}, sin_zero = "\000\000\000\000\000\000\000"}, { > sin_family = 0, sin_port = 0, sin_addr = {s_addr = 0}, > sin_zero = "\000\000\000\000\000\000\000"}, {sin_family = 0, > sin_port = 0, sin_addr = {s_addr = 0}, > sin_zero = "\000\000\000\000\000\000\000"}}, dnsrch = {0x0, 0x0, 0x0, > 0x0, 0x0, 0x0, 0x0}, nscount = 0 '\000', ndots = 0 '\000', > retrans = 0 '\000', retry = 0 '\000', defdname = '\000' <repeats 255 times>, > nsort = 0 '\000', pfcode = 0, id = 0, res_h_errno = 0, sort_list = {{addr = { > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}}, _u = { > _ext = {nsaddrs = {0x0, 0x0, 0x0}, nscount = 0 '\000', nstimes = {0, 0, > 0}, nssocks = {0, 0, 0}, nscount6 = 0, nsinit = 0}}} > (gdb) p &_res > $2 = (struct __res_state *) 0x7f8ff8fd98 <_res> > (gdb) p rp > $3 = (struct __res_state *) 0x7fffffffff > > And the following uclibc code at libc/inet/resolv.c:3356: > > 3345 static void res_sync_func(void) > 3346 { > 3347 struct __res_state *rp = &(_res); > 3348 int n; > 3349 > 3350 /* If we didn't get malloc failure earlier... */ > 3351 if (__nameserver != (void*) &__local_nameserver) { > 3352 /* TODO: > 3353 * if (__nameservers < rp->nscount) - try to grow __nameserver[]? > 3354 */ > 3355 #ifdef __UCLIBC_HAS_IPV6__ > 3356 if (__nameservers > rp->_u._ext.nscount) > 3357 __nameservers = rp->_u._ext.nscount; > 3358 n = __nameservers; > > The special thing about ntpsec is the DNS lookup in an extra thread > and/or the call to res_init(), see ntpsec-1_2_0/ntpd/ntp_dns.c: > > 69 msyslog(LOG_INFO, "DNS: dns_probe: %s, cast_flags:%x, flags:%x%s", > 70 hostname, pp->cast_flags, pp->cfg.flags, busy); > 71 if (NULL != active) /* normally redundant */ > 72 return false; > 73 > 74 active = pp; > 75 > 76 sigfillset(&block_mask); > 77 pthread_sigmask(SIG_BLOCK, &block_mask, &saved_sig_mask); > 78 rc = pthread_create(&worker, NULL, dns_lookup, pp); > > and > > 165 static void* dns_lookup(void* arg) > 166 { > 167 struct peer *pp = (struct peer *) arg; > 168 struct addrinfo hints; > 169 > 170 #ifdef HAVE_SECCOMP_H > 171 setup_SIGSYS_trap(); /* enable trap for this thread */ > 172 #endif > 173 > 174 #ifdef HAVE_RES_INIT > 175 /* Reload DNS servers from /etc/resolv.conf in case DHCP has updated it. > 176 * We only need to do this occasionally, but it's not expensive > 177 * and simpler to do it every time than it is to figure out when > 178 * to do it. > 179 * This res_init() covers NTS too. > 180 */ > 181 res_init(); > 182 #endif > 183 > 184 if (pp->cfg.flags & FLAG_NTS) { > 185 #ifndef DISABLE_NTS > 186 nts_probe(pp); > 187 #endif > 188 } else { > 189 ZERO(hints); > 190 hints.ai_protocol = IPPROTO_UDP; > 191 hints.ai_socktype = SOCK_DGRAM; > 192 hints.ai_family = AF(&pp->srcadr); > 193 gai_rc = getaddrinfo(pp->hostname, NTP_PORTA, &hints, &answer); > 194 } > > $ /usr/lib/uclibc-ng-test/test/inet/tst-res > Segmentation fault (core dumped) > > $ ./host/bin/aarch64-buildroot-linux-uclibc-gdb ./build/uclibc-ng-test-0844445e7358eb10e716155b55b0fb23e88d644a/test/inet/tst-res core > Core was generated by `/usr/lib/uclibc-ng-test/test/inet/tst-res'. > Program terminated with signal SIGSEGV, Segmentation fault. > (gdb) where > #0 __GI___res_init () at libc/inet/resolv.c:3514 > #1 0x0000005591e507e4 in main (argc=<optimized out>, argv=<optimized out>) > at tst-res.c:20 > > Signed-off-by: Peter Seiderer <ps.report@gmx.net> Forgot to link to the original buildroot/uclibc-ng error reports: https://lore.kernel.org/buildroot/20211028230131.5f50d6e7@gmx.net/ https://www.mail-archive.com/devel@uclibc-ng.org/msg01085.html Regards, Peter > --- > include/resolv.h | 2 +- > libc/inet/resolv.c | 4 ++-- > 2 files changed, 3 insertions(+), 3 deletions(-) > > diff --git a/include/resolv.h b/include/resolv.h > index 485b8db98..2a82641a4 100644 > --- a/include/resolv.h > +++ b/include/resolv.h > @@ -457,7 +457,7 @@ __END_DECLS > # ifndef NOT_IN_libc > # define __resp __libc_resp > # endif > -# define _res (*__resp) > +# define _res (*__res_state()) > extern __thread struct __res_state *__resp attribute_tls_model_ie; > # endif > # else > diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c > index 8bbd7c7cd..cf170fba6 100644 > --- a/libc/inet/resolv.c > +++ b/libc/inet/resolv.c > @@ -3344,7 +3344,7 @@ libc_hidden_def(dn_skipname) > /* Will be called under __resolv_lock. */ > static void res_sync_func(void) > { > - struct __res_state *rp = &(_res); > + struct __res_state *rp = __res_state(); > int n; > > /* If we didn't get malloc failure earlier... */ > @@ -3896,7 +3896,7 @@ res_ninit(res_state statp) > #endif /* L_res_init */ > > #ifdef L_res_state > -# if defined __UCLIBC_HAS_TLS__ > +# if !defined __UCLIBC_HAS_TLS__ > struct __res_state * > __res_state (void) > {
Hi Peter, thanks applied! best regards Waldemar Peter Seiderer wrote, > - use the provided __res_state() method instead of direct access > to struct __res_state pointer &_res/*__resp > > - change the __UCLIBC_HAS_TLS__ protected __res_state() implementation > to the one where the comment 'When threaded, _res may be a per-thread > variable.' indicates this should be used with threads/TLS enabled > > Fixes the following segfaults with buildroot raspberrypi3_64_defconfig > (uclibc, -Os, Note: runs fine using the raspberrypi3_defconfig): > > $ /usr/sbin/ntpd -n -d > 1970-01-01T00:01:49 ntpd[249]: INIT: ntpd ntpsec-1.2.0 2021-11-03T20:39:50Z: Starting > 1970-01-01T00:01:49 ntpd[249]: INIT: Command line: /usr/sbin/ntpd -n -d > 1970-01-01T00:01:49 ntpd[249]: INIT: precision = 7.240 usec (-17) > 1970-01-01T00:01:49 ntpd[249]: INIT: successfully locked into RAM > 1970-01-01T00:01:49 ntpd[249]: CONFIG: readconfig: parsing file: /etc/ntp.conf > 1970-01-01T00:01:49 ntpd[249]: CONFIG: restrict nopeer ignored > 1970-01-01T00:01:49 ntpd[249]: INIT: Using SO_TIMESTAMPNS > 1970-01-01T00:01:49 ntpd[249]: IO: Listen and drop on 0 v6wildcard [::]:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listen and drop on 1 v4wildcard 0.0.0.0:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 2 lo 127.0.0.1:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 3 eth0 172.16.0.30:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 4 lo [::1]:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 5 eth0 [fe80::ba27:ebff:fea6:340%2]:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listening on routing socket on fd #22 for interface updates > 1970-01-01T00:01:50 ntpd[249]: SYNC: Found 10 servers, suggest minsane at least 3 > 1970-01-01T00:01:50 ntpd[249]: INIT: MRU 10922 entries, 13 hash bits, 65536 bytes > 1970-01-01T00:01:50 ntpd[249]: statistics directory /var/NTP/ does not exist or is unwriteable, error No such file or directory > 1970-01-01T00:01:51 ntpd[249]: DNS: dns_probe: 0.pool.ntp.org, cast_flags:8, flags:101 > Segmentation fault (core dumped) > > $ ./host/bin/aarch64-buildroot-linux-uclibc-gdb ./build/ntpsec-1_2_0/build/main/ntpd/ntpd core > Core was generated by `/usr/sbin/ntpd -n -d'. > Program terminated with signal SIGSEGV, Segmentation fault. > (gdb) where > #0 0x0000007f8ff1f150 in res_sync_func () at libc/inet/resolv.c:3356 > #1 0x0000007f8ff1c468 in __open_nameservers () at libc/inet/resolv.c:949 > #2 0x0000007f8ff1b498 in __dns_lookup (name=0x55943c67f0 "0.pool.ntp.org", > type=1, outpacket=0x7f8fe91c48, a=0x7f8fe91c08) at libc/inet/resolv.c:1134 > #3 0x0000007f8ff1d744 in __GI_gethostbyname_r ( > name=0x55943c67f0 "0.pool.ntp.org", result_buf=0x7f8fe92628, > buf=0x7f8fe91d90 "", buflen=992, result=0x7f8fe92670, > h_errnop=0x7f8fe92668) at libc/inet/resolv.c:1966 > #4 0x0000007f8ff1d9a0 in __GI_gethostbyname2_r ( > name=0x55943c67f0 "0.pool.ntp.org", family=2, result_buf=0x7f8fe92628, > buf=0x7f8fe91d70 "0.pool.ntp.org", buflen=1024, result=0x7f8fe92670, > h_errnop=0x7f8fe92668) at libc/inet/resolv.c:2065 > #5 0x0000007f8ff16924 in gaih_inet (name=0x55943c67f0 "0.pool.ntp.org", > service=0x7f8fe92828, req=0x7f8fe92890, pai=0x7f8fe92838) > at libc/inet/getaddrinfo.c:596 > #6 0x0000007f8ff17624 in __GI_getaddrinfo ( > name=0x55943c67f0 "0.pool.ntp.org", > service=0x5582eb8acd "\377H\213D$\bL\211\367H\213\260\270", > hints=0x7f8fe92890, pai=0x5582ee1bf8) at libc/inet/getaddrinfo.c:957 > #7 0x0000005582ea60f4 in _start () > (gdb) p _res > $1 = {options = 0, nsaddr_list = {{sin_family = 0, sin_port = 0, sin_addr = { > s_addr = 0}, sin_zero = "\000\000\000\000\000\000\000"}, { > sin_family = 0, sin_port = 0, sin_addr = {s_addr = 0}, > sin_zero = "\000\000\000\000\000\000\000"}, {sin_family = 0, > sin_port = 0, sin_addr = {s_addr = 0}, > sin_zero = "\000\000\000\000\000\000\000"}}, dnsrch = {0x0, 0x0, 0x0, > 0x0, 0x0, 0x0, 0x0}, nscount = 0 '\000', ndots = 0 '\000', > retrans = 0 '\000', retry = 0 '\000', defdname = '\000' <repeats 255 times>, > nsort = 0 '\000', pfcode = 0, id = 0, res_h_errno = 0, sort_list = {{addr = { > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}}, _u = { > _ext = {nsaddrs = {0x0, 0x0, 0x0}, nscount = 0 '\000', nstimes = {0, 0, > 0}, nssocks = {0, 0, 0}, nscount6 = 0, nsinit = 0}}} > (gdb) p &_res > $2 = (struct __res_state *) 0x7f8ff8fd98 <_res> > (gdb) p rp > $3 = (struct __res_state *) 0x7fffffffff > > And the following uclibc code at libc/inet/resolv.c:3356: > > 3345 static void res_sync_func(void) > 3346 { > 3347 struct __res_state *rp = &(_res); > 3348 int n; > 3349 > 3350 /* If we didn't get malloc failure earlier... */ > 3351 if (__nameserver != (void*) &__local_nameserver) { > 3352 /* TODO: > 3353 * if (__nameservers < rp->nscount) - try to grow __nameserver[]? > 3354 */ > 3355 #ifdef __UCLIBC_HAS_IPV6__ > 3356 if (__nameservers > rp->_u._ext.nscount) > 3357 __nameservers = rp->_u._ext.nscount; > 3358 n = __nameservers; > > The special thing about ntpsec is the DNS lookup in an extra thread > and/or the call to res_init(), see ntpsec-1_2_0/ntpd/ntp_dns.c: > > 69 msyslog(LOG_INFO, "DNS: dns_probe: %s, cast_flags:%x, flags:%x%s", > 70 hostname, pp->cast_flags, pp->cfg.flags, busy); > 71 if (NULL != active) /* normally redundant */ > 72 return false; > 73 > 74 active = pp; > 75 > 76 sigfillset(&block_mask); > 77 pthread_sigmask(SIG_BLOCK, &block_mask, &saved_sig_mask); > 78 rc = pthread_create(&worker, NULL, dns_lookup, pp); > > and > > 165 static void* dns_lookup(void* arg) > 166 { > 167 struct peer *pp = (struct peer *) arg; > 168 struct addrinfo hints; > 169 > 170 #ifdef HAVE_SECCOMP_H > 171 setup_SIGSYS_trap(); /* enable trap for this thread */ > 172 #endif > 173 > 174 #ifdef HAVE_RES_INIT > 175 /* Reload DNS servers from /etc/resolv.conf in case DHCP has updated it. > 176 * We only need to do this occasionally, but it's not expensive > 177 * and simpler to do it every time than it is to figure out when > 178 * to do it. > 179 * This res_init() covers NTS too. > 180 */ > 181 res_init(); > 182 #endif > 183 > 184 if (pp->cfg.flags & FLAG_NTS) { > 185 #ifndef DISABLE_NTS > 186 nts_probe(pp); > 187 #endif > 188 } else { > 189 ZERO(hints); > 190 hints.ai_protocol = IPPROTO_UDP; > 191 hints.ai_socktype = SOCK_DGRAM; > 192 hints.ai_family = AF(&pp->srcadr); > 193 gai_rc = getaddrinfo(pp->hostname, NTP_PORTA, &hints, &answer); > 194 } > > $ /usr/lib/uclibc-ng-test/test/inet/tst-res > Segmentation fault (core dumped) > > $ ./host/bin/aarch64-buildroot-linux-uclibc-gdb ./build/uclibc-ng-test-0844445e7358eb10e716155b55b0fb23e88d644a/test/inet/tst-res core > Core was generated by `/usr/lib/uclibc-ng-test/test/inet/tst-res'. > Program terminated with signal SIGSEGV, Segmentation fault. > (gdb) where > #0 __GI___res_init () at libc/inet/resolv.c:3514 > #1 0x0000005591e507e4 in main (argc=<optimized out>, argv=<optimized out>) > at tst-res.c:20 > > Signed-off-by: Peter Seiderer <ps.report@gmx.net> > --- > include/resolv.h | 2 +- > libc/inet/resolv.c | 4 ++-- > 2 files changed, 3 insertions(+), 3 deletions(-) > > diff --git a/include/resolv.h b/include/resolv.h > index 485b8db98..2a82641a4 100644 > --- a/include/resolv.h > +++ b/include/resolv.h > @@ -457,7 +457,7 @@ __END_DECLS > # ifndef NOT_IN_libc > # define __resp __libc_resp > # endif > -# define _res (*__resp) > +# define _res (*__res_state()) > extern __thread struct __res_state *__resp attribute_tls_model_ie; > # endif > # else > diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c > index 8bbd7c7cd..cf170fba6 100644 > --- a/libc/inet/resolv.c > +++ b/libc/inet/resolv.c > @@ -3344,7 +3344,7 @@ libc_hidden_def(dn_skipname) > /* Will be called under __resolv_lock. */ > static void res_sync_func(void) > { > - struct __res_state *rp = &(_res); > + struct __res_state *rp = __res_state(); > int n; > > /* If we didn't get malloc failure earlier... */ > @@ -3896,7 +3896,7 @@ res_ninit(res_state statp) > #endif /* L_res_init */ > > #ifdef L_res_state > -# if defined __UCLIBC_HAS_TLS__ > +# if !defined __UCLIBC_HAS_TLS__ > struct __res_state * > __res_state (void) > { > -- > 2.33.1 > > _______________________________________________ > devel mailing list -- devel@uclibc-ng.org > To unsubscribe send an email to devel-leave@uclibc-ng.org >
Hi Peter, sorry about coming so late up with a regression. I get following failure when compiling the defconfig stm32f429_disco_xip_defconfig in buildroot with your patch: In file included from libc/inet/_res_state.c:8: libc/inet/resolv.c: In function '__res_state': libc/inet/resolv.c:3903:15: error: '__resp' undeclared (first use in this function); did you mean '_res'? 3903 | return __resp; | ^~~~~~ | _res libc/inet/resolv.c:3903:15: note: each undeclared identifier is reported only once for each function it appears in libc/inet/resolv.c:3904:1: warning: control reaches end of non-void function [-Wreturn-type] 3904 | } | ^ make[1]: *** [Makerules:368: libc/inet/_res_state.o] Error 1 make[1]: Leaving directory '/home/wbx/buildroot/output/build/uclibc-1.0.39' make: *** [package/pkg-generic.mk:295: /home/wbx/buildroot/output/build/uclibc-1.0.39/.stamp_built] Error 2 In this case Linuxthreads are used, because the target is noMMU and FLAT binary format. Any idea? best regards Waldemar Peter Seiderer wrote, > - use the provided __res_state() method instead of direct access > to struct __res_state pointer &_res/*__resp > > - change the __UCLIBC_HAS_TLS__ protected __res_state() implementation > to the one where the comment 'When threaded, _res may be a per-thread > variable.' indicates this should be used with threads/TLS enabled > > Fixes the following segfaults with buildroot raspberrypi3_64_defconfig > (uclibc, -Os, Note: runs fine using the raspberrypi3_defconfig): > > $ /usr/sbin/ntpd -n -d > 1970-01-01T00:01:49 ntpd[249]: INIT: ntpd ntpsec-1.2.0 2021-11-03T20:39:50Z: Starting > 1970-01-01T00:01:49 ntpd[249]: INIT: Command line: /usr/sbin/ntpd -n -d > 1970-01-01T00:01:49 ntpd[249]: INIT: precision = 7.240 usec (-17) > 1970-01-01T00:01:49 ntpd[249]: INIT: successfully locked into RAM > 1970-01-01T00:01:49 ntpd[249]: CONFIG: readconfig: parsing file: /etc/ntp.conf > 1970-01-01T00:01:49 ntpd[249]: CONFIG: restrict nopeer ignored > 1970-01-01T00:01:49 ntpd[249]: INIT: Using SO_TIMESTAMPNS > 1970-01-01T00:01:49 ntpd[249]: IO: Listen and drop on 0 v6wildcard [::]:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listen and drop on 1 v4wildcard 0.0.0.0:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 2 lo 127.0.0.1:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 3 eth0 172.16.0.30:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 4 lo [::1]:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 5 eth0 [fe80::ba27:ebff:fea6:340%2]:123 > 1970-01-01T00:01:49 ntpd[249]: IO: Listening on routing socket on fd #22 for interface updates > 1970-01-01T00:01:50 ntpd[249]: SYNC: Found 10 servers, suggest minsane at least 3 > 1970-01-01T00:01:50 ntpd[249]: INIT: MRU 10922 entries, 13 hash bits, 65536 bytes > 1970-01-01T00:01:50 ntpd[249]: statistics directory /var/NTP/ does not exist or is unwriteable, error No such file or directory > 1970-01-01T00:01:51 ntpd[249]: DNS: dns_probe: 0.pool.ntp.org, cast_flags:8, flags:101 > Segmentation fault (core dumped) > > $ ./host/bin/aarch64-buildroot-linux-uclibc-gdb ./build/ntpsec-1_2_0/build/main/ntpd/ntpd core > Core was generated by `/usr/sbin/ntpd -n -d'. > Program terminated with signal SIGSEGV, Segmentation fault. > (gdb) where > #0 0x0000007f8ff1f150 in res_sync_func () at libc/inet/resolv.c:3356 > #1 0x0000007f8ff1c468 in __open_nameservers () at libc/inet/resolv.c:949 > #2 0x0000007f8ff1b498 in __dns_lookup (name=0x55943c67f0 "0.pool.ntp.org", > type=1, outpacket=0x7f8fe91c48, a=0x7f8fe91c08) at libc/inet/resolv.c:1134 > #3 0x0000007f8ff1d744 in __GI_gethostbyname_r ( > name=0x55943c67f0 "0.pool.ntp.org", result_buf=0x7f8fe92628, > buf=0x7f8fe91d90 "", buflen=992, result=0x7f8fe92670, > h_errnop=0x7f8fe92668) at libc/inet/resolv.c:1966 > #4 0x0000007f8ff1d9a0 in __GI_gethostbyname2_r ( > name=0x55943c67f0 "0.pool.ntp.org", family=2, result_buf=0x7f8fe92628, > buf=0x7f8fe91d70 "0.pool.ntp.org", buflen=1024, result=0x7f8fe92670, > h_errnop=0x7f8fe92668) at libc/inet/resolv.c:2065 > #5 0x0000007f8ff16924 in gaih_inet (name=0x55943c67f0 "0.pool.ntp.org", > service=0x7f8fe92828, req=0x7f8fe92890, pai=0x7f8fe92838) > at libc/inet/getaddrinfo.c:596 > #6 0x0000007f8ff17624 in __GI_getaddrinfo ( > name=0x55943c67f0 "0.pool.ntp.org", > service=0x5582eb8acd "\377H\213D$\bL\211\367H\213\260\270", > hints=0x7f8fe92890, pai=0x5582ee1bf8) at libc/inet/getaddrinfo.c:957 > #7 0x0000005582ea60f4 in _start () > (gdb) p _res > $1 = {options = 0, nsaddr_list = {{sin_family = 0, sin_port = 0, sin_addr = { > s_addr = 0}, sin_zero = "\000\000\000\000\000\000\000"}, { > sin_family = 0, sin_port = 0, sin_addr = {s_addr = 0}, > sin_zero = "\000\000\000\000\000\000\000"}, {sin_family = 0, > sin_port = 0, sin_addr = {s_addr = 0}, > sin_zero = "\000\000\000\000\000\000\000"}}, dnsrch = {0x0, 0x0, 0x0, > 0x0, 0x0, 0x0, 0x0}, nscount = 0 '\000', ndots = 0 '\000', > retrans = 0 '\000', retry = 0 '\000', defdname = '\000' <repeats 255 times>, > nsort = 0 '\000', pfcode = 0, id = 0, res_h_errno = 0, sort_list = {{addr = { > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}}, _u = { > _ext = {nsaddrs = {0x0, 0x0, 0x0}, nscount = 0 '\000', nstimes = {0, 0, > 0}, nssocks = {0, 0, 0}, nscount6 = 0, nsinit = 0}}} > (gdb) p &_res > $2 = (struct __res_state *) 0x7f8ff8fd98 <_res> > (gdb) p rp > $3 = (struct __res_state *) 0x7fffffffff > > And the following uclibc code at libc/inet/resolv.c:3356: > > 3345 static void res_sync_func(void) > 3346 { > 3347 struct __res_state *rp = &(_res); > 3348 int n; > 3349 > 3350 /* If we didn't get malloc failure earlier... */ > 3351 if (__nameserver != (void*) &__local_nameserver) { > 3352 /* TODO: > 3353 * if (__nameservers < rp->nscount) - try to grow __nameserver[]? > 3354 */ > 3355 #ifdef __UCLIBC_HAS_IPV6__ > 3356 if (__nameservers > rp->_u._ext.nscount) > 3357 __nameservers = rp->_u._ext.nscount; > 3358 n = __nameservers; > > The special thing about ntpsec is the DNS lookup in an extra thread > and/or the call to res_init(), see ntpsec-1_2_0/ntpd/ntp_dns.c: > > 69 msyslog(LOG_INFO, "DNS: dns_probe: %s, cast_flags:%x, flags:%x%s", > 70 hostname, pp->cast_flags, pp->cfg.flags, busy); > 71 if (NULL != active) /* normally redundant */ > 72 return false; > 73 > 74 active = pp; > 75 > 76 sigfillset(&block_mask); > 77 pthread_sigmask(SIG_BLOCK, &block_mask, &saved_sig_mask); > 78 rc = pthread_create(&worker, NULL, dns_lookup, pp); > > and > > 165 static void* dns_lookup(void* arg) > 166 { > 167 struct peer *pp = (struct peer *) arg; > 168 struct addrinfo hints; > 169 > 170 #ifdef HAVE_SECCOMP_H > 171 setup_SIGSYS_trap(); /* enable trap for this thread */ > 172 #endif > 173 > 174 #ifdef HAVE_RES_INIT > 175 /* Reload DNS servers from /etc/resolv.conf in case DHCP has updated it. > 176 * We only need to do this occasionally, but it's not expensive > 177 * and simpler to do it every time than it is to figure out when > 178 * to do it. > 179 * This res_init() covers NTS too. > 180 */ > 181 res_init(); > 182 #endif > 183 > 184 if (pp->cfg.flags & FLAG_NTS) { > 185 #ifndef DISABLE_NTS > 186 nts_probe(pp); > 187 #endif > 188 } else { > 189 ZERO(hints); > 190 hints.ai_protocol = IPPROTO_UDP; > 191 hints.ai_socktype = SOCK_DGRAM; > 192 hints.ai_family = AF(&pp->srcadr); > 193 gai_rc = getaddrinfo(pp->hostname, NTP_PORTA, &hints, &answer); > 194 } > > $ /usr/lib/uclibc-ng-test/test/inet/tst-res > Segmentation fault (core dumped) > > $ ./host/bin/aarch64-buildroot-linux-uclibc-gdb ./build/uclibc-ng-test-0844445e7358eb10e716155b55b0fb23e88d644a/test/inet/tst-res core > Core was generated by `/usr/lib/uclibc-ng-test/test/inet/tst-res'. > Program terminated with signal SIGSEGV, Segmentation fault. > (gdb) where > #0 __GI___res_init () at libc/inet/resolv.c:3514 > #1 0x0000005591e507e4 in main (argc=<optimized out>, argv=<optimized out>) > at tst-res.c:20 > > Signed-off-by: Peter Seiderer <ps.report@gmx.net> > --- > include/resolv.h | 2 +- > libc/inet/resolv.c | 4 ++-- > 2 files changed, 3 insertions(+), 3 deletions(-) > > diff --git a/include/resolv.h b/include/resolv.h > index 485b8db98..2a82641a4 100644 > --- a/include/resolv.h > +++ b/include/resolv.h > @@ -457,7 +457,7 @@ __END_DECLS > # ifndef NOT_IN_libc > # define __resp __libc_resp > # endif > -# define _res (*__resp) > +# define _res (*__res_state()) > extern __thread struct __res_state *__resp attribute_tls_model_ie; > # endif > # else > diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c > index 8bbd7c7cd..cf170fba6 100644 > --- a/libc/inet/resolv.c > +++ b/libc/inet/resolv.c > @@ -3344,7 +3344,7 @@ libc_hidden_def(dn_skipname) > /* Will be called under __resolv_lock. */ > static void res_sync_func(void) > { > - struct __res_state *rp = &(_res); > + struct __res_state *rp = __res_state(); > int n; > > /* If we didn't get malloc failure earlier... */ > @@ -3896,7 +3896,7 @@ res_ninit(res_state statp) > #endif /* L_res_init */ > > #ifdef L_res_state > -# if defined __UCLIBC_HAS_TLS__ > +# if !defined __UCLIBC_HAS_TLS__ > struct __res_state * > __res_state (void) > { > -- > 2.33.1 > > _______________________________________________ > devel mailing list -- devel@uclibc-ng.org > To unsubscribe send an email to devel-leave@uclibc-ng.org >
Hello Waldemar, On Fri, 21 Jan 2022 11:04:57 +0100, Waldemar Brodkorb <wbx@uclibc-ng.org> wrote: > Hi Peter, > > sorry about coming so late up with a regression. No problem... > > I get following failure when compiling the defconfig stm32f429_disco_xip_defconfig in buildroot with your patch: > > In file included from libc/inet/_res_state.c:8: > libc/inet/resolv.c: In function '__res_state': > libc/inet/resolv.c:3903:15: error: '__resp' undeclared (first use in this function); did you mean '_res'? > 3903 | return __resp; > | ^~~~~~ > | _res > libc/inet/resolv.c:3903:15: note: each undeclared identifier is reported only once for each function it appears in > libc/inet/resolv.c:3904:1: warning: control reaches end of non-void function [-Wreturn-type] > 3904 | } > | ^ > make[1]: *** [Makerules:368: libc/inet/_res_state.o] Error 1 > make[1]: Leaving directory '/home/wbx/buildroot/output/build/uclibc-1.0.39' > make: *** [package/pkg-generic.mk:295: /home/wbx/buildroot/output/build/uclibc-1.0.39/.stamp_built] Error 2 > > In this case Linuxthreads are used, because the target is noMMU and FLAT binary format. > > Any idea? No...not yet, but will take a look at it ;-) Regards, Peter > > best regards > Waldemar > > Peter Seiderer wrote, > > > - use the provided __res_state() method instead of direct access > > to struct __res_state pointer &_res/*__resp > > > > - change the __UCLIBC_HAS_TLS__ protected __res_state() implementation > > to the one where the comment 'When threaded, _res may be a per-thread > > variable.' indicates this should be used with threads/TLS enabled > > > > Fixes the following segfaults with buildroot raspberrypi3_64_defconfig > > (uclibc, -Os, Note: runs fine using the raspberrypi3_defconfig): > > > > $ /usr/sbin/ntpd -n -d > > 1970-01-01T00:01:49 ntpd[249]: INIT: ntpd ntpsec-1.2.0 2021-11-03T20:39:50Z: Starting > > 1970-01-01T00:01:49 ntpd[249]: INIT: Command line: /usr/sbin/ntpd -n -d > > 1970-01-01T00:01:49 ntpd[249]: INIT: precision = 7.240 usec (-17) > > 1970-01-01T00:01:49 ntpd[249]: INIT: successfully locked into RAM > > 1970-01-01T00:01:49 ntpd[249]: CONFIG: readconfig: parsing file: /etc/ntp.conf > > 1970-01-01T00:01:49 ntpd[249]: CONFIG: restrict nopeer ignored > > 1970-01-01T00:01:49 ntpd[249]: INIT: Using SO_TIMESTAMPNS > > 1970-01-01T00:01:49 ntpd[249]: IO: Listen and drop on 0 v6wildcard [::]:123 > > 1970-01-01T00:01:49 ntpd[249]: IO: Listen and drop on 1 v4wildcard 0.0.0.0:123 > > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 2 lo 127.0.0.1:123 > > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 3 eth0 172.16.0.30:123 > > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 4 lo [::1]:123 > > 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 5 eth0 [fe80::ba27:ebff:fea6:340%2]:123 > > 1970-01-01T00:01:49 ntpd[249]: IO: Listening on routing socket on fd #22 for interface updates > > 1970-01-01T00:01:50 ntpd[249]: SYNC: Found 10 servers, suggest minsane at least 3 > > 1970-01-01T00:01:50 ntpd[249]: INIT: MRU 10922 entries, 13 hash bits, 65536 bytes > > 1970-01-01T00:01:50 ntpd[249]: statistics directory /var/NTP/ does not exist or is unwriteable, error No such file or directory > > 1970-01-01T00:01:51 ntpd[249]: DNS: dns_probe: 0.pool.ntp.org, cast_flags:8, flags:101 > > Segmentation fault (core dumped) > > > > $ ./host/bin/aarch64-buildroot-linux-uclibc-gdb ./build/ntpsec-1_2_0/build/main/ntpd/ntpd core > > Core was generated by `/usr/sbin/ntpd -n -d'. > > Program terminated with signal SIGSEGV, Segmentation fault. > > (gdb) where > > #0 0x0000007f8ff1f150 in res_sync_func () at libc/inet/resolv.c:3356 > > #1 0x0000007f8ff1c468 in __open_nameservers () at libc/inet/resolv.c:949 > > #2 0x0000007f8ff1b498 in __dns_lookup (name=0x55943c67f0 "0.pool.ntp.org", > > type=1, outpacket=0x7f8fe91c48, a=0x7f8fe91c08) at libc/inet/resolv.c:1134 > > #3 0x0000007f8ff1d744 in __GI_gethostbyname_r ( > > name=0x55943c67f0 "0.pool.ntp.org", result_buf=0x7f8fe92628, > > buf=0x7f8fe91d90 "", buflen=992, result=0x7f8fe92670, > > h_errnop=0x7f8fe92668) at libc/inet/resolv.c:1966 > > #4 0x0000007f8ff1d9a0 in __GI_gethostbyname2_r ( > > name=0x55943c67f0 "0.pool.ntp.org", family=2, result_buf=0x7f8fe92628, > > buf=0x7f8fe91d70 "0.pool.ntp.org", buflen=1024, result=0x7f8fe92670, > > h_errnop=0x7f8fe92668) at libc/inet/resolv.c:2065 > > #5 0x0000007f8ff16924 in gaih_inet (name=0x55943c67f0 "0.pool.ntp.org", > > service=0x7f8fe92828, req=0x7f8fe92890, pai=0x7f8fe92838) > > at libc/inet/getaddrinfo.c:596 > > #6 0x0000007f8ff17624 in __GI_getaddrinfo ( > > name=0x55943c67f0 "0.pool.ntp.org", > > service=0x5582eb8acd "\377H\213D$\bL\211\367H\213\260\270", > > hints=0x7f8fe92890, pai=0x5582ee1bf8) at libc/inet/getaddrinfo.c:957 > > #7 0x0000005582ea60f4 in _start () > > (gdb) p _res > > $1 = {options = 0, nsaddr_list = {{sin_family = 0, sin_port = 0, sin_addr = { > > s_addr = 0}, sin_zero = "\000\000\000\000\000\000\000"}, { > > sin_family = 0, sin_port = 0, sin_addr = {s_addr = 0}, > > sin_zero = "\000\000\000\000\000\000\000"}, {sin_family = 0, > > sin_port = 0, sin_addr = {s_addr = 0}, > > sin_zero = "\000\000\000\000\000\000\000"}}, dnsrch = {0x0, 0x0, 0x0, > > 0x0, 0x0, 0x0, 0x0}, nscount = 0 '\000', ndots = 0 '\000', > > retrans = 0 '\000', retry = 0 '\000', defdname = '\000' <repeats 255 times>, > > nsort = 0 '\000', pfcode = 0, id = 0, res_h_errno = 0, sort_list = {{addr = { > > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { > > s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}}, _u = { > > _ext = {nsaddrs = {0x0, 0x0, 0x0}, nscount = 0 '\000', nstimes = {0, 0, > > 0}, nssocks = {0, 0, 0}, nscount6 = 0, nsinit = 0}}} > > (gdb) p &_res > > $2 = (struct __res_state *) 0x7f8ff8fd98 <_res> > > (gdb) p rp > > $3 = (struct __res_state *) 0x7fffffffff > > > > And the following uclibc code at libc/inet/resolv.c:3356: > > > > 3345 static void res_sync_func(void) > > 3346 { > > 3347 struct __res_state *rp = &(_res); > > 3348 int n; > > 3349 > > 3350 /* If we didn't get malloc failure earlier... */ > > 3351 if (__nameserver != (void*) &__local_nameserver) { > > 3352 /* TODO: > > 3353 * if (__nameservers < rp->nscount) - try to grow __nameserver[]? > > 3354 */ > > 3355 #ifdef __UCLIBC_HAS_IPV6__ > > 3356 if (__nameservers > rp->_u._ext.nscount) > > 3357 __nameservers = rp->_u._ext.nscount; > > 3358 n = __nameservers; > > > > The special thing about ntpsec is the DNS lookup in an extra thread > > and/or the call to res_init(), see ntpsec-1_2_0/ntpd/ntp_dns.c: > > > > 69 msyslog(LOG_INFO, "DNS: dns_probe: %s, cast_flags:%x, flags:%x%s", > > 70 hostname, pp->cast_flags, pp->cfg.flags, busy); > > 71 if (NULL != active) /* normally redundant */ > > 72 return false; > > 73 > > 74 active = pp; > > 75 > > 76 sigfillset(&block_mask); > > 77 pthread_sigmask(SIG_BLOCK, &block_mask, &saved_sig_mask); > > 78 rc = pthread_create(&worker, NULL, dns_lookup, pp); > > > > and > > > > 165 static void* dns_lookup(void* arg) > > 166 { > > 167 struct peer *pp = (struct peer *) arg; > > 168 struct addrinfo hints; > > 169 > > 170 #ifdef HAVE_SECCOMP_H > > 171 setup_SIGSYS_trap(); /* enable trap for this thread */ > > 172 #endif > > 173 > > 174 #ifdef HAVE_RES_INIT > > 175 /* Reload DNS servers from /etc/resolv.conf in case DHCP has updated it. > > 176 * We only need to do this occasionally, but it's not expensive > > 177 * and simpler to do it every time than it is to figure out when > > 178 * to do it. > > 179 * This res_init() covers NTS too. > > 180 */ > > 181 res_init(); > > 182 #endif > > 183 > > 184 if (pp->cfg.flags & FLAG_NTS) { > > 185 #ifndef DISABLE_NTS > > 186 nts_probe(pp); > > 187 #endif > > 188 } else { > > 189 ZERO(hints); > > 190 hints.ai_protocol = IPPROTO_UDP; > > 191 hints.ai_socktype = SOCK_DGRAM; > > 192 hints.ai_family = AF(&pp->srcadr); > > 193 gai_rc = getaddrinfo(pp->hostname, NTP_PORTA, &hints, &answer); > > 194 } > > > > $ /usr/lib/uclibc-ng-test/test/inet/tst-res > > Segmentation fault (core dumped) > > > > $ ./host/bin/aarch64-buildroot-linux-uclibc-gdb ./build/uclibc-ng-test-0844445e7358eb10e716155b55b0fb23e88d644a/test/inet/tst-res core > > Core was generated by `/usr/lib/uclibc-ng-test/test/inet/tst-res'. > > Program terminated with signal SIGSEGV, Segmentation fault. > > (gdb) where > > #0 __GI___res_init () at libc/inet/resolv.c:3514 > > #1 0x0000005591e507e4 in main (argc=<optimized out>, argv=<optimized out>) > > at tst-res.c:20 > > > > Signed-off-by: Peter Seiderer <ps.report@gmx.net> > > --- > > include/resolv.h | 2 +- > > libc/inet/resolv.c | 4 ++-- > > 2 files changed, 3 insertions(+), 3 deletions(-) > > > > diff --git a/include/resolv.h b/include/resolv.h > > index 485b8db98..2a82641a4 100644 > > --- a/include/resolv.h > > +++ b/include/resolv.h > > @@ -457,7 +457,7 @@ __END_DECLS > > # ifndef NOT_IN_libc > > # define __resp __libc_resp > > # endif > > -# define _res (*__resp) > > +# define _res (*__res_state()) > > extern __thread struct __res_state *__resp attribute_tls_model_ie; > > # endif > > # else > > diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c > > index 8bbd7c7cd..cf170fba6 100644 > > --- a/libc/inet/resolv.c > > +++ b/libc/inet/resolv.c > > @@ -3344,7 +3344,7 @@ libc_hidden_def(dn_skipname) > > /* Will be called under __resolv_lock. */ > > static void res_sync_func(void) > > { > > - struct __res_state *rp = &(_res); > > + struct __res_state *rp = __res_state(); > > int n; > > > > /* If we didn't get malloc failure earlier... */ > > @@ -3896,7 +3896,7 @@ res_ninit(res_state statp) > > #endif /* L_res_init */ > > > > #ifdef L_res_state > > -# if defined __UCLIBC_HAS_TLS__ > > +# if !defined __UCLIBC_HAS_TLS__ > > struct __res_state * > > __res_state (void) > > { > > -- > > 2.33.1 > > > > _______________________________________________ > > devel mailing list -- devel@uclibc-ng.org > > To unsubscribe send an email to devel-leave@uclibc-ng.org > >
diff --git a/include/resolv.h b/include/resolv.h index 485b8db98..2a82641a4 100644 --- a/include/resolv.h +++ b/include/resolv.h @@ -457,7 +457,7 @@ __END_DECLS # ifndef NOT_IN_libc # define __resp __libc_resp # endif -# define _res (*__resp) +# define _res (*__res_state()) extern __thread struct __res_state *__resp attribute_tls_model_ie; # endif # else diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 8bbd7c7cd..cf170fba6 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -3344,7 +3344,7 @@ libc_hidden_def(dn_skipname) /* Will be called under __resolv_lock. */ static void res_sync_func(void) { - struct __res_state *rp = &(_res); + struct __res_state *rp = __res_state(); int n; /* If we didn't get malloc failure earlier... */ @@ -3896,7 +3896,7 @@ res_ninit(res_state statp) #endif /* L_res_init */ #ifdef L_res_state -# if defined __UCLIBC_HAS_TLS__ +# if !defined __UCLIBC_HAS_TLS__ struct __res_state * __res_state (void) {
- use the provided __res_state() method instead of direct access to struct __res_state pointer &_res/*__resp - change the __UCLIBC_HAS_TLS__ protected __res_state() implementation to the one where the comment 'When threaded, _res may be a per-thread variable.' indicates this should be used with threads/TLS enabled Fixes the following segfaults with buildroot raspberrypi3_64_defconfig (uclibc, -Os, Note: runs fine using the raspberrypi3_defconfig): $ /usr/sbin/ntpd -n -d 1970-01-01T00:01:49 ntpd[249]: INIT: ntpd ntpsec-1.2.0 2021-11-03T20:39:50Z: Starting 1970-01-01T00:01:49 ntpd[249]: INIT: Command line: /usr/sbin/ntpd -n -d 1970-01-01T00:01:49 ntpd[249]: INIT: precision = 7.240 usec (-17) 1970-01-01T00:01:49 ntpd[249]: INIT: successfully locked into RAM 1970-01-01T00:01:49 ntpd[249]: CONFIG: readconfig: parsing file: /etc/ntp.conf 1970-01-01T00:01:49 ntpd[249]: CONFIG: restrict nopeer ignored 1970-01-01T00:01:49 ntpd[249]: INIT: Using SO_TIMESTAMPNS 1970-01-01T00:01:49 ntpd[249]: IO: Listen and drop on 0 v6wildcard [::]:123 1970-01-01T00:01:49 ntpd[249]: IO: Listen and drop on 1 v4wildcard 0.0.0.0:123 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 2 lo 127.0.0.1:123 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 3 eth0 172.16.0.30:123 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 4 lo [::1]:123 1970-01-01T00:01:49 ntpd[249]: IO: Listen normally on 5 eth0 [fe80::ba27:ebff:fea6:340%2]:123 1970-01-01T00:01:49 ntpd[249]: IO: Listening on routing socket on fd #22 for interface updates 1970-01-01T00:01:50 ntpd[249]: SYNC: Found 10 servers, suggest minsane at least 3 1970-01-01T00:01:50 ntpd[249]: INIT: MRU 10922 entries, 13 hash bits, 65536 bytes 1970-01-01T00:01:50 ntpd[249]: statistics directory /var/NTP/ does not exist or is unwriteable, error No such file or directory 1970-01-01T00:01:51 ntpd[249]: DNS: dns_probe: 0.pool.ntp.org, cast_flags:8, flags:101 Segmentation fault (core dumped) $ ./host/bin/aarch64-buildroot-linux-uclibc-gdb ./build/ntpsec-1_2_0/build/main/ntpd/ntpd core Core was generated by `/usr/sbin/ntpd -n -d'. Program terminated with signal SIGSEGV, Segmentation fault. (gdb) where #0 0x0000007f8ff1f150 in res_sync_func () at libc/inet/resolv.c:3356 #1 0x0000007f8ff1c468 in __open_nameservers () at libc/inet/resolv.c:949 #2 0x0000007f8ff1b498 in __dns_lookup (name=0x55943c67f0 "0.pool.ntp.org", type=1, outpacket=0x7f8fe91c48, a=0x7f8fe91c08) at libc/inet/resolv.c:1134 #3 0x0000007f8ff1d744 in __GI_gethostbyname_r ( name=0x55943c67f0 "0.pool.ntp.org", result_buf=0x7f8fe92628, buf=0x7f8fe91d90 "", buflen=992, result=0x7f8fe92670, h_errnop=0x7f8fe92668) at libc/inet/resolv.c:1966 #4 0x0000007f8ff1d9a0 in __GI_gethostbyname2_r ( name=0x55943c67f0 "0.pool.ntp.org", family=2, result_buf=0x7f8fe92628, buf=0x7f8fe91d70 "0.pool.ntp.org", buflen=1024, result=0x7f8fe92670, h_errnop=0x7f8fe92668) at libc/inet/resolv.c:2065 #5 0x0000007f8ff16924 in gaih_inet (name=0x55943c67f0 "0.pool.ntp.org", service=0x7f8fe92828, req=0x7f8fe92890, pai=0x7f8fe92838) at libc/inet/getaddrinfo.c:596 #6 0x0000007f8ff17624 in __GI_getaddrinfo ( name=0x55943c67f0 "0.pool.ntp.org", service=0x5582eb8acd "\377H\213D$\bL\211\367H\213\260\270", hints=0x7f8fe92890, pai=0x5582ee1bf8) at libc/inet/getaddrinfo.c:957 #7 0x0000005582ea60f4 in _start () (gdb) p _res $1 = {options = 0, nsaddr_list = {{sin_family = 0, sin_port = 0, sin_addr = { s_addr = 0}, sin_zero = "\000\000\000\000\000\000\000"}, { sin_family = 0, sin_port = 0, sin_addr = {s_addr = 0}, sin_zero = "\000\000\000\000\000\000\000"}, {sin_family = 0, sin_port = 0, sin_addr = {s_addr = 0}, sin_zero = "\000\000\000\000\000\000\000"}}, dnsrch = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, nscount = 0 '\000', ndots = 0 '\000', retrans = 0 '\000', retry = 0 '\000', defdname = '\000' <repeats 255 times>, nsort = 0 '\000', pfcode = 0, id = 0, res_h_errno = 0, sort_list = {{addr = { s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = { s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}}, _u = { _ext = {nsaddrs = {0x0, 0x0, 0x0}, nscount = 0 '\000', nstimes = {0, 0, 0}, nssocks = {0, 0, 0}, nscount6 = 0, nsinit = 0}}} (gdb) p &_res $2 = (struct __res_state *) 0x7f8ff8fd98 <_res> (gdb) p rp $3 = (struct __res_state *) 0x7fffffffff And the following uclibc code at libc/inet/resolv.c:3356: 3345 static void res_sync_func(void) 3346 { 3347 struct __res_state *rp = &(_res); 3348 int n; 3349 3350 /* If we didn't get malloc failure earlier... */ 3351 if (__nameserver != (void*) &__local_nameserver) { 3352 /* TODO: 3353 * if (__nameservers < rp->nscount) - try to grow __nameserver[]? 3354 */ 3355 #ifdef __UCLIBC_HAS_IPV6__ 3356 if (__nameservers > rp->_u._ext.nscount) 3357 __nameservers = rp->_u._ext.nscount; 3358 n = __nameservers; The special thing about ntpsec is the DNS lookup in an extra thread and/or the call to res_init(), see ntpsec-1_2_0/ntpd/ntp_dns.c: 69 msyslog(LOG_INFO, "DNS: dns_probe: %s, cast_flags:%x, flags:%x%s", 70 hostname, pp->cast_flags, pp->cfg.flags, busy); 71 if (NULL != active) /* normally redundant */ 72 return false; 73 74 active = pp; 75 76 sigfillset(&block_mask); 77 pthread_sigmask(SIG_BLOCK, &block_mask, &saved_sig_mask); 78 rc = pthread_create(&worker, NULL, dns_lookup, pp); and 165 static void* dns_lookup(void* arg) 166 { 167 struct peer *pp = (struct peer *) arg; 168 struct addrinfo hints; 169 170 #ifdef HAVE_SECCOMP_H 171 setup_SIGSYS_trap(); /* enable trap for this thread */ 172 #endif 173 174 #ifdef HAVE_RES_INIT 175 /* Reload DNS servers from /etc/resolv.conf in case DHCP has updated it. 176 * We only need to do this occasionally, but it's not expensive 177 * and simpler to do it every time than it is to figure out when 178 * to do it. 179 * This res_init() covers NTS too. 180 */ 181 res_init(); 182 #endif 183 184 if (pp->cfg.flags & FLAG_NTS) { 185 #ifndef DISABLE_NTS 186 nts_probe(pp); 187 #endif 188 } else { 189 ZERO(hints); 190 hints.ai_protocol = IPPROTO_UDP; 191 hints.ai_socktype = SOCK_DGRAM; 192 hints.ai_family = AF(&pp->srcadr); 193 gai_rc = getaddrinfo(pp->hostname, NTP_PORTA, &hints, &answer); 194 } $ /usr/lib/uclibc-ng-test/test/inet/tst-res Segmentation fault (core dumped) $ ./host/bin/aarch64-buildroot-linux-uclibc-gdb ./build/uclibc-ng-test-0844445e7358eb10e716155b55b0fb23e88d644a/test/inet/tst-res core Core was generated by `/usr/lib/uclibc-ng-test/test/inet/tst-res'. Program terminated with signal SIGSEGV, Segmentation fault. (gdb) where #0 __GI___res_init () at libc/inet/resolv.c:3514 #1 0x0000005591e507e4 in main (argc=<optimized out>, argv=<optimized out>) at tst-res.c:20 Signed-off-by: Peter Seiderer <ps.report@gmx.net> --- include/resolv.h | 2 +- libc/inet/resolv.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)