`AsyncFd::new` and related constructors violate I/O safety
`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` 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
- Products
- tokio
- Affected versions
- Not specified
- Fixed versions
- 1.51.6, 1.53.3
- CVEs
- Not specified
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 31 Oct 2026, 21:35 UTC · Revision 1
Source evidence
`AsyncFd::new` and related constructors violate I/O safety
core-osv · Original sourcePublished 13 Oct 2026, 12:00 UTC
`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` 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
osv:RUSTSEC-2026-0386
tokio
Fixed versions: 1.51.6, 1.53.3
Complete source record
{
"id": "6aa202b95f86b1ac7ad346d75f1ab8231ad5e2c6ef7e88f1db59bb197dfe9ef2",
"url": "https://osv.dev/vulnerability/RUSTSEC-2026-0386",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "`AsyncFd::new` and related constructors violate I/O safety",
"summary": "`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` 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",
"evidence": "osv:RUSTSEC-2026-0386",
"products": [
{
"name": {
"value": "tokio",
"evidence": "/affected/0/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "1.51.6",
"evidence": "/affected/0/ranges"
},
{
"value": "1.53.3",
"evidence": "/affected/0/ranges"
}
],
"affected_versions": []
}
],
"severity": "unknown",
"structured": {
"id": "RUSTSEC-2026-0386",
"aliases": [
"RUSTSEC-2026-0386"
],
"affected": [
{
"ranges": [
{
"type": "SEMVER",
"events": [
{
"introduced": "0.3.2"
},
{
"fixed": "1.51.6"
},
{
"introduced": "1.52.0"
},
{
"fixed": "1.53.3"
}
]
}
],
"package": {
"name": "tokio",
"purl": "pkg:cargo/tokio",
"ecosystem": "crates.io"
},
"database_specific": {
"cvss": null,
"source": "https://github.com/rustsec/advisory-db/blob/osv/crates/RUSTSEC-2026-0386.json",
"categories": [
"memory-corruption"
],
"informational": "unsound"
},
"ecosystem_specific": {
"affects": {
"os": [],
"arch": [],
"functions": [
"tokio::io::unix::AsyncFd::new",
"tokio::io::unix::AsyncFd::try_new",
"tokio::io::unix::AsyncFd::try_with_interest",
"tokio::io::unix::AsyncFd::with_interest"
]
},
"affected_functions": null
}
}
],
"modified": "2026-10-23T14:45:03.847864944Z",
"provider": "osv",
"references": [
"https://crates.io/crates/tokio",
"https://rustsec.org/advisories/RUSTSEC-2026-0386.html",
"https://github.com/tokio-rs/tokio/pull/8587",
"https://github.com/tokio-rs/tokio/issues/8538",
"https://github.com/tokio-rs/tokio/issues/8539"
],
"provider_metadata": {
"license": "CC0-1.0"
}
},
"related_cves": [],
"security_relevant": true,
"severity_evidence": null
},
"source_id": "core-osv",
"document_id": 413703,
"published_at": "2026-10-13T12:00:00+00:00"
}