Re: [PATCH 2/9] watchdog: w83627hf_wdt: Convert to platform driver model

[email protected] Sat, 25 Jul 2026 10:42:59 +0000
Newsgroups org.kernel.vger.linux-watchdog
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 4 potential issue(=
s) to consider:
- [High] Potential NULL pointer dereference in `wdt_probe()` when matching =
via `driver_override`.
- [High] State contamination across unbind/bind cycles due to the use of sh=
ared global device structures.
- [Medium] The watchdog device's parent is not set, resulting in an incompl=
ete sysfs topology and preventing property parsing.
- [Low] An uninitialized empty structure `struct wdt_pdata` is passed to `p=
latform_device_register_data()`.
--

--- Patch [2]: [PATCH 2/9] watchdog: w83627hf_wdt: Convert to platform driv=
er model ---
commit dfce32dc3eb2e74bc7730f263ff7f45b7b16d876
Author: Paul Louvel <[email protected]>

watchdog: w83627hf_wdt: Convert to platform driver model

This commit converts the w83627hf_wdt driver to use the Linux driver model
by registering it as a platform driver. It replaces direct device=20
initialization and registration with a probe function and standard
platform device structures.

> diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_=
wdt.c
> index 1529a4e168209..993e65ce4447c 100644
> --- a/drivers/watchdog/w83627hf_wdt.c
> +++ b/drivers/watchdog/w83627hf_wdt.c

[ ... ]

> @@ -464,6 +467,37 @@ static int wdt_find(int addr)
>  	return ret;
>  }
> =20
> +static int wdt_probe(struct platform_device *pdev)
> +{
> +	const struct platform_device_id *id =3D platform_get_device_id(pdev);
> +	enum chips chip =3D id->driver_data;

[Severity: High]
Could platform_get_device_id() return a NULL pointer here if a privileged
user manually forces the device to bind to this driver using the
driver_override sysfs interface?

If so, does id->driver_data trigger a NULL pointer dereference since the
platform bus matching logic bypasses the id_table?

> +	int ret;
> +
> +	pr_info("WDT driver for %s Super I/O chip initialising\n", id->name);
> +
> +	snprintf(wdt_info.identity, sizeof(wdt_info.identity), "%s Watchdog",
> +		 id->name);
> +
> +	watchdog_init_timeout(&wdt_dev, timeout, NULL);

[Severity: High]
Does modifying statically allocated global structures like wdt_info and
wdt_dev instead of using dynamically allocated per-device state cause state
contamination across unbind/bind cycles?

If the driver is unbound and rebound via sysfs, the wdt_dev.status bitmask
retains accumulated state flags like WDOG_HW_RUNNING. If this flag is false=
ly
retained, wouldn't the watchdog core spawn a worker thread to automatically
ping the watchdog on behalf of the kernel, defeating the watchdog's purpose
if userspace hangs?

> +	watchdog_set_nowayout(&wdt_dev, nowayout);
> +	watchdog_stop_on_reboot(&wdt_dev);
> +
> +	ret =3D w83627hf_init(&wdt_dev, chip);
> +	if (ret) {
> +		pr_err("failed to initialize watchdog (err=3D%d)\n", ret);
> +		return ret;
> +	}
> +
> +	ret =3D devm_watchdog_register_device(&pdev->dev, &wdt_dev);

[Severity: Medium]
Is the sysfs topology broken here because the global wdt_dev struct lacks
a .parent =3D &pdev->dev assignment before registration?

Since the parent is not set and watchdog_init_timeout() earlier is passed a
NULL device pointer, won't the watchdog character device be created at the
root of the sysfs hierarchy instead of as a child of the platform device,
preventing standard properties like timeout-sec from being parsed?

> +	if (ret)
> +		return ret;
> +
> +	pr_info("initialized. timeout=3D%d sec (nowayout=3D%d)\n", wdt_dev.time=
out,
> +		nowayout);
> +
> +	return ret;
> +}

[ ... ]

> @@ -533,35 +580,25 @@ static int __init wdt_init(void)
>  			return chip;
>  	}
> =20
> -	pr_info("WDT driver for %s Super I/O chip initialising\n",
> -		chip_name[chip]);
> -
> -	snprintf(wdt_info.identity, sizeof(wdt_info.identity), "%s Watchdog",
> -		 chip_name[chip]);
> -
> -	watchdog_init_timeout(&wdt_dev, timeout, NULL);
> -	watchdog_set_nowayout(&wdt_dev, nowayout);
> -	watchdog_stop_on_reboot(&wdt_dev);
> -
> -	ret =3D w83627hf_init(&wdt_dev, chip);
> -	if (ret) {
> -		pr_err("failed to initialize watchdog (err=3D%d)\n", ret);
> -		return ret;
> -	}
> -
> -	ret =3D watchdog_register_device(&wdt_dev);
> +	ret =3D platform_driver_register(&wdt_driver);
>  	if (ret)
>  		return ret;
> =20
> -	pr_info("initialized. timeout=3D%d sec (nowayout=3D%d)\n",
> -		wdt_dev.timeout, nowayout);
> +	wdt_pdev =3D platform_device_register_data(NULL, wdt_ids[chip].name,
> +						 PLATFORM_DEVID_NONE, &pdata,
> +						 sizeof(pdata));

[Severity: Low]
Does passing the uninitialized stack variable pdata serve a purpose here?
Although sizeof(pdata) evaluating to 0 makes it currently safe, would it
be clearer to pass NULL and 0 for the size instead?

> +	if (IS_ERR(wdt_pdev)) {
> +		platform_driver_unregister(&wdt_driver);
> +		return PTR_ERR(wdt_pdev);
> +	}
> =20
> -	return ret;
> +	return 0;
>  }

--=20
Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/20260725-w83627hf_w=
[email protected]?part=3D2