Skip to content

Commit

Permalink
Auto merge of rust-lang#123682 - pietroalbini:pa-cve-2024-24576-beta,…
Browse files Browse the repository at this point in the history
… r=pietroalbini

[beta] Backport fix of CVE-2024-24576

r? `@ghost`

See https://blog.rust-lang.org/2024/04/09/cve-2024-24576.html
  • Loading branch information
bors committed Apr 9, 2024
2 parents 9eff510 + fa1e080 commit 27011d5
Show file tree
Hide file tree
Showing 9 changed files with 456 additions and 14 deletions.
134 changes: 134 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,137 @@
Version 1.77.2 (2024-04-09)
===========================

<a id="1.77.2"></a>

- [CVE-2024-24576: fix escaping of Windows batch file arguments in `std::process::Command`](https://blog.rust-lang.org/2024/04/09/cve-2024-24576.html)

Version 1.77.1 (2024-03-28)
===========================

<a id="1.77.1"></a>

- [Revert stripping debuginfo by default for Windows](https://github.com/rust-lang/cargo/pull/13654)
This fixes a regression in 1.77 by reverting to the previous default.
Platforms other than Windows are not affected.
- Internal: [Fix heading anchor rendering in doc pages](https://github.com/rust-lang/rust/pull/122693)

Version 1.77.0 (2024-03-21)
==========================

<a id="1.77.0-Language"></a>

Language
--------

- [Reveal opaque types within the defining body for exhaustiveness checking.](https://github.com/rust-lang/rust/pull/116821/)
- [Stabilize C-string literals.](https://github.com/rust-lang/rust/pull/117472/)
- [Stabilize THIR unsafeck.](https://github.com/rust-lang/rust/pull/117673/)
- [Add lint `static_mut_refs` to warn on references to mutable statics.](https://github.com/rust-lang/rust/pull/117556/)
- [Support async recursive calls (as long as they have indirection).](https://github.com/rust-lang/rust/pull/117703/)
- [Undeprecate lint `unstable_features` and make use of it in the compiler.](https://github.com/rust-lang/rust/pull/118639/)
- [Make inductive cycles in coherence ambiguous always.](https://github.com/rust-lang/rust/pull/118649/)
- [Get rid of type-driven traversal in const-eval interning](https://github.com/rust-lang/rust/pull/119044/),
only as a [future compatiblity lint](https://github.com/rust-lang/rust/pull/122204) for now.
- [Deny braced macro invocations in let-else.](https://github.com/rust-lang/rust/pull/119062/)

<a id="1.77.0-Compiler"></a>

Compiler
--------

- [Include lint `soft_unstable` in future breakage reports.](https://github.com/rust-lang/rust/pull/116274/)
- [Make `i128` and `u128` 16-byte aligned on x86-based targets.](https://github.com/rust-lang/rust/pull/116672/)
- [Use `--verbose` in diagnostic output.](https://github.com/rust-lang/rust/pull/119129/)
- [Improve spacing between printed tokens.](https://github.com/rust-lang/rust/pull/120227/)
- [Merge the `unused_tuple_struct_fields` lint into `dead_code`.](https://github.com/rust-lang/rust/pull/118297/)
- [Error on incorrect implied bounds in well-formedness check](https://github.com/rust-lang/rust/pull/118553/),
with a temporary exception for Bevy.
- [Fix coverage instrumentation/reports for non-ASCII source code.](https://github.com/rust-lang/rust/pull/119033/)
- [Fix `fn`/`const` items implied bounds and well-formedness check.](https://github.com/rust-lang/rust/pull/120019/)
- [Promote `riscv32{im|imafc}-unknown-none-elf` targets to tier 2.](https://github.com/rust-lang/rust/pull/118704/)
- Add several new tier 3 targets:
- [`aarch64-unknown-illumos`](https://github.com/rust-lang/rust/pull/112936/)
- [`hexagon-unknown-none-elf`](https://github.com/rust-lang/rust/pull/117601/)
- [`riscv32imafc-esp-espidf`](https://github.com/rust-lang/rust/pull/119738/)
- [`riscv32im-risc0-zkvm-elf`](https://github.com/rust-lang/rust/pull/117958/)

Refer to Rust's [platform support page][platform-support-doc]
for more information on Rust's tiered platform support.

<a id="1.77.0-Libraries"></a>

Libraries
---------

- [Implement `From<&[T; N]>` for `Cow<[T]>`.](https://github.com/rust-lang/rust/pull/113489/)
- [Remove special-case handling of `vec.split_off(0)`.](https://github.com/rust-lang/rust/pull/119917/)

<a id="1.77.0-Stabilized-APIs"></a>

Stabilized APIs
---------------

- [`array::each_ref`](https://doc.rust-lang.org/stable/std/primitive.array.html#method.each_ref)
- [`array::each_mut`](https://doc.rust-lang.org/stable/std/primitive.array.html#method.each_mut)
- [`core::net`](https://doc.rust-lang.org/stable/core/net/index.html)
- [`f32::round_ties_even`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.round_ties_even)
- [`f64::round_ties_even`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.round_ties_even)
- [`mem::offset_of!`](https://doc.rust-lang.org/stable/std/mem/macro.offset_of.html)
- [`slice::first_chunk`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.first_chunk)
- [`slice::first_chunk_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.first_chunk_mut)
- [`slice::split_first_chunk`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_first_chunk)
- [`slice::split_first_chunk_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_first_chunk_mut)
- [`slice::last_chunk`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.last_chunk)
- [`slice::last_chunk_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.last_chunk_mut)
- [`slice::split_last_chunk`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_last_chunk)
- [`slice::split_last_chunk_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_last_chunk_mut)
- [`slice::chunk_by`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.chunk_by)
- [`slice::chunk_by_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.chunk_by_mut)
- [`Bound::map`](https://doc.rust-lang.org/stable/std/ops/enum.Bound.html#method.map)
- [`File::create_new`](https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.create_new)
- [`Mutex::clear_poison`](https://doc.rust-lang.org/stable/std/sync/struct.Mutex.html#method.clear_poison)
- [`RwLock::clear_poison`](https://doc.rust-lang.org/stable/std/sync/struct.RwLock.html#method.clear_poison)

<a id="1.77.0-Cargo"></a>

Cargo
-----

- [Extend the build directive syntax with `cargo::`.](https://github.com/rust-lang/cargo/pull/12201/)
- [Stabilize metadata `id` format as `PackageIDSpec`.](https://github.com/rust-lang/cargo/pull/12914/)
- [Pull out as `cargo-util-schemas` as a crate.](https://github.com/rust-lang/cargo/pull/13178/)
- [Strip all debuginfo when debuginfo is not requested.](https://github.com/rust-lang/cargo/pull/13257/)
- [Inherit jobserver from env for all kinds of runners.](https://github.com/rust-lang/cargo/pull/12776/)
- [Deprecate rustc plugin support in cargo.](https://github.com/rust-lang/cargo/pull/13248/)

<a id="1.77.0-Rustdoc"></a>

Rustdoc
-----

- [Allows links in markdown headings.](https://github.com/rust-lang/rust/pull/117662/)
- [Search for tuples and unit by type with `()`.](https://github.com/rust-lang/rust/pull/118194/)
- [Clean up the source sidebar's hide button.](https://github.com/rust-lang/rust/pull/119066/)
- [Prevent JS injection from `localStorage`.](https://github.com/rust-lang/rust/pull/120250/)

<a id="1.77.0-Misc"></a>

Misc
----

- [Recommend version-sorting for all sorting in style guide.](https://github.com/rust-lang/rust/pull/115046/)

<a id="1.77.0-Internal-Changes"></a>

Internal Changes
----------------

These changes do not affect any public interfaces of Rust, but they represent
significant improvements to the performance or internals of rustc and related
tools.

- [Add more weirdness to `weird-exprs.rs`.](https://github.com/rust-lang/rust/pull/119028/)

Version 1.76.0 (2024-02-08)
==========================

Expand Down
56 changes: 54 additions & 2 deletions library/std/src/os/windows/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,60 @@ pub trait CommandExt: Sealed {

/// Append literal text to the command line without any quoting or escaping.
///
/// This is useful for passing arguments to `cmd.exe /c`, which doesn't follow
/// `CommandLineToArgvW` escaping rules.
/// This is useful for passing arguments to applications which doesn't follow
/// the standard C run-time escaping rules, such as `cmd.exe /c`.
///
/// # Bat files
///
/// Note the `cmd /c` command line has slightly different escaping rules then bat files
/// themselves. If possible, it may be better to write complex arguments to a temporary
/// .bat file, with appropriate escaping, and simply run that using:
///
/// ```no_run
/// # use std::process::Command;
/// # let temp_bat_file = "";
/// # #[allow(unused)]
/// let output = Command::new("cmd").args(["/c", &format!("\"{temp_bat_file}\"")]).output();
/// ```
///
/// # Example
///
/// Run a bat script using both trusted and untrusted arguments.
///
/// ```no_run
/// #[cfg(windows)]
/// // `my_script_path` is a path to known bat file.
/// // `user_name` is an untrusted name given by the user.
/// fn run_script(
/// my_script_path: &str,
/// user_name: &str,
/// ) -> Result<std::process::Output, std::io::Error> {
/// use std::io::{Error, ErrorKind};
/// use std::os::windows::process::CommandExt;
/// use std::process::Command;
///
/// // Create the command line, making sure to quote the script path.
/// // This assumes the fixed arguments have been tested to work with the script we're using.
/// let mut cmd_args = format!(r#""{my_script_path}" "--features=[a,b,c]""#);
///
/// // Make sure the user name is safe. In particular we need to be
/// // cautious of ascii symbols that cmd may interpret specially.
/// // Here we only allow alphanumeric characters.
/// if !user_name.chars().all(|c| c.is_alphanumeric()) {
/// return Err(Error::new(ErrorKind::InvalidInput, "invalid user name"));
/// }
/// // now we've checked the user name, let's add that too.
/// cmd_args.push(' ');
/// cmd_args.push_str(&format!("--user {user_name}"));
///
/// // call cmd.exe and return the output
/// Command::new("cmd.exe")
/// .arg("/c")
/// // surround the entire command in an extra pair of quotes, as required by cmd.exe.
/// .raw_arg(&format!("\"{cmd_args}\""))
/// .output()
/// }
/// ````
#[stable(feature = "windows_process_extensions_raw_arg", since = "1.62.0")]
fn raw_arg<S: AsRef<OsStr>>(&mut self, text_to_append_as_is: S) -> &mut process::Command;

Expand Down
79 changes: 79 additions & 0 deletions library/std/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,47 @@
//! assert_eq!(b"test", output.stdout.as_slice());
//! ```
//!
//! # Windows argument splitting
//!
//! On Unix systems arguments are passed to a new process as an array of strings
//! but on Windows arguments are passed as a single commandline string and it's
//! up to the child process to parse it into an array. Therefore the parent and
//! child processes must agree on how the commandline string is encoded.
//!
//! Most programs use the standard C run-time `argv`, which in practice results
//! in consistent argument handling. However some programs have their own way of
//! parsing the commandline string. In these cases using [`arg`] or [`args`] may
//! result in the child process seeing a different array of arguments then the
//! parent process intended.
//!
//! Two ways of mitigating this are:
//!
//! * Validate untrusted input so that only a safe subset is allowed.
//! * Use [`raw_arg`] to build a custom commandline. This bypasses the escaping
//! rules used by [`arg`] so should be used with due caution.
//!
//! `cmd.exe` and `.bat` use non-standard argument parsing and are especially
//! vulnerable to malicious input as they may be used to run arbitrary shell
//! commands. Untrusted arguments should be restricted as much as possible.
//! For examples on handling this see [`raw_arg`].
//!
//! ### Bat file special handling
//!
//! On Windows, `Command` uses the Windows API function [`CreateProcessW`] to
//! spawn new processes. An undocumented feature of this function is that,
//! when given a `.bat` file as the application to run, it will automatically
//! convert that into running `cmd.exe /c` with the bat file as the next argument.
//!
//! For historical reasons Rust currently preserves this behaviour when using
//! [`Command::new`], and escapes the arguments according to `cmd.exe` rules.
//! Due to the complexity of `cmd.exe` argument handling, it might not be
//! possible to safely escape some special chars, and using them will result
//! in an error being returned at process spawn. The set of unescapeable
//! special chars might change between releases.
//!
//! Also note that running `.bat` scripts in this way may be removed in the
//! future and so should not be relied upon.
//!
//! [`spawn`]: Command::spawn
//! [`output`]: Command::output
//!
Expand All @@ -97,6 +138,12 @@
//!
//! [`Write`]: io::Write
//! [`Read`]: io::Read
//!
//! [`arg`]: Command::arg
//! [`args`]: Command::args
//! [`raw_arg`]: crate::os::windows::process::CommandExt::raw_arg
//!
//! [`CreateProcessW`]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw

#![stable(feature = "process", since = "1.0.0")]
#![deny(unsafe_op_in_unsafe_fn)]
Expand Down Expand Up @@ -611,6 +658,22 @@ impl Command {
/// escaped characters, word splitting, glob patterns, variable substitution, etc.
/// have no effect.
///
/// <div class="warning">
///
/// On Windows use caution with untrusted inputs. Most applications use the
/// standard convention for decoding arguments passed to them. These are safe to use with `arg`.
/// However some applications, such as `cmd.exe` and `.bat` files, use a non-standard way of decoding arguments
/// and are therefore vulnerable to malicious input.
/// In the case of `cmd.exe` this is especially important because a malicious argument can potentially run arbitrary shell commands.
///
/// See [Windows argument splitting][windows-args] for more details
/// or [`raw_arg`] for manually implementing non-standard argument encoding.
///
/// [`raw_arg`]: crate::os::windows::process::CommandExt::raw_arg
/// [windows-args]: crate::process#windows-argument-splitting
///
/// </div>
///
/// # Examples
///
/// Basic usage:
Expand Down Expand Up @@ -641,6 +704,22 @@ impl Command {
/// escaped characters, word splitting, glob patterns, variable substitution, etc.
/// have no effect.
///
/// <div class="warning">
///
/// On Windows use caution with untrusted inputs. Most applications use the
/// standard convention for decoding arguments passed to them. These are safe to use with `args`.
/// However some applications, such as `cmd.exe` and `.bat` files, use a non-standard way of decoding arguments
/// and are therefore vulnerable to malicious input.
/// In the case of `cmd.exe` this is especially important because a malicious argument can potentially run arbitrary shell commands.
///
/// See [Windows argument splitting][windows-args] for more details
/// or [`raw_arg`] for manually implementing non-standard argument encoding.
///
/// [`raw_arg`]: crate::os::windows::process::CommandExt::raw_arg
/// [windows-args]: crate::process#windows-argument-splitting
///
/// </div>
///
/// # Examples
///
/// Basic usage:
Expand Down
Loading

0 comments on commit 27011d5

Please sign in to comment.