Published: June 2024
Affected Component: Linux Kernel drivers/usb/serial/quatech2.c
Vulnerability Type: Null Pointer Dereference (null-ptr-deref)
Fixed in: Linux kernel mainline as of commit 2f5149268d4ccf07
Overview
A security flaw known as CVE-2025-21689 was recently found and fixed in the Linux kernel's quatech2 USB serial driver. This post discusses how the bug could be exploited, what caused it, and how the Linux team fixed it—using code snippets and real-world language.
The Vulnerability in Simple Terms
The Linux kernel lets computers talk to lots of external devices—like USB-to-serial converters. The quatech2 driver is used for some serial adapters. Inside this driver, there's a function called qt2_process_read_urb() that handles data coming in from the USB device.
There was a check in this code to make sure the driver didn't try to use a port number that was out-of-range. But the check was not strict enough. This meant that, under the right (wrong!) circumstances, the driver could try to use a port that doesn't exist. When that happens, it would try to access a NULL pointer, causing the kernel to crash—a classic *"null pointer dereference"* bug.
Here's the vulnerable code from before the patch
// Previous bounds check
if (newport > serial->num_ports) {
dev_err(&port->dev,
"%s - port change to invalid port: %i\n",
__func__, newport);
break;
}
The serial->port array is indexed by port numbers starting at and going up to serial->num_ports - 1. If newport is equal to serial->num_ports, the check above lets it pass---that's one too high.
Right after this check, the pointer is used
serial_priv->current_port = newport;
port = serial->port[serial_priv->current_port]; // <-- Oops!
If newport == serial->num_ports, then this line is out-of-bounds and sets port to NULL. Accessing port->dev just after that causes a kernel panic.
Causing the driver to process a fake or corrupted packet with an invalid newport value.
3. Making the kernel pointer dereference NULL, crashing the system or potentially enabling further attacks (in some setups, this could lead to denial-of-service or—rarely—privilege escalation).
This is mainly a denial-of-service (DoS) issue unless other memory corruptions are chained in an attack.
The developers fixed the problem with a stricter check. The corrected code now looks like this
// Patched bounds check: only allow valid port numbers!
if (newport >= serial->num_ports) {
dev_err(&port->dev,
"%s - port change to invalid port: %i\n",
__func__, newport);
break;
}
With this, the function will prevent newport from ever being "too high", so the assignment and lookup are always within the array bounds.
Official Patch:
CVE Entry:
Linux USB Serial driver source:
drivers/usb/serial/quatech2.c mainline
Example: How You Might Hit the Bug
A malicious user with the right hardware or kernel access could exploit the bug like this (pseudo-steps):
Craft a packet that gets newport set to serial->num_ports.
- When the kernel driver runs qt2_process_read_urb(), it tries to access a non-existent port; port becomes NULL.
The next access to port->dev triggers a kernel crash (oops!).
You generally need root or physical access, but USB-based attacks are a known vector for exploiting kernel driver bugs like this.
What Should You Do?
If you're a user:
Apply all available updates, especially if you use USB serial adapters
If you build or patch kernels:
Conclusion
CVE-2025-21689 shows how a minor off-by-one mistake in bounds checking can have big consequences for security and stability—even in drivers that most users never notice. This vulnerability demonstrates why careful attention to USB device driver code is so important, and how quickly the Linux community responds to eliminate these bugs.
Stay updated!
Always run the latest patches to avoid old, known vulnerabilities like this one.
*(Exclusive summary for this blog. Please link back to kernel.org and CVE.org if referencing material.)*
Timeline
Published on: 02/10/2025 16:15:38 UTC
Last modified on: 03/24/2025 15:38:56 UTC