Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions crates/axi-uart16550/RUSTSEC-0000-0000.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
```toml
[advisory]
id = "RUSTSEC-0000-0000"
package = "axi-uart16550"
date = "2026-06-13"
informational = "unsound"
references = [
"https://egit.irs.uni-stuttgart.de/rust/axi-uart16550",
"https://crates.io/crates/axi-uart16550",
]
keywords = ["async", "use-after-free", "soundness", "embedded", "uart"]

[versions]
patched = [">=0.2.0"]
```

# axi-uart16550: information disclosure via leaking an in-flight async UART TX future

`axi-uart16550` before 0.2.0 exposes a **safe** asynchronous UART transmit API
(`impl embedded_io_async::Write for TxAsync`, `src/tx_async.rs`) that accepts a **non-`'static`
borrowed buffer** and erases its lifetime (via `raw-slice`/`raw-buffer`) to hand a bare pointer to
the TX interrupt. Cancellation safety relies **entirely** on the returned future's `Drop` to disable
the interrupt, laundered through the safe `Write` trait impl.

Because `core::mem::forget` is **safe** and skips `Drop` — as are other leaks (`Rc`/arena reference
cycles, a leaked/aborted task, `Box::leak`) — safe code can leak an **in-flight** transmit future
(polled at least once, so the TX interrupt is armed) while the borrow of the user buffer ends and
its storage is freed or reused. The TX interrupt then keeps **reading the freed buffer and
transmitting its bytes on the wire** — an **information disclosure** of adjacent freed memory,
reachable with no `unsafe` in the caller.

Neither the borrow checker nor Miri flags it (the interrupt access is outside the abstract machine
and the lifetime is erased). Normal cancellation (dropping the future) runs `Drop` and is handled;
only *leaking* an in-flight future triggers it. Severity is application-dependent, but the API is
**unsound** (safe code can cause UB).

## Remediation

Version 0.2.0 marks the `TxFuture` constructor `unsafe` and requires the future to borrow the
buffer for its lifetime, addressing the inherent API path. The `embedded_io_async::Write` trait
implementation retains a theoretical gap (the trait mandates borrowed buffers that cannot be
lifetime-constrained in the return type), which is documented in the crate. The underlying
`raw-buffer` crate's safety notes were also updated to document this obligation for HAL authors.

Upgrade to `axi-uart16550 >= 0.2.0`.

---
Reported by Kyounghwan Kim (Pusan National University, kbhetrr@gmail.com); coordinated with the
maintainer prior to publication.
49 changes: 49 additions & 0 deletions crates/axi-uartlite/RUSTSEC-0000-0000.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
```toml
[advisory]
id = "RUSTSEC-0000-0000"
package = "axi-uartlite"
date = "2026-06-13"
informational = "unsound"
references = [
"https://egit.irs.uni-stuttgart.de/rust/axi-uartlite",
"https://crates.io/crates/axi-uartlite",
]
keywords = ["async", "use-after-free", "soundness", "embedded", "uart"]

[versions]
patched = [">=0.2.0"]
```

# axi-uartlite: information disclosure via leaking an in-flight async UART TX future

`axi-uartlite` before 0.2.0 exposes a **safe** asynchronous UART transmit API
(`impl embedded_io_async::Write for TxAsync`, `src/tx_async.rs`) that accepts a **non-`'static`
borrowed buffer** and erases its lifetime (via `raw-slice`/`raw-buffer`) to hand a bare pointer to
the TX interrupt. Cancellation safety relies on the returned future's `Drop`, laundered through the
safe `Write` trait impl. In this crate `TxFuture::drop` additionally **cannot disable the
interrupt** (commented "We can not disable interrupts, might be active for RX as well"), so even
ordinary cancellation is weaker here.

Because `core::mem::forget` is **safe** and skips `Drop` — as are other leaks (`Rc`/arena reference
cycles, a leaked/aborted task, `Box::leak`) — safe code can leak an **in-flight** transmit future
while the borrow of the user buffer ends and its storage is freed or reused. The TX interrupt then
keeps **reading the freed buffer and transmitting its bytes on the wire** — an **information
disclosure** of adjacent freed memory, reachable with no `unsafe` in the caller.

Neither the borrow checker nor Miri flags it (the interrupt access is outside the abstract machine
and the lifetime is erased). Severity is application-dependent, but the API is **unsound** (safe
code can cause UB).

## Remediation

Version 0.2.0 marks the `TxFuture` constructor `unsafe` and requires the future to borrow the
buffer for its lifetime, addressing the inherent API path. The `embedded_io_async::Write` trait
implementation retains a theoretical gap (the trait mandates borrowed buffers that cannot be
lifetime-constrained in the return type), which is documented in the crate. The underlying
`raw-buffer` crate's safety notes were also updated to document this obligation for HAL authors.

Upgrade to `axi-uartlite >= 0.2.0`.

---
Reported by Kyounghwan Kim (Pusan National University, kbhetrr@gmail.com); coordinated with the
maintainer prior to publication.