diff mbox series

[uclibc-ng-devel] Re: [Buildroot] [PATCH v1] package/ntpsec: new package

Message ID 20211028230131.5f50d6e7@gmx.net
State New
Headers show
Series [uclibc-ng-devel] Re: [Buildroot] [PATCH v1] package/ntpsec: new package | expand

Commit Message

Peter Seiderer Oct. 28, 2021, 9:01 p.m. UTC
Hello Waldemar, *,

On Mon, 25 Oct 2021 23:25:41 +0200, Peter Seiderer <ps.report@gmx.net> wrote:

> - set 'CC=gcc' to avoid cross-compile failure (see [1]):
> 
>   /bin/sh: line 1: .../build/ntpsec-1_2_0/build/host/ntpd/keyword-gen: cannot execute binary file: Exec format error
> 
>   Waf: Leaving directory `.../build/ntpsec-1_2_0/build/host'
>   Build failed
>    -> task in 'ntp_keyword.h' failed with exit status 126 (run with -v to display more information)  
> 
> - set '-std=gnu99"' to avoid compile failure with old compilers
> 
> - explicit set PYTHON_CONFIG
> 
> - add patch 001-ntptime-fix-jfmt5-ofmt5-jfmt6-ofmt6-related-compile-.patch to
>   fix ntptime jfmt5/ofmt5 jfmt6/ofmt6 related compile failure
> 
> - add SYSV init file (S49ntp)
> 
> - add example ntpd.conf (with legacy option enabled and provide skeleton
>   for NTS configuration)
> 
> - add config option for NTS support
> 
> - depend on python3 (omit python2 to reduce test effort)
> 
> - add ntp user/group and run ntpd as restricted user
> 
> - add libcap dependency (compile time optional but needed for droproot
>   support)
> 
> [1] https://gitlab.com/NTPsec/ntpsec/-/issues/694
> 
> Signed-off-by: Peter Seiderer <ps.report@gmx.net>
> ---
>  DEVELOPERS                                    |  1 +
>  package/Config.in                             |  1 +
>  ...5-ofmt5-jfmt6-ofmt6-related-compile-.patch | 61 ++++++++++++++++
>  package/ntpsec/Config.in                      | 31 ++++++++
>  package/ntpsec/S49ntp                         | 58 +++++++++++++++
>  package/ntpsec/ntpd.etc.conf                  | 33 +++++++++
>  package/ntpsec/ntpsec.hash                    |  4 ++
>  package/ntpsec/ntpsec.mk                      | 71 +++++++++++++++++++
>  8 files changed, 260 insertions(+)
>  create mode 100644 package/ntpsec/0001-ntptime-fix-jfmt5-ofmt5-jfmt6-ofmt6-related-compile-.patch
>  create mode 100644 package/ntpsec/Config.in
>  create mode 100644 package/ntpsec/S49ntp
>  create mode 100644 package/ntpsec/ntpd.etc.conf
>  create mode 100644 package/ntpsec/ntpsec.hash
>  create mode 100644 package/ntpsec/ntpsec.mk
> 
> diff --git a/DEVELOPERS b/DEVELOPERS
> index 771519fd9b..593526e61f 100644
> --- a/DEVELOPERS
> +++ b/DEVELOPERS
> @@ -2167,6 +2167,7 @@ F:	package/iwd/
>  F:	package/libevdev/
>  F:	package/libuev/
>  F:	package/log4cplus/
> +F:	package/ntpsec/
>  F:	package/postgresql/
>  F:	package/python-colorzero/
>  F:	package/python-flask-wtf/
> diff --git a/package/Config.in b/package/Config.in
> index d40eb9dabc..842e555342 100644
> --- a/package/Config.in
> +++ b/package/Config.in
> @@ -2256,6 +2256,7 @@ endif
>  	source "package/nmap/Config.in"
>  	source "package/noip/Config.in"
>  	source "package/ntp/Config.in"
> +	source "package/ntpsec/Config.in"
>  	source "package/nuttcp/Config.in"
>  	source "package/odhcp6c/Config.in"
>  	source "package/odhcploc/Config.in"
> diff --git a/package/ntpsec/0001-ntptime-fix-jfmt5-ofmt5-jfmt6-ofmt6-related-compile-.patch b/package/ntpsec/0001-ntptime-fix-jfmt5-ofmt5-jfmt6-ofmt6-related-compile-.patch
> new file mode 100644
> index 0000000000..c2838fe8e0
> --- /dev/null
> +++ b/package/ntpsec/0001-ntptime-fix-jfmt5-ofmt5-jfmt6-ofmt6-related-compile-.patch
> @@ -0,0 +1,61 @@
> +From 4015a1183d2f79dad6dd675ca5e0d329825f3fa3 Mon Sep 17 00:00:00 2001
> +From: Peter Seiderer <ps.report@gmx.net>
> +Date: Mon, 4 Oct 2021 22:25:58 +0200
> +Subject: [PATCH] ntptime: fix jfmt5/ofmt5 jfmt6/ofmt6 related compile failure
> +MIME-Version: 1.0
> +Content-Type: text/plain; charset=UTF-8
> +Content-Transfer-Encoding: 8bit
> +
> +Use same define guard for definiton as for usage ('HAVE_STRUCT_NTPTIMEVAL_TAI'
> +instead of 'NTP_API && NTP_API > 3').
> +
> +Fixes:
> +
> +  ../../ntptime/ntptime.c: In function ‘main’:
> +  ../../ntptime/ntptime.c:349:17: error: ‘jfmt5’ undeclared (first use in this function); did you mean ‘jfmt6’?
> +    349 |   printf(json ? jfmt5 : ofmt5, (long)ntv.tai);
> +        |                 ^~~~~
> +        |                 jfmt6
> +  ../../ntptime/ntptime.c:349:17: note: each undeclared identifier is reported only once for each function it appears in
> +  ../../ntptime/ntptime.c:349:25: error: ‘ofmt5’ undeclared (first use in this function); did you mean ‘ofmt6’?
> +    349 |   printf(json ? jfmt5 : ofmt5, (long)ntv.tai);
> +        |                         ^~~~~
> +        |                         ofmt6
> +  ../../ntptime/ntptime.c:321:15: warning: unused variable ‘jfmt6’ [-Wunused-variable]
> +    321 |   const char *jfmt6 = "";
> +        |               ^~~~~
> +  ../../ntptime/ntptime.c:311:15: warning: unused variable ‘ofmt6’ [-Wunused-variable]
> +    311 |   const char *ofmt6 = "\n";
> +        |               ^~~~~
> +
> +[Upstream: https://gitlab.com/NTPsec/ntpsec/-/merge_requests/1245]
> +Signed-off-by: Peter Seiderer <ps.report@gmx.net>
> +---
> + ntptime/ntptime.c | 4 ++--
> + 1 file changed, 2 insertions(+), 2 deletions(-)
> +
> +diff --git a/ntptime/ntptime.c b/ntptime/ntptime.c
> +index ff861cb..5d58593 100644
> +--- a/ntptime/ntptime.c
> ++++ b/ntptime/ntptime.c
> +@@ -305,7 +305,7 @@ main(
> + 		const char *ofmt2 = "  time %s, (.%0*d),\n";
> + 		const char *ofmt3 = "  maximum error %lu us, estimated error %lu us";
> + 		const char *ofmt4 = "  ntptime=%x.%x unixtime=%x.%0*d %s";
> +-#if defined NTP_API && NTP_API > 3
> ++#if defined(HAVE_STRUCT_NTPTIMEVAL_TAI)
> + 		const char *ofmt5 = ", TAI offset %ld\n";
> + #else
> + 		const char *ofmt6 = "\n";
> +@@ -315,7 +315,7 @@ main(
> + 		const char *jfmt2 = "\"time\":\"%s\",\"fractional-time\":\".%0*d\",";
> + 		const char *jfmt3 = "\"maximum-error\":%lu,\"estimated-error\":%lu,";
> + 		const char *jfmt4 = "\"raw-ntp-time\":\"%x.%x\",\"raw-unix-time\":\"%x.%0*d %s\",";
> +-#if defined NTP_API && NTP_API > 3
> ++#if defined(HAVE_STRUCT_NTPTIMEVAL_TAI)
> + 		const char *jfmt5 = "\"TAI-offset\":%d,";
> + #else
> + 		const char *jfmt6 = "";
> +-- 
> +2.33.0
> +
> diff --git a/package/ntpsec/Config.in b/package/ntpsec/Config.in
> new file mode 100644
> index 0000000000..7275533d26
> --- /dev/null
> +++ b/package/ntpsec/Config.in
> @@ -0,0 +1,31 @@
> +config BR2_PACKAGE_NTPSEC
> +	bool "ntpsec"
> +	depends on BR2_PACKAGE_PYTHON3
> +	select BR2_PACKAGE_LIBCAP
> +	select BR2_PACKAGE_OPENSSL
> +	help
> +	  NTPsec project - a secure, hardened, and improved
> +	  implementation of Network Time Protocol derived
> +	  from NTP Classic, Dave Mills’s original.
> +
> +	  Provides things like ntpd, ntpdate, ntpq, etc...
> +
> +	  https://www.ntpsec.org/
> +
> +if BR2_PACKAGE_NTPSEC
> +
> +config BR2_PACKAGE_NTPSEC_CLASSIC_MODE
> +	bool "classic-mode"
> +	help
> +	  Enable strict configuration and log-format compatibility
> +	  with NTP Classic.
> +
> +config BR2_PACKAGE_NTPSEC_NTS
> +	bool "NTS support"
> +	help
> +	  Enable Network Time Security (NTS) support.
> +
> +endif
> +
> +comment "ntpsec depens on Pyhton3"
> +	depends on !BR2_PACKAGE_PYTHON3
> diff --git a/package/ntpsec/S49ntp b/package/ntpsec/S49ntp
> new file mode 100644
> index 0000000000..f3db51418e
> --- /dev/null
> +++ b/package/ntpsec/S49ntp
> @@ -0,0 +1,58 @@
> +#!/bin/sh
> +#
> +# Starts Network Time Protocol daemon
> +#
> +
> +DAEMON="ntpd"
> +PIDFILE="/var/run/$DAEMON.pid"
> +
> +NTPD_ARGS="-g -u ntp:ntp -s /var/run/ntp"
> +
> +# shellcheck source=/dev/null
> +[ -r "/etc/default/$DAEMON" ] && . "/etc/default/$DAEMON"
> +
> +mkdir -p /var/run/ntp && chown ntp:ntp /var/run/ntp
> +
> +start() {
> +	printf 'Starting %s: ' "$DAEMON"
> +	# shellcheck disable=SC2086 # we need the word splitting
> +	start-stop-daemon -S -q -p "$PIDFILE" -x "/usr/sbin/$DAEMON" \
> +		-- $NTPD_ARGS -p "$PIDFILE"
> +	status=$?
> +	if [ "$status" -eq 0 ]; then
> +		echo "OK"
> +	else
> +		echo "FAIL"
> +	fi
> +	return "$status"
> +}
> +
> +stop() {
> +	printf 'Stopping %s: ' "$DAEMON"
> +	start-stop-daemon -K -q -p "$PIDFILE"
> +	status=$?
> +	if [ "$status" -eq 0 ]; then
> +		rm -f "$PIDFILE"
> +		echo "OK"
> +	else
> +		echo "FAIL"
> +	fi
> +	return "$status"
> +}
> +
> +restart() {
> +	stop
> +	sleep 1
> +	start
> +}
> +
> +case "$1" in
> +	start|stop|restart)
> +		"$1";;
> +	reload)
> +		# Restart, since there is no true "reload" feature.
> +		restart;;
> +	*)
> +		echo "Usage: $0 {start|stop|restart|reload}"
> +		exit 1
> +esac
> diff --git a/package/ntpsec/ntpd.etc.conf b/package/ntpsec/ntpd.etc.conf
> new file mode 100644
> index 0000000000..e0f45c1438
> --- /dev/null
> +++ b/package/ntpsec/ntpd.etc.conf
> @@ -0,0 +1,33 @@
> +#
> +# legacy NTP configuration
> +#
> +pool 0.pool.ntp.org iburst
> +pool 1.pool.ntp.org iburst
> +pool 2.pool.ntp.org iburst
> +pool 3.pool.ntp.org iburst
> +
> +#
> +# NTS configuration
> +#
> +# Notes:
> +#  - uncomment the following lines to enable NTS support (but
> +#    make sure the initial clock is up-to-date (otherwise the
> +#    NTS certificate validation will fail with 'NTSc: certificate invalid:
> +#    9=>certificate is not yet valid' as on boards without RTC support)
> +#    and/or keep at least one line from the legacy NTP lines
> +#  - enable BR2_PACKAGE_CA_CERTIFICATES to gain access to the certificate
> +#    files
> +#
> +# server time.cloudflare.com nts  # Global, anycast
> +# server nts.ntp.se:4443 nts      # Sweden
> +# server ntpmon.dcs1.biz nts      # Singapore
> +# server ntp1.glypnod.com nts     # San Francisco
> +# server ntp2.glypnod.com nts     # London
> +#
> +# ca /usr/share/ca-certificates/mozilla
> +
> +# Allow only time queries, at a limited rate, sending KoD when in excess.
> +# Allow all local queries (IPv4, IPv6)
> +restrict default nomodify nopeer noquery limited kod
> +restrict 127.0.0.1
> +restrict [::1]
> diff --git a/package/ntpsec/ntpsec.hash b/package/ntpsec/ntpsec.hash
> new file mode 100644
> index 0000000000..9c30605cbd
> --- /dev/null
> +++ b/package/ntpsec/ntpsec.hash
> @@ -0,0 +1,4 @@
> +# Locally calculated
> +sha256  80e5b4c07dc1f8f7dc90851662c72a80a4111477c48040ae9e1f2e56f893251d  ntpsec-NTPsec_1_2_0.tar.bz2
> +sha256  b4db4de3317c3b0554ed91eb692968800bdfd6ad2c16ffbeee8ce4895ed91da4  LICENSE.adoc
> +sha256  d3b21470adadd9abd9c6d675378f8c371ac5a4ea6dbec91859e02fadca3c0856  docs/copyright.adoc
> diff --git a/package/ntpsec/ntpsec.mk b/package/ntpsec/ntpsec.mk
> new file mode 100644
> index 0000000000..c62077dce6
> --- /dev/null
> +++ b/package/ntpsec/ntpsec.mk
> @@ -0,0 +1,71 @@
> +################################################################################
> +#
> +# ntpsec
> +#
> +################################################################################
> +
> +NTPSEC_VERSION_MAJOR = 1
> +NTPSEC_VERSION_MINOR = 2
> +NTPSEC_VERSION_POINT = 0
> +NTPSEC_VERSION = $(NTPSEC_VERSION_MAJOR)_$(NTPSEC_VERSION_MINOR)_$(NTPSEC_VERSION_POINT)
> +NTPSEC_SOURCE = ntpsec-NTPsec_$(NTPSEC_VERSION).tar.bz2
> +NTPSEC_SITE = https://gitlab.com/NTPsec/ntpsec/-/archive/NTPsec_$(NTPSEC_VERSION)
> +NTPSEC_LICENSE = BSD-2-Clause NTP BSD-3-Clause MIT
> +NTPSEC_LICENSE_FILES = LICENSE.adoc docs/copyright.adoc
> +
> +NTPSEC_CPE_ID_VENDOR = ntpsec
> +NTPSEC_CPE_ID_VERSION = $(NTPSEC_VERSION_MAJOR).$(NTPSEC_VERSION_MINOR)
> +NTPSEC_CPE_ID_UPDATE = $(NTPSEC_VERSION_POINT)
> +
> +NTPSEC_DEPENDENCIES = \
> +	host-pkgconf \
> +	$(if $(BR2_PACKAGE_PYTHON),python,python3) \
> +	libcap \
> +	openssl
> +
> +NTPSEC_CONF_OPTS = \
> +	CC=gcc \
> +	PYTHON_CONFIG="$(STAGING_DIR)/usr/bin/$(if $(BR2_PACKAGE_PYTHON),python,python3)-config" \
> +	--cross-compiler="$(TARGET_CC)" \
> +	--cross-cflags="$(TARGET_CFLAGS) -std=gnu99" \
> +	--cross-ldflags="$(TARGET_LDFLAGS)" \
> +	--notests \
> +	--enable-early-droproot \
> +	--disable-mdns-registration \
> +	--enable-pylib=ffi \
> +	--nopyc \
> +	--nopyo \
> +	--nopycache \
> +	--disable-doc \
> +	--disable-manpage
> +
> +ifeq ($(BR2_PACKAGE_NTPSEC_CLASSIC_MODE),y)
> +NTPSEC_CONF_OPTS += --enable-classic-mode
> +endif
> +
> +ifeq ($(BR2_PACKAGE_NTPSEC_NTS),y)
> +#NTPSEC_CONF_OPTS += --enable-nts
> +else
> +NTPSEC_CONF_OPTS += --disable-nts
> +endif
> +
> +# add a link to libntpc.so where python searches for it
> +define NTPSEC_LIBNTPC_LINK
> +	ln -sf /usr/lib/ntp/libntpc.so $(TARGET_DIR)/usr/lib/libntpc.so
> +endef
> +NTPSEC_POST_INSTALL_TARGET_HOOKS += NTPSEC_LIBNTPC_LINK
> +
> +define NTPSEC_INSTALL_NTPSEC_CONF
> +	$(INSTALL) -m 644 package/ntpsec/ntpd.etc.conf $(TARGET_DIR)/etc/ntp.conf
> +endef
> +NTPSEC_POST_INSTALL_TARGET_HOOKS += NTPSEC_INSTALL_NTPSEC_CONF
> +
> +define NTPSEC_INSTALL_INIT_SYSV
> +	$(INSTALL) -D -m 755 package/ntpsec/S49ntp $(TARGET_DIR)/etc/init.d/S49ntp
> +endef
> +
> +define NTPSEC_USERS
> +	ntp -1 ntp -1 * - - - ntpd user
> +endef
> +
> +$(eval $(waf-package))


The resulting ntpd runs fine with the raspberrypi3_defconfig, but segfaults
when compiled/used with raspberrypi3_64_defconfig (uclibc, -Os):

	$ /usr/sbin/ntpd -n -d -g
1970-01-01T00:04:18 ntpd[263]: INIT: ntpd ntpsec-1.2.0 2021-10-24T13:39:21Z: Starting
1970-01-01T00:04:18 ntpd[263]: INIT: Command line: /usr/sbin/ntpd -n -d
1970-01-01T00:04:18 ntpd[263]: INIT: precision = 7.291 usec (-17)
1970-01-01T00:04:18 ntpd[263]: INIT: successfully locked into RAM
1970-01-01T00:04:18 ntpd[263]: CONFIG: readconfig: parsing file: /etc/ntp.conf
1970-01-01T00:04:18 ntpd[263]: CONFIG: restrict nopeer ignored
1970-01-01T00:04:18 ntpd[263]: INIT: Using SO_TIMESTAMPNS
1970-01-01T00:04:18 ntpd[263]: IO: Listen and drop on 0 v6wildcard [::]:123
1970-01-01T00:04:18 ntpd[263]: IO: Listen and drop on 1 v4wildcard 0.0.0.0:123
1970-01-01T00:04:18 ntpd[263]: IO: Listen normally on 2 lo 127.0.0.1:123
1970-01-01T00:04:18 ntpd[263]: IO: Listen normally on 3 eth0 172.16.0.30:123
1970-01-01T00:04:18 ntpd[263]: IO: Listen normally on 4 lo [::1]:123
1970-01-01T00:04:18 ntpd[263]: IO: Listen normally on 5 eth0 [fe80::ba27:ebff:fea6:340%2]:123
1970-01-01T00:04:18 ntpd[263]: IO: Listening on routing socket on fd #22 for interface updates
1970-01-01T00:04:19 ntpd[263]: SYNC: Found 10 servers, suggest minsane at least 3
1970-01-01T00:04:19 ntpd[263]: INIT: MRU 10922 entries, 13 hash bits, 65536 bytes
1970-01-01T00:04:20 ntpd[263]: DNS: dns_probe: 0.pool.ntp.org, cast_flags:8, flags:101
Segmentation fault (core dumped)


With the following stacktrace:

	$ ./host/bin/aarch64-buildroot-linux-uclibc-gdb build/ntpsec-1_2_0/build/main/ntpd/ntpd core
Program terminated with signal SIGSEGV, Segmentation fault.
(gdb) where
#0  0x0000007fbbfa4150 in res_sync_func () at libc/inet/resolv.c:3356
#1  0x0000007fbbfa1468 in __open_nameservers () at libc/inet/resolv.c:949
#2  0x0000007fbbfa0498 in __dns_lookup (name=0x55a464a7f0 "0.pool.ntp.org",
    type=1, outpacket=0x7fbbf16c48, a=0x7fbbf16c08) at libc/inet/resolv.c:1134
#3  0x0000007fbbfa2744 in __GI_gethostbyname_r (
    name=0x55a464a7f0 "0.pool.ntp.org", result_buf=0x7fbbf17628,
    buf=0x7fbbf16d90 "", buflen=992, result=0x7fbbf17670,
    h_errnop=0x7fbbf17668) at libc/inet/resolv.c:1966
#4  0x0000007fbbfa29a0 in __GI_gethostbyname2_r (
    name=0x55a464a7f0 "0.pool.ntp.org", family=2, result_buf=0x7fbbf17628,
    buf=0x7fbbf16d70 "0.pool.ntp.org", buflen=1024, result=0x7fbbf17670,
    h_errnop=0x7fbbf17668) at libc/inet/resolv.c:2065
#5  0x0000007fbbf9b924 in gaih_inet (name=0x55a464a7f0 "0.pool.ntp.org",
    service=0x7fbbf17828, req=0x7fbbf17890, pai=0x7fbbf17838)
    at libc/inet/getaddrinfo.c:596
#6  0x0000007fbbf9c624 in __GI_getaddrinfo (
    name=0x55a464a7f0 "0.pool.ntp.org",
    service=0x5576ad807d "\277\261\377\377A\215E\001I9\334r\263f\017\037D",
    hints=0x7fbbf17890, pai=0x5576b00bd8) at libc/inet/getaddrinfo.c:957
#7  0x0000005576ac5698 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 *) 0x7fbc014d98 <_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         }


The failure can be fixed/work-around with the following uClibc-ng-1.0.39 patch:



The first change is using the provided __res_state() method instead
of direct access, the second one changes the __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...

Not sure if this is the right fix and/or I figrue out enough of the uclibc
logic about the _res access vs. res_init() vs. thread/TLS logic...

Regards,
Peter

Comments

Waldemar Brodkorb Oct. 30, 2021, 10:56 p.m. UTC | #1
Hi Peter,
Peter Seiderer wrote,

> Hello Waldemar, *,
> 
> On Mon, 25 Oct 2021 23:25:41 +0200, Peter Seiderer <ps.report@gmx.net> wrote:
> 
> The resulting ntpd runs fine with the raspberrypi3_defconfig, but segfaults
> when compiled/used with raspberrypi3_64_defconfig (uclibc, -Os):
> 
> 	$ /usr/sbin/ntpd -n -d -g
> 1970-01-01T00:04:18 ntpd[263]: INIT: ntpd ntpsec-1.2.0 2021-10-24T13:39:21Z: Starting
> 1970-01-01T00:04:18 ntpd[263]: INIT: Command line: /usr/sbin/ntpd -n -d
> 1970-01-01T00:04:18 ntpd[263]: INIT: precision = 7.291 usec (-17)
> 1970-01-01T00:04:18 ntpd[263]: INIT: successfully locked into RAM
> 1970-01-01T00:04:18 ntpd[263]: CONFIG: readconfig: parsing file: /etc/ntp.conf
> 1970-01-01T00:04:18 ntpd[263]: CONFIG: restrict nopeer ignored
> 1970-01-01T00:04:18 ntpd[263]: INIT: Using SO_TIMESTAMPNS
> 1970-01-01T00:04:18 ntpd[263]: IO: Listen and drop on 0 v6wildcard [::]:123
> 1970-01-01T00:04:18 ntpd[263]: IO: Listen and drop on 1 v4wildcard 0.0.0.0:123
> 1970-01-01T00:04:18 ntpd[263]: IO: Listen normally on 2 lo 127.0.0.1:123
> 1970-01-01T00:04:18 ntpd[263]: IO: Listen normally on 3 eth0 172.16.0.30:123
> 1970-01-01T00:04:18 ntpd[263]: IO: Listen normally on 4 lo [::1]:123
> 1970-01-01T00:04:18 ntpd[263]: IO: Listen normally on 5 eth0 [fe80::ba27:ebff:fea6:340%2]:123
> 1970-01-01T00:04:18 ntpd[263]: IO: Listening on routing socket on fd #22 for interface updates
> 1970-01-01T00:04:19 ntpd[263]: SYNC: Found 10 servers, suggest minsane at least 3
> 1970-01-01T00:04:19 ntpd[263]: INIT: MRU 10922 entries, 13 hash bits, 65536 bytes
> 1970-01-01T00:04:20 ntpd[263]: DNS: dns_probe: 0.pool.ntp.org, cast_flags:8, flags:101
> Segmentation fault (core dumped)

Could you add a small C test program to uClibc-ng-test to trigger
the bug? That would help to find any regression to targets without
TLS support.

best regards
 Waldemar
diff mbox series

Patch

diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
index 8bbd7c7..cf170fb 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)
 {