Message ID | 20250303161345.3053496-3-wwasko@nvidia.com (mailing list archive) |
---|---|
State | New |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Permission checks for dynamic POSIX clocks | expand |
On Mon, Mar 03 2025 at 18:13, Wojtek Wasko wrote: > 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>
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c index bf6468c56419..4380e6ddb849 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 4e114e34a6e0..fe963384d5c2 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; }