diff --git a/qubes-rpc/qubes-sync-clock b/qubes-rpc/qubes-sync-clock index de508f1e6..7065efb3c 100755 --- a/qubes-rpc/qubes-sync-clock +++ b/qubes-rpc/qubes-sync-clock @@ -18,21 +18,49 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # -import sys +import os import re import subprocess +import sys def main(): - stdin = sys.stdin.read(25) - - untrusted_date_out = stdin.strip() - - if not re.match(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+00:?00$', untrusted_date_out): + os.environ['LC_ALL'] = 'C' + untrusted_date_out = sys.stdin.buffer.read(36) + try: + untrusted_date_out.decode('ascii', 'strict') + except UnicodeDecodeError: + sys.stderr.write('Received non-ASCII date, aborting!\n') + sys.exit(1) + untrusted_date_len = len(untrusted_date_out) + if untrusted_date_len == 36: # new format, nanosecond precision + regexp = rb'\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2},[0-9]{9}\+00:00\n\Z' + precision = b'ns' + elif untrusted_date_len == 26: # old format, second precision + regexp = rb'\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+00:00\n\Z' + precision = b'seconds' + else: + sys.stderr.write('Invalid date length (expected 26 or 36 bytes, got {})' + ', aborting!\n'.format(untrusted_date_len)) + sys.exit(1) + if untrusted_date_out[-7:] != b'+00:00\n': + sys.stderr.write('Date not in UTC, aborting!\n') + sys.exit(1) + if not re.match(regexp, untrusted_date_out): sys.stderr.write('Invalid date received, aborting!\n') sys.exit(1) + # this time is arbitrary, something better should be used instead + if untrusted_date_out[:19] <= b'2022-07-10T17:08:31': + sys.stderr.write('Received a date older than this program, aborting!\n') + sys.exit(1) date_out = untrusted_date_out - subprocess.check_call(['date', '-u', '-Iseconds', '-s', date_out], - stdout=subprocess.DEVNULL) + try: + subprocess.check_call([b'date', b'-u', b'-I' + precision, b'-s', + date_out[:-1]], + stdout=subprocess.DEVNULL) + except subprocess.CalledProcessError as e: + # input is trusted here, so it can be safely printed + sys.stderr.write('Unable to set the date: process {!r} failed.\n'.format(e.cmd)) + sys.exit(e.returncode) if __name__ == '__main__': main() diff --git a/qubes-rpc/qubes.GetDate b/qubes-rpc/qubes.GetDate index ebd9ebf90..bb3af9b0f 100755 --- a/qubes-rpc/qubes.GetDate +++ b/qubes-rpc/qubes.GetDate @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh -- # # The Qubes OS Project, http://www.qubes-os.org # @@ -16,7 +16,9 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# -date -u -Iseconds +export LC_ALL=C +case ${1-} in +'') exec date -u -Iseconds;; +nanosecond|nanoseconds|ns|*) exec date -u -Ins;; +esac diff --git a/qubes-rpc/qvm-sync-clock b/qubes-rpc/qvm-sync-clock index eaaf6f69d..9f0b0c0db 100644 --- a/qubes-rpc/qvm-sync-clock +++ b/qubes-rpc/qvm-sync-clock @@ -19,4 +19,5 @@ # # shellcheck disable=SC2016 -qrexec-client-vm '$default' qubes.GetDate /usr/lib/qubes/qubes-sync-clock +qrexec-client-vm --filter-escape-chars-stderr '@default' \ + qubes.GetDate+nanoseconds /usr/lib/qubes/qubes-sync-clock diff --git a/vm-systemd/qubes-sync-time.service b/vm-systemd/qubes-sync-time.service index e611a42ab..f802ce5fe 100644 --- a/vm-systemd/qubes-sync-time.service +++ b/vm-systemd/qubes-sync-time.service @@ -5,4 +5,5 @@ ConditionPathExists=!/var/run/qubes-service/clocksync [Service] ExecStart=/usr/bin/qvm-sync-clock +Type=oneshot User=root