fix sourcedir reloading to not multiply sources (RHEL-95016)

Resolves: RHEL-95016
This commit is contained in:
Miroslav Lichvar 2025-06-04 09:35:28 +02:00
parent b3b6fcd0d0
commit 34f40e8d86
5 changed files with 356 additions and 3 deletions

2
.gitignore vendored
View File

@ -1,3 +1,3 @@
/chrony-4.6.1.tar.gz
/chrony-4.6.1-tar-gz-asc.txt
/clknetsim-40bb97.tar.gz
/clknetsim-cdd694.tar.gz

279
chrony-sourcedir.patch Normal file
View File

@ -0,0 +1,279 @@
commit d6aab8da1533b169385c749f8d1320c2b568a149
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Mon Jun 2 10:53:47 2025 +0200
conf: fix sourcedir reloading to not multiply sources
The sourcedir reload triggered by the chronyc "reload sources"
command incorrectly assumed that NSR_AddSourceByName() can return
only the NSR_Success status when a source is added. It ignored the
NSR_UnresolvedName status returned for a source whose name needs to
be resolved after the call (i.e. not specified with an IP address)
and added the source again, effectively multiplying it if the name
can be resolved to a different IP address.
Fix the code to check for the NSR_UnresolvedName status to correctly
determine whether the source was already added before and should not be
added again.
Reported-by: MichaelR <MichaelR42@runbox.com>
Fixes: 916ed70c4a81 ("conf: save source status in sourcedir reload")
diff --git a/conf.c b/conf.c
index cbb11304..59a2e5c9 100644
--- a/conf.c
+++ b/conf.c
@@ -1742,8 +1742,8 @@ reload_source_dirs(void)
NTP_Source *prev_sources, *new_sources, *source;
unsigned int i, j, prev_size, new_size, unresolved;
char buf[MAX_LINE_LENGTH];
+ int d, pass, was_added;
NSR_Status s;
- int d, pass;
/* Ignore reload command before adding configured sources */
if (!conf_ntp_sources_added)
@@ -1782,13 +1782,16 @@ reload_source_dirs(void)
else
d = i < prev_size ? -1 : 1;
+ was_added = d <= 0 && (prev_sources[i].status == NSR_Success ||
+ prev_sources[i].status == NSR_UnresolvedName);
+
/* Remove missing sources before adding others to avoid conflicts */
- if (pass == 0 && d < 0 && prev_sources[i].status == NSR_Success) {
+ if (pass == 0 && d < 0 && was_added) {
NSR_RemoveSourcesById(prev_sources[i].conf_id);
}
/* Add new sources and sources that could not be added before */
- if (pass == 1 && (d > 0 || (d == 0 && prev_sources[i].status != NSR_Success))) {
+ if (pass == 1 && (d > 0 || (d == 0 && !was_added))) {
source = &new_sources[j];
s = NSR_AddSourceByName(source->params.name, source->params.family, source->params.port,
source->pool, source->type, &source->params.params,
commit 778331092436c2f2077a7d0b6253ca1771fb8e27
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Tue Jun 3 10:58:00 2025 +0200
test: add 149-sourcedir test
diff --git a/test/simulation/149-sourcedir b/test/simulation/149-sourcedir
new file mode 100755
index 00000000..77b8499f
--- /dev/null
+++ b/test/simulation/149-sourcedir
@@ -0,0 +1,189 @@
+#!/usr/bin/env bash
+
+. ./test.common
+
+test_start "sourcedir directive"
+
+check_config_h 'FEAT_CMDMON 1' || test_skip
+
+servers=4
+limit=191
+update_executable="tmp/update-sourcedir"
+client_server_conf="sourcedir tmp"
+base_delay="(+ 1e-4 (* 5 (equal 0.1 from $[servers + 2])))"
+chronyc_start=1
+chronyc_conf="timeout 6000
+activity
+$(for i in $(seq 1 18); do echo "reload sources"; echo activity; done)"
+
+cat > tmp/sources.sources <<EOF
+pool nodes-1-2-3-4.net1.clk iburst
+EOF
+
+cat > tmp/update-sourcedir <<EOF
+#!/usr/bin/env bash
+case "\$1" in
+ 19) s="pool nodes-1-2-3-4.net1.clk";;
+ 39) s="pool nodes-1-2-3-4.net1.clk maxsources 3";;
+ 59) s="pool nodes-1-2-3.net1.clk";;
+ 79) s="pool nodes-1-2-3.net1.clk
+ server nodes-3-4.net1.clk";;
+ 99) s="server nodes-3-4.net1.clk";;
+ 119) s="server nodes-1-2-3.net1.clk";;
+ 139) s="server 192.168.123.2";;
+ 159) s="server 192.168.123.2 maxdelay 0.1";;
+ 179) s="";;
+ *) exit 0;;
+esac
+echo "\$s" > tmp/sources.sources
+EOF
+chmod 755 tmp/update-sourcedir
+
+run_test || test_fail
+check_chronyd_exit || test_fail
+
+check_log_messages "T00:0.:[135].Z \(Added\|Removed\)" 0 0 || test_fail
+check_log_messages "T00:0.:..Z Added pool nodes-1-2-3-4\." 3 3 || test_fail
+check_log_messages "T00:0.:..Z Removed pool nodes-1-2-3-4\." 3 3 || test_fail
+check_log_messages "T00:0.:..Z Added pool nodes-1-2-3\." 1 1 || test_fail
+check_log_messages "T00:0.:..Z Removed pool nodes-1-2-3\." 1 1 || test_fail
+check_log_messages "T00:0.:..Z Added source ID#" 2 2 || test_fail
+check_log_messages "T00:0.:..Z Added source 192.168.123.[1234]" 2 2 || test_fail
+check_log_messages "T00:0.:..Z Removed source 192.168.123.[1234]" 4 4 || test_fail
+
+check_chronyc_output "^200 OK
+0 sources online
+0 sources offline
+4 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+4 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+4 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+4 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+3 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+3 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+3 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+5 sources with unknown address
+200 OK
+200 OK
+3 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+5 sources with unknown address
+200 OK
+200 OK
+4 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+5 sources with unknown address
+200 OK
+200 OK
+4 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+5 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+1 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address
+200 OK
+200 OK
+0 sources online
+0 sources offline
+0 sources doing burst \(return to online\)
+0 sources doing burst \(return to offline\)
+0 sources with unknown address$" || test_fail
+
+check_packet_interval || test_fail
+
+test_pass
diff --git a/test/simulation/test.common b/test/simulation/test.common
index 42a2917b..7eb348e3 100644
--- a/test/simulation/test.common
+++ b/test/simulation/test.common
@@ -39,6 +39,7 @@ default_refclock_jitter=""
default_refclock_offset=0.0
default_update_interval=0
+default_update_executable=""
default_shift_pll=2
default_server_strata=1
@@ -442,7 +443,9 @@ run_simulation() {
-o tmp/log.offset -f tmp/log.freq -p tmp/log.packets \
-R $(awk "BEGIN {print $update_interval < 0 ? 2^-($update_interval) : 1}") \
-r $(awk "BEGIN {print $max_sync_time * 2^$update_interval}") \
- -l $(awk "BEGIN {print $limit * 2^$update_interval}") && test_ok || test_error
+ -l $(awk "BEGIN {print $limit * 2^$update_interval}") \
+ $([ "$update_executable" != "" ] && printf "%s" "-e $update_executable") && \
+ test_ok || test_error
}
run_test() {

View File

@ -1,5 +1,5 @@
%global _hardened_build 1
%global clknetsim_ver 40bb97
%global clknetsim_ver cdd694
%bcond_without debug
%bcond_without nts
@ -37,6 +37,11 @@ Patch5: chrony-refclkreach.patch
Patch6: chrony-docrefresh.patch
# improve logging of selection failures
Patch7: chrony-logselect.patch
# fix sourcedir reloading to not multiply sources
Patch8: chrony-sourcedir.patch
# revert clknetsim changes in PHC breaking old refclock tests
Patch20: clknetsim-revert-phc.patch
BuildRequires: gnutls-devel libcap-devel libedit-devel pps-tools-devel
BuildRequires: gcc gcc-c++ make bison systemd gnupg2
@ -74,6 +79,11 @@ service to other computers in the network.
%patch5 -p1
%patch6 -p1 -b .docrefresh
%patch7 -p1
%patch8 -p1
pushd clknetsim-*-%{clknetsim_ver}*
%patch20 -R -p1
popd
%{?gitpatch: echo %{version}-%{gitpatch} > version.txt}

View File

@ -0,0 +1,64 @@
commit 1205197f2e15166a47fa1817feaf3587738fb37a
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Wed Nov 27 16:03:19 2024 +0100
avoid timestamps from future in PTP_SYS_OFFSET_EXTENDED
diff --git a/client.c b/client.c
index 065eddf..32796e0 100644
--- a/client.c
+++ b/client.c
@@ -2065,24 +2065,24 @@ int ioctl(int fd, unsigned long request, ...) {
} else if (request == PTP_SYS_OFFSET_EXTENDED && fd == REFCLK_FD) {
struct ptp_sys_offset_extended *sys_off = va_arg(ap, struct ptp_sys_offset_extended *);
struct timespec ts, ts1, ts2;
+ double delay;
int i;
if (sys_off->n_samples > PTP_MAX_SAMPLES)
sys_off->n_samples = PTP_MAX_SAMPLES;
for (i = 0; i < sys_off->n_samples; i++) {
+ clock_gettime(CLOCK_REALTIME, &ts2);
clock_gettime(REFCLK_ID, &ts);
- sys_off->ts[i][1].sec = ts.tv_sec;
- sys_off->ts[i][1].nsec = ts.tv_nsec;
- }
-
- clock_gettime(CLOCK_REALTIME, &ts);
- for (i = 0; i < sys_off->n_samples; i++) {
- ts1 = ts, ts2 = ts;
- add_to_timespec(&ts1, -get_phc_delay(-1));
- add_to_timespec(&ts2, get_phc_delay(1));
+ delay = get_phc_delay(1);
+ add_to_timespec(&ts, -delay);
+ delay += get_phc_delay(-1);
+ ts1 = ts2;
+ add_to_timespec(&ts1, -delay);
sys_off->ts[i][0].sec = ts1.tv_sec;
sys_off->ts[i][0].nsec = ts1.tv_nsec;
+ sys_off->ts[i][1].sec = ts.tv_sec;
+ sys_off->ts[i][1].nsec = ts.tv_nsec;
sys_off->ts[i][2].sec = ts2.tv_sec;
sys_off->ts[i][2].nsec = ts2.tv_nsec;
}
commit 8b8831d98df1fca21288a9bc18c6a8fbfe6874a6
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Wed Nov 27 16:06:40 2024 +0100
round nanoseconds in PTP_SYS_OFFSET* delay adjustments
diff --git a/client.c b/client.c
index 32796e0..0e235a6 100644
--- a/client.c
+++ b/client.c
@@ -794,7 +794,7 @@ static void normalize_timespec(struct timespec *tp) {
static void add_to_timespec(struct timespec *tp, double offset) {
tp->tv_sec += floor(offset);
- tp->tv_nsec += (offset - floor(offset)) * 1e9;
+ tp->tv_nsec += round((offset - floor(offset)) * 1e9);
normalize_timespec(tp);
}

View File

@ -1,3 +1,3 @@
SHA512 (chrony-4.6.1.tar.gz) = 646ae08f2587366236796f2399d8ab3eb570979e0d82f5d13f5cec49939054c876cc93dc20c8d38e105fd3500e1720d05a223a15076783cd882d0de43afd9c7e
SHA512 (chrony-4.6.1-tar-gz-asc.txt) = 992b706636bf3a7eb6d502562a4990c9d8e20e5f3011d2cdb2ceb32220e9a1c2bfa6eca767212cee49b811823872602dc33f9e7201a7f9a93cc9c90e81b1db49
SHA512 (clknetsim-40bb97.tar.gz) = d0085340a7219dedbe1298f0c709824bcf6f698207cd1be87de38d108b829cd771ac0ea720ee83de3810c4530664a22e122f513516f1174bb9139eddbd359590
SHA512 (clknetsim-cdd694.tar.gz) = 289641461bd8c7227547478ba8cd51b7a114da3e34c994fe652382b0fb4df386c8734585bbcfa3ee5b99891cc6eef305997c5a7d92ea06b2cc6e94480aea5e75