netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v4 0/3] Permission checks for dynamic POSIX clocks
@ 2025-03-03 16:13 Wojtek Wasko
  2025-03-03 16:13 ` [PATCH net-next v4 1/3] posix-clock: Store file pointer in struct posix_clock_context Wojtek Wasko
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Wojtek Wasko @ 2025-03-03 16:13 UTC (permalink / raw)
  To: netdev
  Cc: richardcochran, vadim.fedorenko, kuba, horms, anna-maria,
	frederic, pabeni, tglx

Dynamic clocks - such as PTP clocks - extend beyond the standard POSIX
clock API by using ioctl calls. While file permissions are enforced for
standard POSIX operations, they are not implemented for ioctl calls,
since the POSIX layer cannot differentiate between calls which modify
the clock's state (like enabling PPS output generation) and those that
don't (such as retrieving the clock's PPS capabilities).

On the other hand, drivers implementing the dynamic clocks lack the
necessary information context to enforce permission checks themselves.

Additionally, POSIX clock layer requires the WRITE permission even for
readonly adjtime() operations before invoking the callback.

Add a struct file pointer to the POSIX clock context and use it to
implement the appropriate permission checks on PTP chardevs. Permit
readonly adjtime() for dynamic clocks. Add a readonly option to testptp.

Changes in v4:
- Allow readonly adjtime() for dynamic clocks, as suggested by Thomas

Changes in v3:
- Reword the log message for commit against posix-clock and fix
  documentation of struct posix_clock_context, as suggested by Thomas

Changes in v2:
- Store file pointer in POSIX clock context rather than fmode in the PTP
  clock's private data, as suggested by Richard.
- Move testptp.c changes into separate patch.

Wojtek Wasko (3):
  posix-clock: Store file pointer in struct posix_clock_context
  ptp: Add PHC file mode checks. Allow RO adjtime() without FMODE_WRITE.
  testptp: Add option to open PHC in readonly mode

 drivers/ptp/ptp_chardev.c             | 16 ++++++++++++
 include/linux/posix-clock.h           |  6 ++++-
 kernel/time/posix-clock.c             |  3 ++-
 tools/testing/selftests/ptp/testptp.c | 37 +++++++++++++++++----------
 4 files changed, 46 insertions(+), 16 deletions(-)

-- 
2.43.5


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH net-next v4 1/3] posix-clock: Store file pointer in struct posix_clock_context
  2025-03-03 16:13 [PATCH net-next v4 0/3] Permission checks for dynamic POSIX clocks Wojtek Wasko
@ 2025-03-03 16:13 ` Wojtek Wasko
  2025-03-03 16:13 ` [PATCH net-next v4 2/3] ptp: Add PHC file mode checks. Allow RO adjtime() without FMODE_WRITE Wojtek Wasko
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Wojtek Wasko @ 2025-03-03 16:13 UTC (permalink / raw)
  To: netdev
  Cc: richardcochran, vadim.fedorenko, kuba, horms, anna-maria,
	frederic, pabeni, tglx

File descriptor based pc_clock_*() operations of dynamic posix clocks
have access to the file pointer and implement permission checks in the
generic code before invoking the relevant dynamic clock callback.

Character device operations (open, read, poll, ioctl) do not implement a
generic permission control and the dynamic clock callbacks have no
access to the file pointer to implement them.

Extend struct posix_clock_context with a struct file pointer and
initialize it in posix_clock_open(), so that all dynamic clock callbacks
can access it.

Acked-by: Richard Cochran <richardcochran@gmail.com>
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Wojtek Wasko <wwasko@nvidia.com>
---
 include/linux/posix-clock.h | 6 +++++-
 kernel/time/posix-clock.c   | 1 +
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/include/linux/posix-clock.h b/include/linux/posix-clock.h
index ef8619f48920..a500d3160fe8 100644
--- a/include/linux/posix-clock.h
+++ b/include/linux/posix-clock.h
@@ -95,10 +95,13 @@ struct posix_clock {
  * struct posix_clock_context - represents clock file operations context
  *
  * @clk:              Pointer to the clock
+ * @fp:               Pointer to the file used to open the clock
  * @private_clkdata:  Pointer to user data
  *
  * Drivers should use struct posix_clock_context during specific character
- * device file operation methods to access the posix clock.
+ * device file operation methods to access the posix clock. In particular,
+ * the file pointer can be used to verify correct access mode for ioctl()
+ * calls.
  *
  * Drivers can store a private data structure during the open operation
  * if they have specific information that is required in other file
@@ -106,6 +109,7 @@ struct posix_clock {
  */
 struct posix_clock_context {
 	struct posix_clock *clk;
+	struct file *fp;
 	void *private_clkdata;
 };
 
diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c
index 1af0bb2cc45c..4e114e34a6e0 100644
--- a/kernel/time/posix-clock.c
+++ b/kernel/time/posix-clock.c
@@ -129,6 +129,7 @@ static int posix_clock_open(struct inode *inode, struct file *fp)
 		goto out;
 	}
 	pccontext->clk = clk;
+	pccontext->fp = fp;
 	if (clk->ops.open) {
 		err = clk->ops.open(pccontext, fp->f_mode);
 		if (err) {
-- 
2.43.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net-next v4 2/3] ptp: Add PHC file mode checks. Allow RO adjtime() without FMODE_WRITE.
  2025-03-03 16:13 [PATCH net-next v4 0/3] Permission checks for dynamic POSIX clocks Wojtek Wasko
  2025-03-03 16:13 ` [PATCH net-next v4 1/3] posix-clock: Store file pointer in struct posix_clock_context Wojtek Wasko
@ 2025-03-03 16:13 ` Wojtek Wasko
  2025-03-03 19:33   ` Thomas Gleixner
  2025-03-03 16:13 ` [PATCH net-next v4 3/3] testptp: Add option to open PHC in readonly mode Wojtek Wasko
  2025-03-05 12:50 ` [PATCH net-next v4 0/3] Permission checks for dynamic POSIX clocks patchwork-bot+netdevbpf
  3 siblings, 1 reply; 6+ messages in thread
From: Wojtek Wasko @ 2025-03-03 16:13 UTC (permalink / raw)
  To: netdev
  Cc: richardcochran, vadim.fedorenko, kuba, horms, anna-maria,
	frederic, pabeni, tglx

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>
---
 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 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;
 	}
-- 
2.43.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net-next v4 3/3] testptp: Add option to open PHC in readonly mode
  2025-03-03 16:13 [PATCH net-next v4 0/3] Permission checks for dynamic POSIX clocks Wojtek Wasko
  2025-03-03 16:13 ` [PATCH net-next v4 1/3] posix-clock: Store file pointer in struct posix_clock_context Wojtek Wasko
  2025-03-03 16:13 ` [PATCH net-next v4 2/3] ptp: Add PHC file mode checks. Allow RO adjtime() without FMODE_WRITE Wojtek Wasko
@ 2025-03-03 16:13 ` Wojtek Wasko
  2025-03-05 12:50 ` [PATCH net-next v4 0/3] Permission checks for dynamic POSIX clocks patchwork-bot+netdevbpf
  3 siblings, 0 replies; 6+ messages in thread
From: Wojtek Wasko @ 2025-03-03 16:13 UTC (permalink / raw)
  To: netdev
  Cc: richardcochran, vadim.fedorenko, kuba, horms, anna-maria,
	frederic, pabeni, tglx

PTP Hardware Clocks no longer require WRITE permission to perform
readonly operations, such as listing device capabilities or listening to
EXTTS events once they have been enabled by a process with WRITE
permissions.

Add '-r' option to testptp to open the PHC in readonly mode instead of
the default read-write mode. Skip enabling EXTTS if readonly mode is
requested.

Acked-by: Richard Cochran <richardcochran@gmail.com>
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Signed-off-by: Wojtek Wasko <wwasko@nvidia.com>
---
 tools/testing/selftests/ptp/testptp.c | 37 +++++++++++++++++----------
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/tools/testing/selftests/ptp/testptp.c b/tools/testing/selftests/ptp/testptp.c
index 58064151f2c8..edc08a4433fd 100644
--- a/tools/testing/selftests/ptp/testptp.c
+++ b/tools/testing/selftests/ptp/testptp.c
@@ -140,6 +140,7 @@ static void usage(char *progname)
 		" -H val     set output phase to 'val' nanoseconds (requires -p)\n"
 		" -w val     set output pulse width to 'val' nanoseconds (requires -p)\n"
 		" -P val     enable or disable (val=1|0) the system clock PPS\n"
+		" -r         open the ptp clock in readonly mode\n"
 		" -s         set the ptp clock time from the system time\n"
 		" -S         set the system time from the ptp clock time\n"
 		" -t val     shift the ptp clock time by 'val' seconds\n"
@@ -188,6 +189,7 @@ int main(int argc, char *argv[])
 	int pin_index = -1, pin_func;
 	int pps = -1;
 	int seconds = 0;
+	int readonly = 0;
 	int settime = 0;
 	int channel = -1;
 	clockid_t ext_clockid = CLOCK_REALTIME;
@@ -200,7 +202,7 @@ int main(int argc, char *argv[])
 
 	progname = strrchr(argv[0], '/');
 	progname = progname ? 1+progname : argv[0];
-	while (EOF != (c = getopt(argc, argv, "cd:e:f:F:ghH:i:k:lL:n:o:p:P:sSt:T:w:x:Xy:z"))) {
+	while (EOF != (c = getopt(argc, argv, "cd:e:f:F:ghH:i:k:lL:n:o:p:P:rsSt:T:w:x:Xy:z"))) {
 		switch (c) {
 		case 'c':
 			capabilities = 1;
@@ -252,6 +254,9 @@ int main(int argc, char *argv[])
 		case 'P':
 			pps = atoi(optarg);
 			break;
+		case 'r':
+			readonly = 1;
+			break;
 		case 's':
 			settime = 1;
 			break;
@@ -308,7 +313,7 @@ int main(int argc, char *argv[])
 		}
 	}
 
-	fd = open(device, O_RDWR);
+	fd = open(device, readonly ? O_RDONLY : O_RDWR);
 	if (fd < 0) {
 		fprintf(stderr, "opening %s: %s\n", device, strerror(errno));
 		return -1;
@@ -436,14 +441,16 @@ int main(int argc, char *argv[])
 	}
 
 	if (extts) {
-		memset(&extts_request, 0, sizeof(extts_request));
-		extts_request.index = index;
-		extts_request.flags = PTP_ENABLE_FEATURE;
-		if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) {
-			perror("PTP_EXTTS_REQUEST");
-			extts = 0;
-		} else {
-			puts("external time stamp request okay");
+		if (!readonly) {
+			memset(&extts_request, 0, sizeof(extts_request));
+			extts_request.index = index;
+			extts_request.flags = PTP_ENABLE_FEATURE;
+			if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) {
+				perror("PTP_EXTTS_REQUEST");
+				extts = 0;
+			} else {
+				puts("external time stamp request okay");
+			}
 		}
 		for (; extts; extts--) {
 			cnt = read(fd, &event, sizeof(event));
@@ -455,10 +462,12 @@ int main(int argc, char *argv[])
 			       event.t.sec, event.t.nsec);
 			fflush(stdout);
 		}
-		/* Disable the feature again. */
-		extts_request.flags = 0;
-		if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) {
-			perror("PTP_EXTTS_REQUEST");
+		if (!readonly) {
+			/* Disable the feature again. */
+			extts_request.flags = 0;
+			if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) {
+				perror("PTP_EXTTS_REQUEST");
+			}
 		}
 	}
 
-- 
2.43.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next v4 2/3] ptp: Add PHC file mode checks. Allow RO adjtime() without FMODE_WRITE.
  2025-03-03 16:13 ` [PATCH net-next v4 2/3] ptp: Add PHC file mode checks. Allow RO adjtime() without FMODE_WRITE Wojtek Wasko
@ 2025-03-03 19:33   ` Thomas Gleixner
  0 siblings, 0 replies; 6+ messages in thread
From: Thomas Gleixner @ 2025-03-03 19:33 UTC (permalink / raw)
  To: Wojtek Wasko, netdev
  Cc: richardcochran, vadim.fedorenko, kuba, horms, anna-maria,
	frederic, pabeni

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>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next v4 0/3] Permission checks for dynamic POSIX clocks
  2025-03-03 16:13 [PATCH net-next v4 0/3] Permission checks for dynamic POSIX clocks Wojtek Wasko
                   ` (2 preceding siblings ...)
  2025-03-03 16:13 ` [PATCH net-next v4 3/3] testptp: Add option to open PHC in readonly mode Wojtek Wasko
@ 2025-03-05 12:50 ` patchwork-bot+netdevbpf
  3 siblings, 0 replies; 6+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-03-05 12:50 UTC (permalink / raw)
  To: Wojtek Wasko
  Cc: netdev, richardcochran, vadim.fedorenko, kuba, horms, anna-maria,
	frederic, pabeni, tglx

Hello:

This series was applied to netdev/net-next.git (main)
by David S. Miller <davem@davemloft.net>:

On Mon,  3 Mar 2025 18:13:42 +0200 you wrote:
> Dynamic clocks - such as PTP clocks - extend beyond the standard POSIX
> clock API by using ioctl calls. While file permissions are enforced for
> standard POSIX operations, they are not implemented for ioctl calls,
> since the POSIX layer cannot differentiate between calls which modify
> the clock's state (like enabling PPS output generation) and those that
> don't (such as retrieving the clock's PPS capabilities).
> 
> [...]

Here is the summary with links:
  - [net-next,v4,1/3] posix-clock: Store file pointer in struct posix_clock_context
    https://git.kernel.org/netdev/net-next/c/e859d375d169
  - [net-next,v4,2/3] ptp: Add PHC file mode checks. Allow RO adjtime() without FMODE_WRITE.
    https://git.kernel.org/netdev/net-next/c/b4e53b15c04e
  - [net-next,v4,3/3] testptp: Add option to open PHC in readonly mode
    https://git.kernel.org/netdev/net-next/c/76868642e427

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-03-05 12:50 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-03 16:13 [PATCH net-next v4 0/3] Permission checks for dynamic POSIX clocks Wojtek Wasko
2025-03-03 16:13 ` [PATCH net-next v4 1/3] posix-clock: Store file pointer in struct posix_clock_context Wojtek Wasko
2025-03-03 16:13 ` [PATCH net-next v4 2/3] ptp: Add PHC file mode checks. Allow RO adjtime() without FMODE_WRITE Wojtek Wasko
2025-03-03 19:33   ` Thomas Gleixner
2025-03-03 16:13 ` [PATCH net-next v4 3/3] testptp: Add option to open PHC in readonly mode Wojtek Wasko
2025-03-05 12:50 ` [PATCH net-next v4 0/3] Permission checks for dynamic POSIX clocks patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).