File 0002-Fix-CVE-2022-21658-for-WASI.patch of Package rust1.55.22465

From e278518f1f8ae1afd64048668b894dcdac1723d3 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Tue, 4 Jan 2022 08:44:15 -0800
Subject: [PATCH 2/2] Fix CVE-2022-21658 for WASI

---
 library/std/src/sys/wasi/fs.rs | 71 ++++++++++++++++++++++++++++++----
 1 file changed, 63 insertions(+), 8 deletions(-)

diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs
index 8ffa1c88d88..c34b7bb75b4 100644
--- a/library/std/src/sys/wasi/fs.rs
+++ b/library/std/src/sys/wasi/fs.rs
@@ -14,7 +14,7 @@
 use crate::sys::unsupported;
 use crate::sys_common::FromInner;
 
-pub use crate::sys_common::fs::{remove_dir_all, try_exists};
+pub use crate::sys_common::fs::try_exists;
 
 pub struct File {
     fd: WasiFd,
@@ -128,6 +128,18 @@ pub fn bits(&self) -> wasi::Filetype {
     }
 }
 
+impl ReadDir {
+    fn new(dir: File, root: PathBuf) -> ReadDir {
+        ReadDir {
+            cookie: Some(0),
+            buf: vec![0; 128],
+            offset: 0,
+            cap: 0,
+            inner: Arc::new(ReadDirInner { dir, root }),
+        }
+    }
+}
+
 impl fmt::Debug for ReadDir {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("ReadDir").finish_non_exhaustive()
@@ -482,13 +494,7 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
     opts.directory(true);
     opts.read(true);
     let dir = File::open(p, &opts)?;
-    Ok(ReadDir {
-        cookie: Some(0),
-        buf: vec![0; 128],
-        offset: 0,
-        cap: 0,
-        inner: Arc::new(ReadDirInner { dir, root: p.to_path_buf() }),
-    })
+    Ok(ReadDir::new(dir, p.to_path_buf()))
 }
 
 pub fn unlink(p: &Path) -> io::Result<()> {
@@ -682,3 +688,52 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
 
     io::copy(&mut reader, &mut writer)
 }
+
+pub fn remove_dir_all(path: &Path) -> io::Result<()> {
+    let (parent, path) = open_parent(path)?;
+    remove_dir_all_recursive(&parent, &path)
+}
+
+fn remove_dir_all_recursive(parent: &WasiFd, path: &Path) -> io::Result<()> {
+    // Open up a file descriptor for the directory itself. Note that we don't
+    // follow symlinks here and we specifically open directories.
+    //
+    // At the root invocation of this function this will correctly handle
+    // symlinks passed to the top-level `remove_dir_all`. At the recursive
+    // level this will double-check that after the `readdir` call deduced this
+    // was a directory it's still a directory by the time we open it up.
+    //
+    // If the opened file was actually a symlink then the symlink is deleted,
+    // not the directory recursively.
+    let mut opts = OpenOptions::new();
+    opts.lookup_flags(0);
+    opts.directory(true);
+    opts.read(true);
+    let fd = open_at(parent, path, &opts)?;
+    if fd.file_attr()?.file_type().is_symlink() {
+        return parent.unlink_file(osstr2str(path.as_ref())?);
+    }
+
+    // this "root" is only used by `DirEntry::path` which we don't use below so
+    // it's ok for this to be a bogus value
+    let dummy_root = PathBuf::new();
+
+    // Iterate over all the entries in this directory, and travel recursively if
+    // necessary
+    for entry in ReadDir::new(fd, dummy_root) {
+        let entry = entry?;
+        let path = crate::str::from_utf8(&entry.name).map_err(|_| {
+            io::Error::new_const(io::ErrorKind::Uncategorized, &"invalid utf-8 file name found")
+        })?;
+
+        if entry.file_type()?.is_dir() {
+            remove_dir_all_recursive(&entry.inner.dir.fd, path.as_ref())?;
+        } else {
+            entry.inner.dir.fd.unlink_file(path)?;
+        }
+    }
+
+    // Once all this directory's contents are deleted it should be safe to
+    // delete the directory tiself.
+    parent.remove_directory(osstr2str(path.as_ref())?)
+}
-- 
2.34.1

openSUSE Build Service is sponsored by