[BUG] timekeeping: unprivileged clock_settime can change an enabled auxiliary clock

From: shaos

Date: Mon Oct 19 2026 - 20:37:37 EST


Hello,

aux_clock_set() validates the requested timespec and clock state but performs no permission check. After an administrator enables CLOCK_AUX0, a process with no capabilities can set the system-wide auxiliary clock with clock_settime(). The same clock's adjtime path and CLOCK_REALTIME setter both reject the same caller.

HEAD commit: fe2ec83746e501645709761605c2464a44fd2929
git tree: upstream Linux checkout, local branch master
source version: Linux 7.3.0-rc4-70-gfe2ec83746e50
compiler: gcc 11.4.0, GNU ld 2.38 (from the kernel build banner)

console output:
https://gist.githubusercontent.com/shaos26/189eb1fec9f2b4e69e979642496f5c54/raw/75acb2f68b89a64dd4719f2493e4c2a161e38cb1/console-output.txt
kernel config:
https://gist.githubusercontent.com/shaos26/189eb1fec9f2b4e69e979642496f5c54/raw/01c9b3f973d527975537280bd7631127537531e0/kernel-config.txt
reproducer:
https://gist.githubusercontent.com/shaos26/189eb1fec9f2b4e69e979642496f5c54/raw/003a5649dccbd0218da367d906093594ddf3c8c9/poc.c

Build the kernel from HEAD with the attached reproduction config. The PoC acts as /init, mounts proc and sysfs, runs the test in a child, then powers off the disposable VM.

mkdir -p build rootfs
cp kernel-config.txt build/.config
make O=build olddefconfig
make O=build -j"$(nproc)" bzImage
gcc -O2 -static -Wall -Wextra -o poc poc.c
cp poc rootfs/init
(cd rootfs && find init | cpio -o -H newc --owner=0:0) | gzip -9 > initramfs.cpio.gz
timeout 120 qemu-system-x86_64 -kernel build/arch/x86/boot/bzImage \
-initrd initramfs.cpio.gz -append "console=ttyS0 rdinit=/init panic=-1 loglevel=4 nokaslr" \
-nographic -m 1024 -smp 1 -accel tcg -no-reboot 2>&1 | tee run.log

Two fresh minimal-kernel boots returned success for clock_settime(CLOCK_AUX0) and read back the injected value. CLOCK_REALTIME settime and CLOCK_AUX0 adjtime returned EPERM; disabled CLOCK_AUX1 returned ENODEV.

Impact and prerequisites:
A local unprivileged process can alter a globally visible auxiliary time domain after an administrator enables it. This can disrupt consumers of that clock. It does not change CLOCK_REALTIME, CLOCK_MONOTONIC, or the core timekeeper, and no memory corruption or privilege escalation is demonstrated.

Validation: Two fresh positive boots returned success for the unprivileged CLOCK_AUX0 set and read back the injected value. CLOCK_REALTIME and CLOCK_AUX0 adjtime returned EPERM; disabled CLOCK_AUX1 returned ENODEV.

Thanks,

shaos