Re: [PATCH 6.12 002/169] ptp: Add PHC file mode checks. Allow RO adjtime() without FMODE_WRITE.

Jan Lübbe
2026-02-11T10:47:59Z

Hi,

these new permission checks break chrony < 4.8 (as used in Debian stable) when
using the PHC reclock with extpps mode, as it's opening the device without
O_RDWR.

chrony 4.8 is fixed:
https://gitlab.com/chrony/chrony/-/commit/f78e4681eff71d941fab3be5ee406d920a155a20

I've also reported this to Debian:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1127659

Regards,
Jan

On Wed, 2026-01-28 at 16:21 +0100, Greg Kroah-Hartman wrote:
> 6.12-stable review patch.  If anyone has any objections, please let me know.
>
> ------------------
>
> From: Wojtek Wasko <wwasko@nvidia.com>
>
> [ Upstream commit b4e53b15c04e3852949003752f48f7a14ae39e86 ]
>
> Many devices implement highly accurate clocks, which the kernel manages
> as PTP Hardware Clocks (PHCs). Userspace applications rely on these
> clocks to timestamp events, trace workload execution, correlate
> timescales across devices, and keep various clocks in sync.
>
> The kernel’s current implementation of PTP clocks does not enforce file
> permissions checks for most device operations except for POSIX clock
> operations, where file mode is verified in the POSIX layer before
> forwarding the call to the PTP subsystem. Consequently, it is common
> practice to not give unprivileged userspace applications any access to
> PTP clocks whatsoever by giving the PTP chardevs 600 permissions. An
> example of users running into this limitation is documented in [1].
> Additionally, POSIX layer requires WRITE permission even for readonly
> adjtime() calls which are used in PTP layer to return current frequency
> offset applied to the PHC.
>
> Add permission checks for functions that modify the state of a PTP
> device. Continue enforcing permission checks for POSIX clock operations
> (settime, adjtime) in the POSIX layer. Only require WRITE access for
> dynamic clocks adjtime() if any flags are set in the modes field.
>
> [1] https://lists.nwtime.org/sympa/arc/linuxptp-users/2024-01/msg00036.html
>
> Changes in v4:
> - Require FMODE_WRITE in ajtime() only for calls modifying the clock in
>   any way.
>
> Acked-by: Richard Cochran <richardcochran@gmail.com>
> Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
> Signed-off-by: Wojtek Wasko <wwasko@nvidia.com>
> Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: David S. Miller <davem@davemloft.net>
> Signed-off-by: Sasha Levin <sashal@kernel.org>
> ---
>  drivers/ptp/ptp_chardev.c | 16 ++++++++++++++++
>  kernel/time/posix-clock.c |  2 +-
>  2 files changed, 17 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
> index bf6468c56419c..4380e6ddb8495 100644
> --- a/drivers/ptp/ptp_chardev.c
> +++ b/drivers/ptp/ptp_chardev.c
> @@ -205,6 +205,10 @@ long ptp_ioctl(struct posix_clock_context *pccontext,
> unsigned int cmd,
>
>   case PTP_EXTTS_REQUEST:
>   case PTP_EXTTS_REQUEST2:
> + if ((pccontext->fp->f_mode & FMODE_WRITE) == 0) {
> + err = -EACCES;
> + break;
> + }
>   memset(&req, 0, sizeof(req));
>
>   if (copy_from_user(&req.extts, (void __user *)arg,
> @@ -246,6 +250,10 @@ long ptp_ioctl(struct posix_clock_context *pccontext,
> unsigned int cmd,
>
>   case PTP_PEROUT_REQUEST:
>   case PTP_PEROUT_REQUEST2:
> + if ((pccontext->fp->f_mode & FMODE_WRITE) == 0) {
> + err = -EACCES;
> + break;
> + }
>   memset(&req, 0, sizeof(req));
>
>   if (copy_from_user(&req.perout, (void __user *)arg,
> @@ -314,6 +322,10 @@ long ptp_ioctl(struct posix_clock_context *pccontext,
> unsigned int cmd,
>
>   case PTP_ENABLE_PPS:
>   case PTP_ENABLE_PPS2:
> + if ((pccontext->fp->f_mode & FMODE_WRITE) == 0) {
> + err = -EACCES;
> + break;
> + }
>   memset(&req, 0, sizeof(req));
>
>   if (!capable(CAP_SYS_TIME))
> @@ -456,6 +468,10 @@ long ptp_ioctl(struct posix_clock_context *pccontext,
> unsigned int cmd,
>
>   case PTP_PIN_SETFUNC:
>   case PTP_PIN_SETFUNC2:
> + if ((pccontext->fp->f_mode & FMODE_WRITE) == 0) {
> + err = -EACCES;
> + break;
> + }
>   if (copy_from_user(&pd, (void __user *)arg, sizeof(pd))) {
>   err = -EFAULT;
>   break;
> diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c
> index 4e114e34a6e0a..fe963384d5c2a 100644
> --- a/kernel/time/posix-clock.c
> +++ b/kernel/time/posix-clock.c
> @@ -252,7 +252,7 @@ static int pc_clock_adjtime(clockid_t id, struct
> __kernel_timex *tx)
>   if (err)
>   return err;
>
> - if ((cd.fp->f_mode & FMODE_WRITE) == 0) {
> + if (tx->modes && (cd.fp->f_mode & FMODE_WRITE) == 0) {
>   err = -EACCES;
>   goto out;
>   }

--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |