Skip to content
Heist/ feed
Back to feed
UnratedFix available

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

Type: advisorySources: OSV

`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 source

Published 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"
}