Skip to content

RUSTSEC-2026-0386

`AsyncFd::new` and related constructors violate I/O safety

Not rated yet crates.io
Severity
Not rated yet
No source has published a CVSS score yet
Exploit chance (EPSS)
—
No score published
Known exploited
No
Not in CISA's catalog
Weakness
—
Not classified
Fix
1.53.3
Upgrade tokio to this version or later

Description

tokio::io::unix::AsyncFd provides safe constructors (new, with_interest, try_new, and try_with_interest) that accept any T: AsRawFd rather than requiring proof of ownership or validity of the file descriptor. Because RawFd implements AsRawFd, safe code can construct an AsyncFd from an arbitrary or closed file descriptor, or close/replace the underlying file descriptor while the AsyncFd is still alive.

This violates I/O safety in two ways:

  1. AsyncFd<T> implements AsFd for all T: AsRawFd by calling BorrowedFd::borrow_raw(self.as_raw_fd()), allowing safe code to obtain an arbitrary BorrowedFd<'_> without owning the file descriptor.
  2. Tokio's I/O driver stores a pointer to an internal allocation in the epoll/kqueue user data for registered file descriptors. If the underlying file descriptor is duplicated and then closed while an AsyncFd is alive, and the OS reuses that file descriptor number for a another IO resource on the same runtime, dropping the first AsyncFd deregisters the reused file descriptor number and frees the first while the original file description remains registered in epoll, leading to a use-after-free when a readiness event fires.

Starting in Tokio 1.51.6, 1.53.3, and 1.54.0, AsyncFd::new, AsyncFd::with_interest, AsyncFd::try_new, and AsyncFd::try_with_interest are deprecated in favor of the unsafe constructors AsyncFd::register and AsyncFd::register_with_interest. Callers must ensure that the file descriptor remains valid, open, and unchanged for the lifetime of the AsyncFd.

Affected versions

crates.io

PackageVulnerableFixed in
tokio
>= 0.3.2, < 1.51.6
>= 1.52.0, < 1.53.3
1.51.6
1.53.3

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

tokio crates.io → 1.53.3

cargo
cargo update -p tokio --precise 1.53.3

References

Timeline

  1. Published
  2. Last updated by the source
AdvisorySeverityWhy it's related
GHSA-5wjr-9356-4wc8
Tokio: Race condition in `tokio::time::Interval`
Medium Also affects tokio
GHSA-rr8g-9fpq-6wmg
Tokio broadcast channel calls clone in parallel, but does not require `Sync`
Low Also affects tokio
GHSA-4q83-7cq4-p6wg
`tokio::io::ReadHalf<T>::unsplit` is Unsound
Low Also affects tokio
GHSA-7rrj-xr53-82p7
Tokio reject_remote_clients configuration may get dropped when creating a Windows named pipe
Medium Also affects tokio
RUSTSEC-2021-0124
Race Condition in tokio
High Also affects tokio
RUSTSEC-2021-0072
Race condition in tokio
Medium Also affects tokio
Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor