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(a)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(a)uclibc-ng.org
> To unsubscribe send an email to devel-leave(a)uclibc-ng.org
>