In early 2024, a vulnerability was identified and patched in the Linux kernel affecting the ts480_wdt driver, which is a watchdog timer driver. The issue, registered as CVE-2022-49373, concerns a *reference count leak* that occurs in certain error handling paths. If you're a kernel hobbyist or a security enthusiast, this post will walk you through what happened, why it matters, and how it could be exploited. We'll include snippets and original references to keep things practical.
What is the ts480_wdt?
The ts480_wdt driver is used for interacting with the watchdog timer on the Technologic Systems TS-480 hardware. Watchdog timers are often used in embedded devices to reset the system if software gets stuck. Proper driver handling is crucial for device stability.
What was wrong?
Inside the kernel module, the ts480_wdt_probe function uses a helper called of_parse_phandle() to get device tree node information. This helper increases the reference count of device tree nodes, which means you must actively decrement that count with of_node_put() once you’re finished.
In this driver, error handling paths were missing the of_node_put(), causing refcounts to leak. Over time, this prevents memory from being reclaimed. It mostly triggers during driver load errors — something attackers might force repeatedly.
Here’s the core fix
@@ static int ts480_wdt_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
- struct device_node *gpio_np = of_parse_phandle(np, "gpio-controller", );
+ struct device_node *gpio_np = of_parse_phandle(np, "gpio-controller", );
...
- if (!gpio_np)
- return -ENODEV;
+ if (!gpio_np)
+ return -ENODEV;
if (some_error) {
- return -EIO;
+ of_node_put(gpio_np);
+ return -EIO;
}
+
+ of_node_put(gpio_np);
return ;
For every path exiting early, of_node_put(gpio_np); is now correctly called.
Why Does this Matter?
Reference leaks are often overlooked but can pile up, especially in error-heavy or attacker-controlled situations. In embedded and server systems, memory leakage can cause instability or even soft Denial-of-Service conditions if exploited repeatedly.
Potential Exploitation Scenario
A local unprivileged user (with access to hotplug or device tree manipulation, which is rare but possible in some embedded scenarios) could try to forcibly load and unload the driver repeatedly with crafted device trees, artificially increasing the reference count and consuming memory over time.
Here's a pseudo-exploit
for i in {1..100}; do
# This assumes you have a way to reload the driver and supply a failing DT
insmod ts480_wdt.ko
# trigger probe error path
rmmod ts480_wdt
done
Without the patch, each iteration leaves a little memory locked up — eventually causing system issues.
Mainline Linux commit:
Fix refcount leak in ts480_wdt_probe (git.kernel.org)
And the problematic code before the patch looked like this
struct device_node *gpio_np;
gpio_np = of_parse_phandle(np, "gpio-controller", );
if (!gpio_np)
return -ENODEV;
if (some_error)
return -EIO; // PROBLEM: missing of_node_put(gpio_np) here!
of_node_put(gpio_np);
return ;
References
- Linux kernel changelog for CVE-2022-49373
- Patch commit de65511946e1 (git.kernel.org)
- Watchdog timers documentation (kernel.org)
Conclusion
CVE-2022-49373 may sound "minor," but it demonstrates the importance of proper resource management in kernel code. A missing of_node_put() can become a vector for denial of service, especially in systems where devices are probed frequently. If you're maintaining a Linux kernel, make sure you backport this fix; and as a developer, always double-check your reference counts!
If you want to dig into more kernel bugs, follow the Linux Kernel Mailing List and keep an eye on LWN's security page.
Timeline
Published on: 02/26/2025 07:01:13 UTC
Last modified on: 04/14/2025 20:37:24 UTC