diff mbox series

[net] ptp: Ensure info->enable callback is always set

Message ID 20250122-ptp-enable-v1-1-979d3d24591d@weissschuh.net (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [net] ptp: Ensure info->enable callback is always set | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net
netdev/apply fail Patch does not apply to net-0

Commit Message

Thomas Weißschuh Jan. 22, 2025, 6:39 p.m. UTC
The ioctl and sysfs handlers unconditionally call the ->enable callback.
Not all drivers implement that callback, leading to NULL dereferences.
Example of affected drivers: ptp_s390.c, ptp_vclock.c and ptp_mock.c.

Instead use a dummy callback if no better was specified by the driver.

Fixes: d94ba80ebbea ("ptp: Added a brand new class driver for ptp clocks.")
Cc: stable@vger.kernel.org
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
 drivers/ptp/ptp_clock.c | 8 ++++++++
 1 file changed, 8 insertions(+)


---
base-commit: c4b9570cfb63501638db720f3bee9f6dfd044b82
change-id: 20250122-ptp-enable-831339c62428

Best regards,

Comments

Andrew Lunn Jan. 22, 2025, 8:15 p.m. UTC | #1
On Wed, Jan 22, 2025 at 07:39:31PM +0100, Thomas Weißschuh wrote:
> The ioctl and sysfs handlers unconditionally call the ->enable callback.
> Not all drivers implement that callback, leading to NULL dereferences.
> Example of affected drivers: ptp_s390.c, ptp_vclock.c and ptp_mock.c.

> +	if (!ptp->info->enable)
> +		ptp->info->enable = ptp_enable;

Is it possible that a driver has defined info as a const, and placed
it into read only memory? It is generally good practice to make
structures of ops read only to prevent some forms of attack.

	Andrew
Thomas Weißschuh Jan. 22, 2025, 9:40 p.m. UTC | #2
On 2025-01-22 21:15:50+0100, Andrew Lunn wrote:
> On Wed, Jan 22, 2025 at 07:39:31PM +0100, Thomas Weißschuh wrote:
> > The ioctl and sysfs handlers unconditionally call the ->enable callback.
> > Not all drivers implement that callback, leading to NULL dereferences.
> > Example of affected drivers: ptp_s390.c, ptp_vclock.c and ptp_mock.c.
> 
> > +	if (!ptp->info->enable)
> > +		ptp->info->enable = ptp_enable;
> 
> Is it possible that a driver has defined info as a const, and placed
> it into read only memory? It is generally good practice to make
> structures of ops read only to prevent some forms of attack.

The modified info struct is a subsystem-private copy and not the struct
passed by the driver. Also ptp_clock_register() requires a mutable
ops struct parameter anyways.
Jakub Kicinski Jan. 23, 2025, 4:03 a.m. UTC | #3
On Wed, 22 Jan 2025 19:39:31 +0100 Thomas Weißschuh wrote:
> Subject: [PATCH net] ptp: Ensure info->enable callback is always set

The CI says this didn't apply to net/main at the time of posting.
It applies now, since we forward the trees. Could you repost, please?
We don't have a way to re-ingest the patch once it fails on the first
try, unfortunately.
Richard Cochran Jan. 23, 2025, 3 p.m. UTC | #4
On Wed, Jan 22, 2025 at 07:39:31PM +0100, Thomas Weißschuh wrote:
> The ioctl and sysfs handlers unconditionally call the ->enable callback.
> Not all drivers implement that callback, leading to NULL dereferences.
> Example of affected drivers: ptp_s390.c, ptp_vclock.c and ptp_mock.c.
> 
> Instead use a dummy callback if no better was specified by the driver.
> 
> Fixes: d94ba80ebbea ("ptp: Added a brand new class driver for ptp clocks.")
> Cc: stable@vger.kernel.org
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>

Acked-by: Richard Cochran <richardcochran@gmail.com>
diff mbox series

Patch

diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index b932425ddc6a3789504164a69d1b8eba47da462c..35a5994bf64f6373c08269d63aaeac3f4ab31ff0 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -217,6 +217,11 @@  static int ptp_getcycles64(struct ptp_clock_info *info, struct timespec64 *ts)
 		return info->gettime64(info, ts);
 }
 
+static int ptp_enable(struct ptp_clock_info *ptp, struct ptp_clock_request *request, int on)
+{
+	return -EOPNOTSUPP;
+}
+
 static void ptp_aux_kworker(struct kthread_work *work)
 {
 	struct ptp_clock *ptp = container_of(work, struct ptp_clock,
@@ -294,6 +299,9 @@  struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
 			ptp->info->getcrosscycles = ptp->info->getcrosststamp;
 	}
 
+	if (!ptp->info->enable)
+		ptp->info->enable = ptp_enable;
+
 	if (ptp->info->do_aux_work) {
 		kthread_init_delayed_work(&ptp->aux_work, ptp_aux_kworker);
 		ptp->kworker = kthread_run_worker(0, "ptp%d", ptp->index);