diff mbox series

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

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

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag present in non-next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 8 of 8 maintainers
netdev/build_clang success Errors and warnings before: 2 this patch: 2
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch warning WARNING: line length of 92 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2025-01-23--12-00 (tests: 878)

Commit Message

Thomas Weißschuh Jan. 23, 2025, 7:22 a.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

Michal Swiatkowski Jan. 23, 2025, 9:38 a.m. UTC | #1
On Thu, Jan 23, 2025 at 08:22:40AM +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>
> ---
>  drivers/ptp/ptp_clock.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> 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);
> 
> ---
> base-commit: c4b9570cfb63501638db720f3bee9f6dfd044b82
> change-id: 20250122-ptp-enable-831339c62428
> 
> Best regards,
> -- 
> Thomas Weißschuh <linux@weissschuh.net>

Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>

What about other ops, did you check it too? Looks like it isn't needed,
but it sometimes hard to follow.

Thanks
Thomas Weißschuh Jan. 23, 2025, 1:19 p.m. UTC | #2
On 2025-01-23 10:38:37+0100, Michal Swiatkowski wrote:
> On Thu, Jan 23, 2025 at 08:22:40AM +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>
> > ---
> >  drivers/ptp/ptp_clock.c | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> > 
> > 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);
> > 
> > ---
> > base-commit: c4b9570cfb63501638db720f3bee9f6dfd044b82
> > change-id: 20250122-ptp-enable-831339c62428
> > 
> > Best regards,
> > -- 
> > Thomas Weißschuh <linux@weissschuh.net>
> 
> Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
> 
> What about other ops, did you check it too? Looks like it isn't needed,
> but it sometimes hard to follow.

I couldn't find any missing, but I'm not familiar with the subsystem and
didn't check too hard.

Note:

A follow-up fix would be to actually guard the users of ->enable and
error out. For sysfs the attributes could be hidden completely.
That would be a nicer user interface but more code change which are not
so easily backportable.


Thomas
Richard Cochran Jan. 23, 2025, 3:11 p.m. UTC | #3
On Thu, Jan 23, 2025 at 02:19:46PM +0100, Thomas Weißschuh wrote:
> On 2025-01-23 10:38:37+0100, Michal Swiatkowski wrote:
> > What about other ops, did you check it too? Looks like it isn't needed,
> > but it sometimes hard to follow.
> 
> I couldn't find any missing, but I'm not familiar with the subsystem and
> didn't check too hard.

Initially all of the callbacks were required, but that requirement
became relaxed over time with getcycles64().

Now that we have more and more drivers, it wouldn't hurt to let
ptp_clock_register() check that the needed callbacks are valid.

> Note:
> 
> A follow-up fix would be to actually guard the users of ->enable and
> error out.

Yes, I would place checks at the call sites, within ptp_ioctl().

Thanks,
Richard
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);