• 1.0.0-8 83c857211d

    amnesia released this 2026-07-11 21:02:16 +02:00 | 0 commits to main since this release

    sdwdate (LainOS Layer 02 port) ~ Changelog

    1.0.0-8 ~ /etc/adjtime permission fix

    Bug Fix

    • Fixed hwclock: cannot open /etc/adjtime: Permission denied, occurring after hwclock --systohc successfully ran (following the 1.0.0-5 fix) but couldn't read/write its clock-drift calibration file. /etc/adjtime defaults to 0644, root-owned, with no group access.
    • Fix: added a checkpath call in the init script's start_pre() granting group access (root:sdwdate, mode 0664).
    • An initial attempt at this fix (in 1.0.0-7, not separately released) used checkpath -g sdwdate, an option that doesn't exist ~ checkpath has no -g flag. Corrected to checkpath -f -m 0664 -o root:sdwdate /etc/adjtime, using -o user:group instead.
    • Verified end-to-end: forced a full service restart (guaranteeing a first-sync, which always uses the instant /bin/date + hwclock path regardless of correction size), confirmed the log shows Instantly setting the time, a successful /bin/date output, and no adjtime error ~ hwclock --systohc completed silently and successfully this time.

    This is the third and final permission gap found through fresh-install testing in a clean KVM guest (after the RTC device access and hwclock CAP_SYS_TIME grant in 1.0.0-5). All three were only caught by testing on a genuinely clean install rather than continuing to iterate on an already-patched development machine.


    Downloads
  • 1.0.0-6 8aabaa41f3

    amnesia released this 2026-07-11 20:33:18 +02:00 | 1 commits to main since this release

    sdwdate (LainOS Layer 02 port) ~ Changelog

    1.0.0-6 ~ Tor consensus check fix (fresh installs)

    Bug Fix

    • Fixed Tor Consensus Time Sanity Check: error: Could not request from Tor control connection. error: <class 'AttributeError'> on fresh installs, causing every time source to report remote_status: False and fail. Root cause: the sdwdate system user was never added to the tor group, so it couldn't read Tor's control-port authentication cookie (/var/lib/tor/control_auth_cookie, mode 0640, owned tor:tor) needed for the consensus check. This fix had previously only been applied manually, live, on one already-installed system, and was never actually added to the package itself.
    • Fix: added usermod -aG tor sdwdate to both the package's post_install/post_upgrade hooks and the OpenRC init script's start_pre() ~ the latter for the same Calamares-chroot reliability reason established for the log file fix in 1.0.0-3 (install-time hooks have been found not to reliably survive Calamares' chroot-based install process; init-script-time fixes run fresh on every start regardless of install method).
    • Verified end-to-end on a fresh KVM ISO install: confirmed sdwdate was missing from the tor group before the fix, rebuilt and reinstalled the package, forced a full service restart, confirmed group membership took effect (id sdwdate showing tor in the group list), and observed a complete sync cycle with Tor Consensus Time Sanity Check: sane on all three contacted onion sources.

    Note: this bug and the 1.0.0-5 hardware clock fix were both found through genuine fresh-install testing in a KVM guest, not by continuing to test on an already-patched development machine ~ neither would have surfaced from further testing on a system that had already accumulated manual live fixes.


    Downloads
  • 1.0.0-5 c00523a20b

    amnesia released this 2026-07-11 19:43:32 +02:00 | 2 commits to main since this release

    sdwdate (LainOS Layer 02 port) ~ Changelog

    1.0.0-5 ~ Hardware clock sync fix

    Bug Fix

    • Fixed FileNotFoundError: [Errno 2] No such file or directory: '/usr/bin/leaprun' during a real sync cycle. Two call sites in sdwdate.py (run_sclockadj_and_hwclock() and run_sclockadj()) shell out to leaprun sdwdate-sync-hwclock after applying a time correction, to sync the hardware clock (hwclock --systohc) so the correction survives a reboot. leaprun is part of Kicksecure's privleap privilege-delegation tool, not used on LainOS ~ this call site was missed during the initial port (the CLI wrapper's leaprun call was caught and fixed earlier; these two daemon-internal calls were not).
    • Fix: patched both call sites to invoke /usr/bin/hwclock --systohc directly.
    • This surfaced a second, distinct permission issue: hwclock: ioctl(RTC_SET_TIME) to /dev/rtc to set the time failed: Permission denied. /dev/rtc0 was root-only (0600) with no group access, and even after granting access, the RTC_SET_TIME ioctl itself additionally requires the calling process to hold CAP_SYS_TIME beyond plain file permissions.
    • Fix:
      • Added a udev rule (99-lainos-sdwdate-rtc.rules) granting the sdwdate group read/write access to /dev/rtc0 (mode 0660).
      • Granted CAP_SYS_TIME to /usr/bin/hwclock via setcap, alongside the existing grants for sdwdate, sclockadj, and /bin/date.
    • Verified end-to-end from a clean package install: forced a real 30-second clock discrepancy, triggered a fresh sync, confirmed sclockadj completed, Syncing hardware clock logged with no error, and the sync loop returned to its normal sleep cycle ~ the full corrected chain, not just a zero-diff no-op.

    Downloads
  • 1.0.0-4 e950798ecc

    amnesia released this 2026-07-11 17:49:46 +02:00 | 3 commits to main since this release

    sdwdate (lainOS layer 02 port) ~ Changelog

    1.0.0-4 ~ First-sync permission fix

    Bug Fix

    • Fixed date: cannot set date: Operation not permitted on sdwdate's first successful sync after being enabled (or after any hard clock-jump correction). sdwdate's own code (set_time_using_date() in sdwdate.py) shells out directly to /bin/date --set for the first sync and any explicit hard jump, rather than the gradual sclockadj path used for all subsequent, smaller corrections. This path was missing the CAP_SYS_TIME capability grant that sdwdate and sclockadj already had.
    • Fix: granted CAP_SYS_TIME to /bin/date via setcap in the init script's start_pre(), alongside the existing grants for sdwdate and sclockadj.
    • Note on scope: unlike the other two setcap grants (which apply to single-purpose binaries only the sdwdate user ever invokes), /bin/date is a general system utility used by every user on the system. This capability grant is file-wide, meaning any local user could technically use date --set to change the system clock, not just the sdwdate daemon. CAP_SYS_TIME alone grants no other capability (no file access, no broader privilege escalation path), and this was accepted as a reasonable, documented tradeoff rather than patching upstream's source to avoid the /bin/date call entirely for the first-sync case. Commented clearly in the init script for future reference.
    • Verified fixed: a forced first-sync (via lainos-sdwdate disable / enable) completed successfully with the correction applied and no permission error.
    Downloads
  • 1.0.0-3 e950798ecc

    amnesia released this 2026-07-10 22:58:57 +02:00 | 3 commits to main since this release

    sdwdate (lainOS layer 02 port) ~ Changelog

    1.0.0-3 ~ Fresh-install log permission fix

    Bug Fix

    • Fixed start-stop-daemon: unable to open the logfile for stdout '/var/log/sdwdate.log': Permission denied on fresh installs. The package's post_install hook correctly creates and chowns /var/log/sdwdate.log, but this was found not to reliably survive Calamares' ISO install-time chroot execution ~ confirmed present via a live pacman -U on an already-running system, but absent on a fresh Calamares-installed system despite the install script containing identical touch/chown logic.
    • Moved log file creation into the OpenRC init script's start_pre() (via checkpath -f), matching the existing, already-reliable pattern used for /run/sdwdate, /var/lib/sdwdate, and /var/lib/sdwdate-forbidden-temp. This runs fresh on every service start regardless of install method, rather than depending on a one-time install hook.
    • Verified fixed end-to-end on a fresh ISO install: checkpath correctly creates and owns the log file, sdwdate starts cleanly, lainos-sdwdate status reports it running.
    Downloads
  • sdwdate-1.0.0-1 1580da95ee

    amnesia released this 2026-07-10 18:19:31 +02:00 | 7 commits to main since this release

    sdwdate (lainOS layer 02 port) ~ Changelog

    1.0.0-1 (2026-07-10) ~ Initial port

    First working LainOS Layer 02 / OpenRC port of Kicksecure's sdwdate.

    Ported from upstream (GPLv3):

    • Core Python daemon and sclockadj C helper (compiled with upstream's full hardened compiler flag set)
    • Default time-source pool configuration
    • url_to_unixtime per-source fetcher

    New, LainOS-native components (not vendored from Kicksecure):

    • sanitize_string / guimessages.translations ~ minimal reimplementations of two cosmetic Kicksecure helper packages
    • lainos-minimum-unixtime-show ~ reimplementation of the anti-replay-protection floor-timestamp mechanism (replaces Kicksecure's timesanitycheck package dependency)
    • lainos-onion-time-pre-script ~ no-op replacement for upstream's privleap/AppArmor-dependent Tor-restart-request signaling (not applicable on LainOS)
    • OpenRC init script, translated from upstream's systemd unit: need tor/after tor dependency ordering, setcap cap_sys_time+ep in place of AmbientCapabilities=CAP_SYS_TIME, required runtime directories created in start_pre()

    Deliberately not ported: AppArmor profiles, privleap integration, Qubes-specific conditionals, the Tor-restart-request file-watcher mechanism, and dev-only test scripts. See README for full rationale on each.

    Known gaps relative to upstream:

    • No seccomp/SystemCallFilter equivalent yet (OpenRC has no direct translation; a wrapper-based approach similar to protocol7-core's daemons would be needed)
    • Tor-restart-on-request is not implemented (daemon runs fine without it; only affects the specific edge case upstream's file-watcher mechanism handles)

    Verified working end-to-end (2026-07-10): real onion time sources contacted over Tor, Tor consensus sanity checks passing, correct median computation across sources, sclockadj correctly applying a real (small) gradual clock correction, all with a genuinely accurate result.

    Companion change (in lainos-utils): added lainos-sdwdate toggle script (enable/disable/status) to switch between chrony (default) and sdwdate, since sdwdate has no fallback if Tor is unreachable and the two should not run simultaneously.


    Bugs found and fixed during initial porting/testing

    For reference, the real issues found getting this daemon running for the first time, each confirmed via actual testing rather than assumed:

    1. /usr/bin/sdwdate (the interactive CLI wrapper) calls leaprun, a privleap command not present on LainOS ~ resolved by pointing the OpenRC service at the real daemon entry point (/usr/libexec/sdwdate/sdwdate) directly, matching what upstream's own systemd unit does (the wrapper script was never meant to be the service entry point).
    2. Python package files installed to Debian's dist-packages convention; Arch uses site-packages ~ fixed install paths in the PKGBUILD.
    3. sdwdate system user's home directory didn't match what the daemon's status-file logic expects (/run/sdwdate) ~ fixed via usermod/.install.
    4. /var/lib/sdwdate-forbidden-temp (a directory upstream's code creates unconditionally, originally to work around an AppArmor constraint that doesn't apply here) wasn't being created ~ added to the init script's start_pre().
    5. /usr/libexec/helper-scripts/onion-time-pre-script was missing entirely (privleap/AppArmor-specific upstream component) ~ replaced with the no-op lainos-onion-time-pre-script described above.
    6. url_to_unixtime wasn't installed at all (missed in the initial package file list) ~ added.
    7. Tor's control-port authentication cookie (/var/lib/tor/control_auth_cookie) wasn't readable by the sdwdate user, causing Tor consensus sanity checks to fail even though basic SOCKS-based fetching worked ~ fixed by adding sdwdate to the tor group.
    Downloads