A critical bug, tracked as CVE-2023-52456, was found and fixed in the Linux kernel's implementation of the i.MX UART RS485 driver. This issue can cause the serial port to deadlock under certain error scenarios, specifically when the TTY port is abruptly closed during data transmission (like when an application crashes). In this post, we'll break down what this means, how it can be exploited, walk through the technical details, and offer advice on mitigating the problem.
Context
Many Linux-based embedded systems, especially industrial ones, use RS485 serial ports for robust communication. i.MX UART is a common controller on NXP's i.MX CPUs, supporting these ports.
When the serial driver uses RS485 mode, it controls an output pin (TX_EN/RTS) via an internal "state machine," so the hardware knows when to drive the bus.
The Problem
- When the serial port is closed while data is being transmitted (e.g. from a user-space crash), the kernel function imx_uart_shutdown disables the interface and Transmission Complete (TC) interrupt.
- Later, when imx_uart_stop_tx is called, it detects that transmission is incomplete and should let the process finish when the TC interrupt fires.
The transmit state machine is stuck in its "SEND" state, and the line stays busy (TX_EN stuck low).
- After this, you can't use the serial port until a system/device reset.
In summary: It deadlocks the RS485 state machine, rendering the port useless.
Proof of Concept
The vulnerability can be triggered simply by killing a user-space application that's in the middle of sending data over RS485.
Step-by-Step Demo
# 1. Open the RS485 port in one terminal
$ cat > /dev/ttyIMX
# 2. In another terminal, while the first is running, kill the process abruptly
$ pkill -9 cat
# 3. Try sending data again on the same port - it doesn't work!
echo "test" > /dev/ttyIMX # Port is deadlocked!
On affected devices, you won't see data go out. TX_EN (RTS) remains asserted. Only a hard reset brings it back.
Problematic Code (before patch)
// imx_uart_stop_tx()
if (tx_state != RS485_STATE_SEND)
return; // Exits too early if TX incomplete, waiting for TC interrupt
// But TC interrupt is disabled in imx_uart_shutdown()
imx_uart_shutdown() {
...
imx_uart_disabler();
...
}
The Fix
The patch changes imx_uart_stop_tx() to check *both* if transmission is incomplete and if the TC interrupt is enabled before deciding to bail out:
// After the fix:
if (tx_state == RS485_STATE_SEND && tc_interrupt_is_disabled)
goto handle_state_machine; // Ensure state transitions even if TC is off
This ensures the state machine always reaches a safe state, avoiding deadlock.
Reference:
- Original Patch Commit (kernel.org)
- NXP i.MX UART Linux Driver Source
Exploit & Impact
Exploitability:
This issue is *not a typical "remote" exploit*, but in multi-user, multi-process or industrial systems, it can be triggered by a local (possibly unprivileged) user killing or crashing a process using the RS485 port. Automated recovery scripts and watchdogs may also trip over this bug – resulting in serial comms failure, loss of remote control, or even bricking a device until a reboot.
Am I affected?
Affected kernels:
- Linux with i.MX UART RS485 support, prior to the inclusion of this fix.
To check
- Do you use /dev/ttyIMX* or NXP i.MX boards?
Solution
Patch your kernel:
- Upgrade your kernel to v6.8 or later, or apply the fix from the patch above and rebuild.
Workaround (if you can't patch):
Conclusion
CVE-2023-52456 is a subtle but serious issue for anyone using Linux’s i.MX UART in RS485 mode. By understanding the state machine and the fix, you can avoid mysterious serial deadlocks that halt your hardware. Apply the patch to keep your embedded Linux systems resilient!
References
- Linux kernel commit 8377e4e5 (kernel.org)
- NXP i.MX UART Driver source (Bootlin)
- CVE-2023-52456 on NVD
*Stay up to date on embedded Linux security bugs by following kernel changelogs and subscribing to CVE feeds. Protect your devices!*
Timeline
Published on: 02/23/2024 15:15:08 UTC
Last modified on: 04/30/2024 19:34:11 UTC