about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/ffi/os_str.rs2
-rw-r--r--library/std/src/fs.rs84
-rw-r--r--library/std/src/io/mod.rs2
-rw-r--r--library/std/src/os/android/net.rs2
-rw-r--r--library/std/src/os/illumos/mod.rs1
-rw-r--r--library/std/src/os/illumos/net.rs50
-rw-r--r--library/std/src/os/linux/net.rs2
-rw-r--r--library/std/src/os/net/linux_ext/mod.rs2
-rw-r--r--library/std/src/os/net/linux_ext/tcp.rs10
-rw-r--r--library/std/src/os/solaris/mod.rs1
-rw-r--r--library/std/src/os/solaris/net.rs50
-rw-r--r--library/std/src/os/unix/fs.rs12
-rw-r--r--library/std/src/os/unix/process.rs2
-rw-r--r--library/std/src/path.rs8
-rw-r--r--library/std/src/sync/lazy_lock.rs2
-rw-r--r--library/std/src/sys/fs/windows/remove_dir_all.rs19
-rw-r--r--library/std/src/sys/net/connection/socket/unix.rs15
-rw-r--r--library/std/src/sys/net/connection/socket/wasip2.rs2
-rw-r--r--library/std/src/sys/pal/uefi/helpers.rs6
-rw-r--r--library/std/src/sys/pal/windows/api.rs73
-rw-r--r--library/std/src/sys/pal/windows/c.rs7
-rw-r--r--library/std/src/sys/pal/windows/pipe.rs13
-rw-r--r--library/std/src/sys/path/cygwin.rs2
-rw-r--r--library/std/src/sys/process/unix/unix.rs4
-rw-r--r--library/std/src/sys/process/unix/vxworks.rs4
-rw-r--r--library/std/src/sys/random/linux.rs4
-rw-r--r--library/std/src/sys/random/unsupported.rs2
-rw-r--r--library/std/src/thread/spawnhook.rs2
-rw-r--r--library/std/src/time.rs6
29 files changed, 300 insertions, 89 deletions
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 3cc225004ea..8d7edc732af 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -568,7 +568,7 @@ impl OsString {
     /// However, keep in mind that trimming the capacity may result in a reallocation and copy.
     ///
     /// [`into_boxed_os_str`]: Self::into_boxed_os_str
-    #[stable(feature = "os_string_pathbuf_leak", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "os_string_pathbuf_leak", since = "1.89.0")]
     #[inline]
     pub fn leak<'a>(self) -> &'a mut OsStr {
         OsStr::from_inner_mut(self.inner.leak())
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 865ea620a28..72ad7c244ee 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -4,6 +4,27 @@
 //! filesystem. All methods in this module represent cross-platform filesystem
 //! operations. Extra platform-specific functionality can be found in the
 //! extension traits of `std::os::$platform`.
+//!
+//! # Time of Check to Time of Use (TOCTOU)
+//!
+//! Many filesystem operations are subject to a race condition known as "Time of Check to Time of Use"
+//! (TOCTOU). This occurs when a program checks a condition (like file existence or permissions)
+//! and then uses the result of that check to make a decision, but the condition may have changed
+//! between the check and the use.
+//!
+//! For example, checking if a file exists and then creating it if it doesn't is vulnerable to
+//! TOCTOU - another process could create the file between your check and creation attempt.
+//!
+//! Another example is with symbolic links: when removing a directory, if another process replaces
+//! the directory with a symbolic link between the check and the removal operation, the removal
+//! might affect the wrong location. This is why operations like [`remove_dir_all`] need to use
+//! atomic operations to prevent such race conditions.
+//!
+//! To avoid TOCTOU issues:
+//! - Be aware that metadata operations (like [`metadata`] or [`symlink_metadata`]) may be affected by
+//! changes made by other processes.
+//! - Use atomic operations when possible (like [`File::create_new`] instead of checking existence then creating).
+//! - Keep file open for the duration of operations.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![deny(unsafe_op_in_unsafe_fn)]
@@ -121,7 +142,7 @@ pub struct File {
 ///
 /// [`try_lock`]: File::try_lock
 /// [`try_lock_shared`]: File::try_lock_shared
-#[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "file_lock", since = "1.89.0")]
 pub enum TryLockError {
     /// The lock could not be acquired due to an I/O error on the file. The standard library will
     /// not return an [`ErrorKind::WouldBlock`] error inside [`TryLockError::Error`]
@@ -366,10 +387,10 @@ pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result
     inner(path.as_ref(), contents.as_ref())
 }
 
-#[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "file_lock", since = "1.89.0")]
 impl error::Error for TryLockError {}
 
-#[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "file_lock", since = "1.89.0")]
 impl fmt::Debug for TryLockError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
@@ -379,7 +400,7 @@ impl fmt::Debug for TryLockError {
     }
 }
 
-#[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "file_lock", since = "1.89.0")]
 impl fmt::Display for TryLockError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
@@ -390,7 +411,7 @@ impl fmt::Display for TryLockError {
     }
 }
 
-#[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "file_lock", since = "1.89.0")]
 impl From<TryLockError> for io::Error {
     fn from(err: TryLockError) -> io::Error {
         match err {
@@ -548,13 +569,14 @@ impl File {
     /// non-exhaustive list of likely errors.
     ///
     /// This option is useful because it is atomic. Otherwise between checking whether a file
-    /// exists and creating a new one, the file may have been created by another process (a TOCTOU
+    /// exists and creating a new one, the file may have been created by another process (a [TOCTOU]
     /// race condition / attack).
     ///
     /// This can also be written using
     /// `File::options().read(true).write(true).create_new(true).open(...)`.
     ///
     /// [`AlreadyExists`]: crate::io::ErrorKind::AlreadyExists
+    /// [TOCTOU]: self#time-of-check-to-time-of-use-toctou
     ///
     /// # Examples
     ///
@@ -682,11 +704,11 @@ impl File {
     /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not
     /// cause non-lockholders to block.
     ///
-    /// If this file handle/descriptor, or a clone of it, already holds an lock the exact behavior
+    /// If this file handle/descriptor, or a clone of it, already holds a lock the exact behavior
     /// is unspecified and platform dependent, including the possibility that it will deadlock.
     /// However, if this method returns, then an exclusive lock is held.
     ///
-    /// If the file not open for writing, it is unspecified whether this function returns an error.
+    /// If the file is not open for writing, it is unspecified whether this function returns an error.
     ///
     /// The lock will be released when this file (along with any other file descriptors/handles
     /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called.
@@ -721,7 +743,7 @@ impl File {
     ///     Ok(())
     /// }
     /// ```
-    #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "file_lock", since = "1.89.0")]
     pub fn lock(&self) -> io::Result<()> {
         self.inner.lock()
     }
@@ -736,7 +758,7 @@ impl File {
     /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not
     /// cause non-lockholders to block.
     ///
-    /// If this file handle/descriptor, or a clone of it, already holds an lock, the exact behavior
+    /// If this file handle/descriptor, or a clone of it, already holds a lock, the exact behavior
     /// is unspecified and platform dependent, including the possibility that it will deadlock.
     /// However, if this method returns, then a shared lock is held.
     ///
@@ -773,7 +795,7 @@ impl File {
     ///     Ok(())
     /// }
     /// ```
-    #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "file_lock", since = "1.89.0")]
     pub fn lock_shared(&self) -> io::Result<()> {
         self.inner.lock_shared()
     }
@@ -790,11 +812,11 @@ impl File {
     /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not
     /// cause non-lockholders to block.
     ///
-    /// If this file handle/descriptor, or a clone of it, already holds an lock, the exact behavior
+    /// If this file handle/descriptor, or a clone of it, already holds a lock, the exact behavior
     /// is unspecified and platform dependent, including the possibility that it will deadlock.
     /// However, if this method returns `Ok(true)`, then it has acquired an exclusive lock.
     ///
-    /// If the file not open for writing, it is unspecified whether this function returns an error.
+    /// If the file is not open for writing, it is unspecified whether this function returns an error.
     ///
     /// The lock will be released when this file (along with any other file descriptors/handles
     /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called.
@@ -837,7 +859,7 @@ impl File {
     ///     Ok(())
     /// }
     /// ```
-    #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "file_lock", since = "1.89.0")]
     pub fn try_lock(&self) -> Result<(), TryLockError> {
         self.inner.try_lock()
     }
@@ -855,7 +877,7 @@ impl File {
     /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not
     /// cause non-lockholders to block.
     ///
-    /// If this file handle, or a clone of it, already holds an lock, the exact behavior is
+    /// If this file handle, or a clone of it, already holds a lock, the exact behavior is
     /// unspecified and platform dependent, including the possibility that it will deadlock.
     /// However, if this method returns `Ok(true)`, then it has acquired a shared lock.
     ///
@@ -901,7 +923,7 @@ impl File {
     ///     Ok(())
     /// }
     /// ```
-    #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "file_lock", since = "1.89.0")]
     pub fn try_lock_shared(&self) -> Result<(), TryLockError> {
         self.inner.try_lock_shared()
     }
@@ -938,7 +960,7 @@ impl File {
     ///     Ok(())
     /// }
     /// ```
-    #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "file_lock", since = "1.89.0")]
     pub fn unlock(&self) -> io::Result<()> {
         self.inner.unlock()
     }
@@ -1610,7 +1632,7 @@ impl OpenOptions {
     ///
     /// This option is useful because it is atomic. Otherwise between checking
     /// whether a file exists and creating a new one, the file may have been
-    /// created by another process (a TOCTOU race condition / attack).
+    /// created by another process (a [TOCTOU] race condition / attack).
     ///
     /// If `.create_new(true)` is set, [`.create()`] and [`.truncate()`] are
     /// ignored.
@@ -1621,6 +1643,7 @@ impl OpenOptions {
     /// [`.create()`]: OpenOptions::create
     /// [`.truncate()`]: OpenOptions::truncate
     /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists
+    /// [TOCTOU]: self#time-of-check-to-time-of-use-toctou
     ///
     /// # Examples
     ///
@@ -2954,17 +2977,17 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
 /// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtCreateFile`.
 ///
 /// ## Time-of-check to time-of-use (TOCTOU) race conditions
-/// On a few platforms there is no way to remove a directory's contents without following symlinks
-/// unless you perform a check and then operate on paths based on that directory.
-/// This allows concurrently-running code to replace the directory with a symlink after the check,
-/// causing a removal to instead operate on a path based on the symlink. This is a TOCTOU race.
-/// By default, `fs::remove_dir_all` protects against a symlink TOCTOU race on all platforms
-/// except the following. It should not be used in security-sensitive contexts on these platforms:
-/// - Miri: Even when emulating targets where the underlying implementation will protect against
-/// TOCTOU races, Miri will not do so.
-/// - Redox OS: This function does not protect against TOCTOU races, as Redox does not implement
-/// the required platform support to do so.
+/// See the [module-level TOCTOU explanation](self#time-of-check-to-time-of-use-toctou).
+///
+/// On most platforms, `fs::remove_dir_all` protects against symlink TOCTOU races by default.
+/// However, on the following platforms, this protection is not provided and the function should
+/// not be used in security-sensitive contexts:
+/// - **Miri**: Even when emulating targets where the underlying implementation will protect against
+///   TOCTOU races, Miri will not do so.
+/// - **Redox OS**: This function does not protect against TOCTOU races, as Redox does not implement
+///   the required platform support to do so.
 ///
+/// [TOCTOU]: self#time-of-check-to-time-of-use-toctou
 /// [changes]: io#platform-specific-behavior
 ///
 /// # Errors
@@ -3091,7 +3114,7 @@ pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
 /// On UNIX-like systems, this function will update the permission bits
 /// of the file pointed to by the symlink.
 ///
-/// Note that this behavior can lead to privalage escalation vulnerabilites,
+/// Note that this behavior can lead to privalage escalation vulnerabilities,
 /// where the ability to create a symlink in one directory allows you to
 /// cause the permissions of another file or directory to be modified.
 ///
@@ -3238,7 +3261,7 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
 /// permission is denied on one of the parent directories.
 ///
 /// Note that while this avoids some pitfalls of the `exists()` method, it still can not
-/// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios
+/// prevent time-of-check to time-of-use ([TOCTOU]) bugs. You should only use it in scenarios
 /// where those bugs are not an issue.
 ///
 /// # Examples
@@ -3251,6 +3274,7 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
 /// ```
 ///
 /// [`Path::exists`]: crate::path::Path::exists
+/// [TOCTOU]: self#time-of-check-to-time-of-use-toctou
 #[stable(feature = "fs_try_exists", since = "1.81.0")]
 #[inline]
 pub fn exists<P: AsRef<Path>>(path: P) -> io::Result<bool> {
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index a9a24681e7c..17c32d7a571 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -3128,7 +3128,7 @@ impl<T> SizeHint for Take<T> {
     }
 }
 
-#[stable(feature = "seek_io_take", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "seek_io_take", since = "1.89.0")]
 impl<T: Seek> Seek for Take<T> {
     fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
         let new_position = match pos {
diff --git a/library/std/src/os/android/net.rs b/library/std/src/os/android/net.rs
index 3a459ed8aee..95c3a74c489 100644
--- a/library/std/src/os/android/net.rs
+++ b/library/std/src/os/android/net.rs
@@ -6,5 +6,5 @@
 pub use crate::os::net::linux_ext::addr::SocketAddrExt;
 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
 pub use crate::os::net::linux_ext::socket::UnixSocketExt;
-#[stable(feature = "tcp_quickack", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "tcp_quickack", since = "1.89.0")]
 pub use crate::os::net::linux_ext::tcp::TcpStreamExt;
diff --git a/library/std/src/os/illumos/mod.rs b/library/std/src/os/illumos/mod.rs
index e61926f8935..5fbe352e7cf 100644
--- a/library/std/src/os/illumos/mod.rs
+++ b/library/std/src/os/illumos/mod.rs
@@ -3,4 +3,5 @@
 #![stable(feature = "raw_ext", since = "1.1.0")]
 
 pub mod fs;
+pub mod net;
 pub mod raw;
diff --git a/library/std/src/os/illumos/net.rs b/library/std/src/os/illumos/net.rs
new file mode 100644
index 00000000000..5ef4e1ec89e
--- /dev/null
+++ b/library/std/src/os/illumos/net.rs
@@ -0,0 +1,50 @@
+//! illumos-specific networking functionality.
+
+#![unstable(feature = "unix_socket_exclbind", issue = "123481")]
+
+use crate::io;
+use crate::os::unix::net;
+use crate::sealed::Sealed;
+use crate::sys_common::AsInner;
+
+/// illumos-specific functionality for `AF_UNIX` sockets [`UnixDatagram`]
+/// and [`UnixStream`].
+///
+/// [`UnixDatagram`]: net::UnixDatagram
+/// [`UnixStream`]: net::UnixStream
+#[unstable(feature = "unix_socket_exclbind", issue = "123481")]
+pub trait UnixSocketExt: Sealed {
+    /// Enables exclusive binding on the socket.
+    ///
+    /// If true and if the socket had been set with `SO_REUSEADDR`,
+    /// it neutralises its effect.
+    /// See [`man 3 tcp`](https://docs.oracle.com/cd/E88353_01/html/E37843/setsockopt-3c.html)
+    #[unstable(feature = "unix_socket_exclbind", issue = "123481")]
+    fn so_exclbind(&self, excl: bool) -> io::Result<()>;
+
+    /// Get the bind exclusivity bind state of the socket.
+    #[unstable(feature = "unix_socket_exclbind", issue = "123481")]
+    fn exclbind(&self) -> io::Result<bool>;
+}
+
+#[unstable(feature = "unix_socket_exclbind", issue = "123481")]
+impl UnixSocketExt for net::UnixDatagram {
+    fn exclbind(&self) -> io::Result<bool> {
+        self.as_inner().exclbind()
+    }
+
+    fn so_exclbind(&self, excl: bool) -> io::Result<()> {
+        self.as_inner().set_exclbind(excl)
+    }
+}
+
+#[unstable(feature = "unix_socket_exclbind", issue = "123481")]
+impl UnixSocketExt for net::UnixStream {
+    fn exclbind(&self) -> io::Result<bool> {
+        self.as_inner().exclbind()
+    }
+
+    fn so_exclbind(&self, excl: bool) -> io::Result<()> {
+        self.as_inner().set_exclbind(excl)
+    }
+}
diff --git a/library/std/src/os/linux/net.rs b/library/std/src/os/linux/net.rs
index c14aba13bd1..ee56dafdbfd 100644
--- a/library/std/src/os/linux/net.rs
+++ b/library/std/src/os/linux/net.rs
@@ -6,5 +6,5 @@
 pub use crate::os::net::linux_ext::addr::SocketAddrExt;
 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
 pub use crate::os::net::linux_ext::socket::UnixSocketExt;
-#[stable(feature = "tcp_quickack", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "tcp_quickack", since = "1.89.0")]
 pub use crate::os::net::linux_ext::tcp::TcpStreamExt;
diff --git a/library/std/src/os/net/linux_ext/mod.rs b/library/std/src/os/net/linux_ext/mod.rs
index bb9dfae2623..3c9afe35479 100644
--- a/library/std/src/os/net/linux_ext/mod.rs
+++ b/library/std/src/os/net/linux_ext/mod.rs
@@ -8,7 +8,7 @@ pub(crate) mod addr;
 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
 pub(crate) mod socket;
 
-#[stable(feature = "tcp_quickack", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "tcp_quickack", since = "1.89.0")]
 pub(crate) mod tcp;
 
 #[cfg(test)]
diff --git a/library/std/src/os/net/linux_ext/tcp.rs b/library/std/src/os/net/linux_ext/tcp.rs
index 167cfa62531..fde53ec4257 100644
--- a/library/std/src/os/net/linux_ext/tcp.rs
+++ b/library/std/src/os/net/linux_ext/tcp.rs
@@ -9,7 +9,7 @@ use crate::{io, net};
 /// Os-specific extensions for [`TcpStream`]
 ///
 /// [`TcpStream`]: net::TcpStream
-#[stable(feature = "tcp_quickack", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "tcp_quickack", since = "1.89.0")]
 pub trait TcpStreamExt: Sealed {
     /// Enable or disable `TCP_QUICKACK`.
     ///
@@ -33,7 +33,7 @@ pub trait TcpStreamExt: Sealed {
     ///         .expect("Couldn't connect to the server...");
     /// stream.set_quickack(true).expect("set_quickack call failed");
     /// ```
-    #[stable(feature = "tcp_quickack", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "tcp_quickack", since = "1.89.0")]
     fn set_quickack(&self, quickack: bool) -> io::Result<()>;
 
     /// Gets the value of the `TCP_QUICKACK` option on this socket.
@@ -54,7 +54,7 @@ pub trait TcpStreamExt: Sealed {
     /// stream.set_quickack(true).expect("set_quickack call failed");
     /// assert_eq!(stream.quickack().unwrap_or(false), true);
     /// ```
-    #[stable(feature = "tcp_quickack", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "tcp_quickack", since = "1.89.0")]
     fn quickack(&self) -> io::Result<bool>;
 
     /// A socket listener will be awakened solely when data arrives.
@@ -103,10 +103,10 @@ pub trait TcpStreamExt: Sealed {
     fn deferaccept(&self) -> io::Result<u32>;
 }
 
-#[stable(feature = "tcp_quickack", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "tcp_quickack", since = "1.89.0")]
 impl Sealed for net::TcpStream {}
 
-#[stable(feature = "tcp_quickack", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "tcp_quickack", since = "1.89.0")]
 impl TcpStreamExt for net::TcpStream {
     fn set_quickack(&self, quickack: bool) -> io::Result<()> {
         self.as_inner().as_inner().set_quickack(quickack)
diff --git a/library/std/src/os/solaris/mod.rs b/library/std/src/os/solaris/mod.rs
index e4cfd53291a..b4e83620849 100644
--- a/library/std/src/os/solaris/mod.rs
+++ b/library/std/src/os/solaris/mod.rs
@@ -3,4 +3,5 @@
 #![stable(feature = "raw_ext", since = "1.1.0")]
 
 pub mod fs;
+pub mod net;
 pub mod raw;
diff --git a/library/std/src/os/solaris/net.rs b/library/std/src/os/solaris/net.rs
new file mode 100644
index 00000000000..ca841f15b0e
--- /dev/null
+++ b/library/std/src/os/solaris/net.rs
@@ -0,0 +1,50 @@
+//! solaris-specific networking functionality.
+
+#![unstable(feature = "unix_socket_exclbind", issue = "123481")]
+
+use crate::io;
+use crate::os::unix::net;
+use crate::sealed::Sealed;
+use crate::sys_common::AsInner;
+
+/// solaris-specific functionality for `AF_UNIX` sockets [`UnixDatagram`]
+/// and [`UnixStream`].
+///
+/// [`UnixDatagram`]: net::UnixDatagram
+/// [`UnixStream`]: net::UnixStream
+#[unstable(feature = "unix_socket_exclbind", issue = "123481")]
+pub trait UnixSocketExt: Sealed {
+    /// Enables exclusive binding on the socket.
+    ///
+    /// If true and if the socket had been set with `SO_REUSEADDR`,
+    /// it neutralises its effect.
+    /// See [`man 3 tcp`](https://docs.oracle.com/cd/E88353_01/html/E37843/setsockopt-3c.html)
+    #[unstable(feature = "unix_socket_exclbind", issue = "123481")]
+    fn so_exclbind(&self, excl: bool) -> io::Result<()>;
+
+    /// Get the bind exclusivity bind state of the socket.
+    #[unstable(feature = "unix_socket_exclbind", issue = "123481")]
+    fn exclbind(&self) -> io::Result<bool>;
+}
+
+#[unstable(feature = "unix_socket_exclbind", issue = "123481")]
+impl UnixSocketExt for net::UnixDatagram {
+    fn exclbind(&self) -> io::Result<bool> {
+        self.as_inner().exclbind()
+    }
+
+    fn so_exclbind(&self, excl: bool) -> io::Result<()> {
+        self.as_inner().set_exclbind(excl)
+    }
+}
+
+#[unstable(feature = "unix_socket_exclbind", issue = "123481")]
+impl UnixSocketExt for net::UnixStream {
+    fn exclbind(&self) -> io::Result<bool> {
+        self.as_inner().exclbind()
+    }
+
+    fn so_exclbind(&self, excl: bool) -> io::Result<()> {
+        self.as_inner().set_exclbind(excl)
+    }
+}
diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs
index 4f9259f39c1..b776df3dde1 100644
--- a/library/std/src/os/unix/fs.rs
+++ b/library/std/src/os/unix/fs.rs
@@ -408,24 +408,22 @@ pub trait OpenOptionsExt {
     /// Pass custom flags to the `flags` argument of `open`.
     ///
     /// The bits that define the access mode are masked out with `O_ACCMODE`, to
-    /// ensure they do not interfere with the access mode set by Rusts options.
+    /// ensure they do not interfere with the access mode set by Rust's options.
     ///
-    /// Custom flags can only set flags, not remove flags set by Rusts options.
-    /// This options overwrites any previously set custom flags.
+    /// Custom flags can only set flags, not remove flags set by Rust's options.
+    /// This function overwrites any previously-set custom flags.
     ///
     /// # Examples
     ///
     /// ```no_run
-    /// # #![feature(rustc_private)]
+    /// # mod libc { pub const O_NOFOLLOW: i32 = 0; }
     /// use std::fs::OpenOptions;
     /// use std::os::unix::fs::OpenOptionsExt;
     ///
     /// # fn main() {
     /// let mut options = OpenOptions::new();
     /// options.write(true);
-    /// if cfg!(unix) {
-    ///     options.custom_flags(libc::O_NOFOLLOW);
-    /// }
+    /// options.custom_flags(libc::O_NOFOLLOW);
     /// let file = options.open("foo.txt");
     /// # }
     /// ```
diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs
index 3f4fe2e56ec..466b134d8fa 100644
--- a/library/std/src/os/unix/process.rs
+++ b/library/std/src/os/unix/process.rs
@@ -385,7 +385,7 @@ pub trait ChildExt: Sealed {
     /// # Errors
     ///
     /// This function will return an error if the signal is invalid. The integer values associated
-    /// with signals are implemenation-specific, so it's encouraged to use a crate that provides
+    /// with signals are implementation-specific, so it's encouraged to use a crate that provides
     /// posix bindings.
     ///
     /// # Examples
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 07f212b1135..0ce20a143df 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1252,7 +1252,7 @@ impl PathBuf {
     /// However, keep in mind that trimming the capacity may result in a reallocation and copy.
     ///
     /// [`into_boxed_path`]: Self::into_boxed_path
-    #[stable(feature = "os_string_pathbuf_leak", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "os_string_pathbuf_leak", since = "1.89.0")]
     #[inline]
     pub fn leak<'a>(self) -> &'a mut Path {
         Path::from_inner_mut(self.inner.leak())
@@ -3127,7 +3127,7 @@ impl Path {
     /// Returns `true` if the path points at an existing entity.
     ///
     /// Warning: this method may be error-prone, consider using [`try_exists()`] instead!
-    /// It also has a risk of introducing time-of-check to time-of-use (TOCTOU) bugs.
+    /// It also has a risk of introducing time-of-check to time-of-use ([TOCTOU]) bugs.
     ///
     /// This function will traverse symbolic links to query information about the
     /// destination file.
@@ -3148,6 +3148,7 @@ impl Path {
     /// check errors, call [`Path::try_exists`].
     ///
     /// [`try_exists()`]: Self::try_exists
+    /// [TOCTOU]: fs#time-of-check-to-time-of-use-toctou
     #[stable(feature = "path_ext", since = "1.5.0")]
     #[must_use]
     #[inline]
@@ -3167,7 +3168,7 @@ impl Path {
     /// permission is denied on one of the parent directories.
     ///
     /// Note that while this avoids some pitfalls of the `exists()` method, it still can not
-    /// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios
+    /// prevent time-of-check to time-of-use ([TOCTOU]) bugs. You should only use it in scenarios
     /// where those bugs are not an issue.
     ///
     /// This is an alias for [`std::fs::exists`](crate::fs::exists).
@@ -3180,6 +3181,7 @@ impl Path {
     /// assert!(Path::new("/root/secret_file.txt").try_exists().is_err());
     /// ```
     ///
+    /// [TOCTOU]: fs#time-of-check-to-time-of-use-toctou
     /// [`exists()`]: Self::exists
     #[stable(feature = "path_try_exists", since = "1.63.0")]
     #[inline]
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index 82e5fe05db5..eba849d16da 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -313,7 +313,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
     }
 }
 
-#[stable(feature = "lazy_deref_mut", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "lazy_deref_mut", since = "1.89.0")]
 impl<T, F: FnOnce() -> T> DerefMut for LazyLock<T, F> {
     #[inline]
     fn deref_mut(&mut self) -> &mut T {
diff --git a/library/std/src/sys/fs/windows/remove_dir_all.rs b/library/std/src/sys/fs/windows/remove_dir_all.rs
index 06734f9e309..c8b1a076768 100644
--- a/library/std/src/sys/fs/windows/remove_dir_all.rs
+++ b/library/std/src/sys/fs/windows/remove_dir_all.rs
@@ -33,7 +33,7 @@ use core::sync::atomic::{Atomic, AtomicU32, Ordering};
 
 use super::{AsRawHandle, DirBuff, File, FromRawHandle};
 use crate::sys::c;
-use crate::sys::pal::api::WinError;
+use crate::sys::pal::api::{UnicodeStrRef, WinError, unicode_str};
 use crate::thread;
 
 // The maximum number of times to spin when waiting for deletes to complete.
@@ -74,7 +74,7 @@ unsafe fn nt_open_file(
 /// `options` will be OR'd with `FILE_OPEN_REPARSE_POINT`.
 fn open_link_no_reparse(
     parent: &File,
-    path: &[u16],
+    path: UnicodeStrRef<'_>,
     access: u32,
     options: u32,
 ) -> Result<Option<File>, WinError> {
@@ -90,9 +90,8 @@ fn open_link_no_reparse(
     static ATTRIBUTES: Atomic<u32> = AtomicU32::new(c::OBJ_DONT_REPARSE);
 
     let result = unsafe {
-        let mut path_str = c::UNICODE_STRING::from_ref(path);
         let mut object = c::OBJECT_ATTRIBUTES {
-            ObjectName: &mut path_str,
+            ObjectName: path.as_ptr(),
             RootDirectory: parent.as_raw_handle(),
             Attributes: ATTRIBUTES.load(Ordering::Relaxed),
             ..c::OBJECT_ATTRIBUTES::with_length()
@@ -129,7 +128,7 @@ fn open_link_no_reparse(
     }
 }
 
-fn open_dir(parent: &File, name: &[u16]) -> Result<Option<File>, WinError> {
+fn open_dir(parent: &File, name: UnicodeStrRef<'_>) -> Result<Option<File>, WinError> {
     // Open the directory for synchronous directory listing.
     open_link_no_reparse(
         parent,
@@ -140,7 +139,7 @@ fn open_dir(parent: &File, name: &[u16]) -> Result<Option<File>, WinError> {
     )
 }
 
-fn delete(parent: &File, name: &[u16]) -> Result<(), WinError> {
+fn delete(parent: &File, name: UnicodeStrRef<'_>) -> Result<(), WinError> {
     // Note that the `delete` function consumes the opened file to ensure it's
     // dropped immediately. See module comments for why this is important.
     match open_link_no_reparse(parent, name, c::DELETE, 0) {
@@ -179,8 +178,9 @@ pub fn remove_dir_all_iterative(dir: File) -> Result<(), WinError> {
     'outer: while let Some(dir) = dirlist.pop() {
         let more_data = dir.fill_dir_buff(&mut buffer, restart)?;
         for (name, is_directory) in buffer.iter() {
+            let name = unicode_str!(&name);
             if is_directory {
-                let Some(subdir) = open_dir(&dir, &name)? else { continue };
+                let Some(subdir) = open_dir(&dir, name)? else { continue };
                 dirlist.push(dir);
                 dirlist.push(subdir);
                 continue 'outer;
@@ -188,7 +188,7 @@ pub fn remove_dir_all_iterative(dir: File) -> Result<(), WinError> {
                 // Attempt to delete, retrying on sharing violation errors as these
                 // can often be very temporary. E.g. if something takes just a
                 // bit longer than expected to release a file handle.
-                retry(|| delete(&dir, &name), WinError::SHARING_VIOLATION)?;
+                retry(|| delete(&dir, name), WinError::SHARING_VIOLATION)?;
             }
         }
         if more_data {
@@ -197,7 +197,8 @@ pub fn remove_dir_all_iterative(dir: File) -> Result<(), WinError> {
         } else {
             // Attempt to delete, retrying on not empty errors because we may
             // need to wait some time for files to be removed from the filesystem.
-            retry(|| delete(&dir, &[]), WinError::DIR_NOT_EMPTY)?;
+            let name = unicode_str!("");
+            retry(|| delete(&dir, name), WinError::DIR_NOT_EMPTY)?;
             restart = true;
         }
     }
diff --git a/library/std/src/sys/net/connection/socket/unix.rs b/library/std/src/sys/net/connection/socket/unix.rs
index b2a4961c3c5..cc111f3521b 100644
--- a/library/std/src/sys/net/connection/socket/unix.rs
+++ b/library/std/src/sys/net/connection/socket/unix.rs
@@ -522,6 +522,21 @@ impl Socket {
         Ok(name)
     }
 
+    #[cfg(any(target_os = "solaris", target_os = "illumos"))]
+    pub fn set_exclbind(&self, excl: bool) -> io::Result<()> {
+        // not yet on libc crate
+        const SO_EXCLBIND: i32 = 0x1015;
+        setsockopt(self, libc::SOL_SOCKET, SO_EXCLBIND, excl)
+    }
+
+    #[cfg(any(target_os = "solaris", target_os = "illumos"))]
+    pub fn exclbind(&self) -> io::Result<bool> {
+        // not yet on libc crate
+        const SO_EXCLBIND: i32 = 0x1015;
+        let raw: c_int = getsockopt(self, libc::SOL_SOCKET, SO_EXCLBIND)?;
+        Ok(raw != 0)
+    }
+
     #[cfg(any(target_os = "android", target_os = "linux",))]
     pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
         setsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED, passcred as libc::c_int)
diff --git a/library/std/src/sys/net/connection/socket/wasip2.rs b/library/std/src/sys/net/connection/socket/wasip2.rs
index 73c25831872..c77c50fece1 100644
--- a/library/std/src/sys/net/connection/socket/wasip2.rs
+++ b/library/std/src/sys/net/connection/socket/wasip2.rs
@@ -140,7 +140,7 @@ impl Socket {
                 0 => {}
                 _ => {
                     // WASI poll does not return  POLLHUP or POLLERR in revents. Check if the
-                    // connnection actually succeeded and return ok only when the socket is
+                    // connection actually succeeded and return ok only when the socket is
                     // ready and no errors were found.
                     if let Some(e) = self.take_error()? {
                         return Err(e);
diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs
index e47263348db..420481648a7 100644
--- a/library/std/src/sys/pal/uefi/helpers.rs
+++ b/library/std/src/sys/pal/uefi/helpers.rs
@@ -487,7 +487,7 @@ impl<T> OwnedProtocol<T> {
         let protocol: *mut T = Box::into_raw(Box::new(protocol));
         let mut handle: r_efi::efi::Handle = crate::ptr::null_mut();
 
-        // FIXME: Move into r-efi once extended_varargs_abi_support is stablized
+        // FIXME: Move into r-efi once extended_varargs_abi_support is stabilized
         let func: BootInstallMultipleProtocolInterfaces =
             unsafe { crate::mem::transmute((*bt.as_ptr()).install_multiple_protocol_interfaces) };
 
@@ -521,7 +521,7 @@ impl<T> Drop for OwnedProtocol<T> {
         // Do not deallocate a runtime protocol
         if let Some(bt) = boot_services() {
             let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
-            // FIXME: Move into r-efi once extended_varargs_abi_support is stablized
+            // FIXME: Move into r-efi once extended_varargs_abi_support is stabilized
             let func: BootUninstallMultipleProtocolInterfaces = unsafe {
                 crate::mem::transmute((*bt.as_ptr()).uninstall_multiple_protocol_interfaces)
             };
@@ -645,7 +645,7 @@ pub(crate) fn get_device_path_from_map(map: &Path) -> io::Result<BorrowedDeviceP
 }
 
 /// Helper for UEFI Protocols which are created and destroyed using
-/// [EFI_SERVICE_BINDING_PROTCOL](https://uefi.org/specs/UEFI/2.11/11_Protocols_UEFI_Driver_Model.html#efi-service-binding-protocol)
+/// [EFI_SERVICE_BINDING_PROTOCOL](https://uefi.org/specs/UEFI/2.11/11_Protocols_UEFI_Driver_Model.html#efi-service-binding-protocol)
 pub(crate) struct ServiceProtocol {
     service_guid: r_efi::efi::Guid,
     handle: NonNull<crate::ffi::c_void>,
diff --git a/library/std/src/sys/pal/windows/api.rs b/library/std/src/sys/pal/windows/api.rs
index 773455c572f..25a6c2d7d8e 100644
--- a/library/std/src/sys/pal/windows/api.rs
+++ b/library/std/src/sys/pal/windows/api.rs
@@ -30,6 +30,7 @@
 //! should go in sys/pal/windows/mod.rs rather than here. See `IoResult` as an example.
 
 use core::ffi::c_void;
+use core::marker::PhantomData;
 
 use super::c;
 
@@ -291,3 +292,75 @@ impl WinError {
     pub const TIMEOUT: Self = Self::new(c::ERROR_TIMEOUT);
     // tidy-alphabetical-end
 }
+
+/// A wrapper around a UNICODE_STRING that is equivalent to `&[u16]`.
+///
+/// It is preferable to use the `unicode_str!` macro as that contains mitigations for  #143078.
+///
+/// If the MaximumLength field of the underlying UNICODE_STRING is greater than
+/// the Length field then you can test if the string is null terminated by inspecting
+/// the u16 directly after the string. You cannot otherwise depend on nul termination.
+#[derive(Copy, Clone)]
+pub struct UnicodeStrRef<'a> {
+    s: c::UNICODE_STRING,
+    lifetime: PhantomData<&'a [u16]>,
+}
+
+static EMPTY_STRING_NULL_TERMINATED: &[u16] = &[0];
+
+impl UnicodeStrRef<'_> {
+    const fn new(slice: &[u16], is_null_terminated: bool) -> Self {
+        let (len, max_len, ptr) = if slice.is_empty() {
+            (0, 2, EMPTY_STRING_NULL_TERMINATED.as_ptr().cast_mut())
+        } else {
+            let len = slice.len() - (is_null_terminated as usize);
+            (len * 2, size_of_val(slice), slice.as_ptr().cast_mut())
+        };
+        Self {
+            s: c::UNICODE_STRING { Length: len as _, MaximumLength: max_len as _, Buffer: ptr },
+            lifetime: PhantomData,
+        }
+    }
+
+    pub const fn from_slice_with_nul(slice: &[u16]) -> Self {
+        if !slice.is_empty() {
+            debug_assert!(slice[slice.len() - 1] == 0);
+        }
+        Self::new(slice, true)
+    }
+
+    pub const fn from_slice(slice: &[u16]) -> Self {
+        Self::new(slice, false)
+    }
+
+    /// Returns a pointer to the underlying UNICODE_STRING
+    pub const fn as_ptr(&self) -> *const c::UNICODE_STRING {
+        &self.s
+    }
+}
+
+/// Create a UnicodeStringRef from a literal str or a u16 array.
+///
+/// To mitigate #143078, when using a literal str the created UNICODE_STRING
+/// will be nul terminated. The MaximumLength field of the UNICODE_STRING will
+/// be set greater than the Length field to indicate that a nul may be present.
+///
+/// If using a u16 array, the array is used exactly as provided and you cannot
+/// count on the string being nul terminated.
+/// This should generally be used for strings that come from the OS.
+///
+/// **NOTE:** we lack a UNICODE_STRING builder type as we don't currently have
+/// a use for it. If needing to dynamically build a UNICODE_STRING, the builder
+/// should try to ensure there's a nul one past the end of the string.
+pub macro unicode_str {
+    ($str:literal) => {const {
+        crate::sys::pal::windows::api::UnicodeStrRef::from_slice_with_nul(
+            crate::sys::pal::windows::api::wide_str!($str),
+        )
+    }},
+    ($array:expr) => {
+        crate::sys::pal::windows::api::UnicodeStrRef::from_slice(
+            $array,
+        )
+    }
+}
diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs
index 53dec105d0c..eee169d410a 100644
--- a/library/std/src/sys/pal/windows/c.rs
+++ b/library/std/src/sys/pal/windows/c.rs
@@ -37,13 +37,6 @@ pub fn nt_success(status: NTSTATUS) -> bool {
     status >= 0
 }
 
-impl UNICODE_STRING {
-    pub fn from_ref(slice: &[u16]) -> Self {
-        let len = size_of_val(slice);
-        Self { Length: len as _, MaximumLength: len as _, Buffer: slice.as_ptr() as _ }
-    }
-}
-
 impl OBJECT_ATTRIBUTES {
     pub fn with_length() -> Self {
         Self {
diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs
index bc5d05c4505..b5ccf037a4f 100644
--- a/library/std/src/sys/pal/windows/pipe.rs
+++ b/library/std/src/sys/pal/windows/pipe.rs
@@ -1,9 +1,8 @@
 use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
 use crate::ops::Neg;
 use crate::os::windows::prelude::*;
-use crate::sys::api::utf16;
-use crate::sys::c;
 use crate::sys::handle::Handle;
+use crate::sys::{api, c};
 use crate::sys_common::{FromInner, IntoInner};
 use crate::{mem, ptr};
 
@@ -73,8 +72,8 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
         // Open a handle to the pipe filesystem (`\??\PIPE\`).
         // This will be used when creating a new annon pipe.
         let pipe_fs = {
-            let path = c::UNICODE_STRING::from_ref(utf16!(r"\??\PIPE\"));
-            object_attributes.ObjectName = &path;
+            let path = api::unicode_str!(r"\??\PIPE\");
+            object_attributes.ObjectName = path.as_ptr();
             let mut pipe_fs = ptr::null_mut();
             let status = c::NtOpenFile(
                 &mut pipe_fs,
@@ -93,8 +92,12 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
 
         // From now on we're using handles instead of paths to create and open pipes.
         // So set the `ObjectName` to a zero length string.
+        // As a (perhaps overzealous) mitigation for #143078, we use the null pointer
+        // for empty.Buffer instead of unicode_str!("").
+        // There's no difference to the OS itself but it's possible that third party
+        // DLLs which hook in to processes could be relying on the exact form of this string.
         let empty = c::UNICODE_STRING::default();
-        object_attributes.ObjectName = &empty;
+        object_attributes.ObjectName = &raw const empty;
 
         // Create our side of the pipe for async access.
         let ours = {
diff --git a/library/std/src/sys/path/cygwin.rs b/library/std/src/sys/path/cygwin.rs
index e90372805bb..da0982384b0 100644
--- a/library/std/src/sys/path/cygwin.rs
+++ b/library/std/src/sys/path/cygwin.rs
@@ -10,7 +10,7 @@ pub fn is_sep_byte(b: u8) -> bool {
     b == b'/' || b == b'\\'
 }
 
-/// Cygwin allways prefers `/` over `\`, and it always converts all `/` to `\`
+/// Cygwin always prefers `/` over `\`, and it always converts all `/` to `\`
 /// internally when calling Win32 APIs. Therefore, the server component of path
 /// `\\?\UNC\localhost/share` is `localhost/share` on Win32, but `localhost`
 /// on Cygwin.
diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs
index 1fe80c13b81..bbd03e2b0c4 100644
--- a/library/std/src/sys/process/unix/unix.rs
+++ b/library/std/src/sys/process/unix/unix.rs
@@ -968,8 +968,8 @@ impl Process {
     }
 
     pub(crate) fn send_signal(&self, signal: i32) -> io::Result<()> {
-        // If we've already waited on this process then the pid can be recycled
-        // and used for another process, and we probably shouldn't be signaling
+        // If we've already waited on this process then the pid can be recycled and
+        // used for another process, and we probably shouldn't be sending signals to
         // random processes, so return Ok because the process has exited already.
         if self.status.is_some() {
             return Ok(());
diff --git a/library/std/src/sys/process/unix/vxworks.rs b/library/std/src/sys/process/unix/vxworks.rs
index 51ae8c56bdb..2275cbb946a 100644
--- a/library/std/src/sys/process/unix/vxworks.rs
+++ b/library/std/src/sys/process/unix/vxworks.rs
@@ -151,8 +151,8 @@ impl Process {
     }
 
     pub fn send_signal(&self, signal: i32) -> io::Result<()> {
-        // If we've already waited on this process then the pid can be recycled
-        // and used for another process, and we probably shouldn't be killing
+        // If we've already waited on this process then the pid can be recycled and
+        // used for another process, and we probably shouldn't be sending signals to
         // random processes, so return Ok because the process has exited already.
         if self.status.is_some() {
             Ok(())
diff --git a/library/std/src/sys/random/linux.rs b/library/std/src/sys/random/linux.rs
index 18196fae28b..53e2f1da675 100644
--- a/library/std/src/sys/random/linux.rs
+++ b/library/std/src/sys/random/linux.rs
@@ -15,7 +15,7 @@
 //! bytes, while the non-blocking pool, once initialized using the blocking
 //! pool, uses a CPRNG to return an unlimited number of random bytes. With a
 //! strong enough CPRNG however, the entropy estimation didn't contribute that
-//! much towards security while being an excellent vector for DoS attacs. Thus,
+//! much towards security while being an excellent vector for DoS attacks. Thus,
 //! the blocking pool was removed in kernel version 5.6.[^2] That patch did not
 //! magically increase the quality of the non-blocking pool, however, so we can
 //! safely consider it strong enough even in older kernel versions and use it
@@ -30,7 +30,7 @@
 //! data the system has available at the time.
 //!
 //! So in conclusion, we always want the output of the non-blocking pool, but
-//! may need to wait until it is initalized. The default behavior of `getrandom`
+//! may need to wait until it is initialized. The default behavior of `getrandom`
 //! is to wait until the non-blocking pool is initialized and then draw from there,
 //! so if `getrandom` is available, we use its default to generate the bytes. For
 //! `HashMap`, however, we need to specify the `GRND_INSECURE` flags, but that
diff --git a/library/std/src/sys/random/unsupported.rs b/library/std/src/sys/random/unsupported.rs
index d68ce4a9e87..894409b395a 100644
--- a/library/std/src/sys/random/unsupported.rs
+++ b/library/std/src/sys/random/unsupported.rs
@@ -6,7 +6,7 @@ pub fn fill_bytes(_: &mut [u8]) {
 
 pub fn hashmap_random_keys() -> (u64, u64) {
     // Use allocation addresses for a bit of randomness. This isn't
-    // particularily secure, but there isn't really an alternative.
+    // particularly secure, but there isn't really an alternative.
     let stack = 0u8;
     let heap = Box::new(0u8);
     let k1 = ptr::from_ref(&stack).addr() as u64;
diff --git a/library/std/src/thread/spawnhook.rs b/library/std/src/thread/spawnhook.rs
index 98f471ad54b..c8a7bcf55c1 100644
--- a/library/std/src/thread/spawnhook.rs
+++ b/library/std/src/thread/spawnhook.rs
@@ -6,7 +6,7 @@ use crate::thread::Thread;
 crate::thread_local! {
     /// A thread local linked list of spawn hooks.
     ///
-    /// It is a linked list of Arcs, such that it can very cheaply be inhereted by spawned threads.
+    /// It is a linked list of Arcs, such that it can very cheaply be inherited by spawned threads.
     ///
     /// (That technically makes it a set of linked lists with shared tails, so a linked tree.)
     static SPAWN_HOOKS: Cell<SpawnHooks> = const { Cell::new(SpawnHooks { first: None }) };
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index 03af35e809c..393426be087 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -95,10 +95,10 @@ use crate::sys_common::{FromInner, IntoInner};
 /// let now = Instant::now();
 /// let days_per_10_millennia = 365_2425;
 /// let solar_seconds_per_day = 60 * 60 * 24;
-/// let millenium_in_solar_seconds = 31_556_952_000;
-/// assert_eq!(millenium_in_solar_seconds, days_per_10_millennia * solar_seconds_per_day / 10);
+/// let millennium_in_solar_seconds = 31_556_952_000;
+/// assert_eq!(millennium_in_solar_seconds, days_per_10_millennia * solar_seconds_per_day / 10);
 ///
-/// let duration = Duration::new(millenium_in_solar_seconds, 0);
+/// let duration = Duration::new(millennium_in_solar_seconds, 0);
 /// println!("{:?}", now + duration);
 /// ```
 ///