Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 188 additions & 0 deletions SPECS/rpm-ostree/CVE-2026-33055.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
From cc80cb086125efb7a0c7a1f615074406c4480af7 Mon Sep 17 00:00:00 2001
From: AllSpark <allspark@microsoft.com>
Date: Mon, 30 Mar 2026 11:50:49 +0000
Subject: [PATCH] archive: Unconditionally honor PAX size (#441)

This synchronizes our behavior with most other tar parsers
(including astral-tokio-tar and Go archive/tar) ensuring
that we don't parse things differently.

The problem with parsing size in particular differently is
it's easy to craft a tar archive that appears completely differently
between two parsers. This is the case with e.g. crates.io where
astral-tokio-tar is used for validation server side, but cargo uses
the crate to upload.

With this, the two projects agree.

Signed-off-by: Colin Walters <walters@verbum.org>
Co-authored-by: Colin Walters <walters@verbum.org>
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: AI Backport of https://github.com/alexcrichton/tar-rs/commit/de1a5870e603758f430073688691165f21a33946.patch
---
vendor/tar/.cargo-checksum.json | 2 +-
vendor/tar/Cargo.toml | 10 ++++
vendor/tar/src/archive.rs | 9 ++--
vendor/tar/tests/all.rs | 95 +++++++++++++++++++++++++++++++++
4 files changed, 111 insertions(+), 5 deletions(-)

diff --git a/vendor/tar/.cargo-checksum.json b/vendor/tar/.cargo-checksum.json
index 508f784e..af640e3d 100644
--- a/vendor/tar/.cargo-checksum.json
+++ b/vendor/tar/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"9872bf9e41b9cadee45b688c9537030a993ca49a266fc7859029d8c74810d1d5","Cargo.toml":"8353c71aa4d394efa7aaeac3004d0a16fd0c7124b7bd57ea91ba87a7b2015f15","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"71079f1a0962c2cf288058f38d24735bddabd1427ac2dee72ec18cc5ae4bceed","examples/extract_file.rs":"dc487f6631d824175afc3ee33de99e80718a8ca3f9e57fddd7cac0a46c07d3ae","examples/list.rs":"36e412205eaffea8ab7f39be4173594b74e36acb369e091362b1975ee4a7a14b","examples/raw_list.rs":"0a735576ac354457d6d5a4d395d044fae99bf67a7c69960ca784a6f6a1743651","examples/write.rs":"419ac3e4155035e32b52cd8e6ae987a2d99cf82f60abbfb315c2a2c4f8e8fd19","src/archive.rs":"85a0091e02690c62379137988cd9b2689009536a0b941f1ab0581db26e9ebce6","src/builder.rs":"2914f394d44c133557532bf5765fe63e0def30ec0b447f8f2bc620e932a2036a","src/entry.rs":"705016636f7fdcad4fe20d7d2672be2b94cc53bb05e47628f5212b89e17a40fe","src/entry_type.rs":"0786688729a96b4a3135b28d40b95c3d4feaad66b9574c490cbea14814ab975f","src/error.rs":"a20813fbc52f1f2e3a79654f62de6001759f6504a06acee5b0819d4865398587","src/header.rs":"fb2b1fa943c19635826b3f2becfb82527be7d08fdac115af840da3ff06152908","src/lib.rs":"5468e413205c907c367c35d28a528389103d68fd6a5b5979bbedba7c9e6b6c99","src/pax.rs":"54002e31151f9c50e02a3da26b3cacd1d3c9a3902daee008ab76d112cf5a2430","tests/all.rs":"567a05d54e369d22efe40f3507a26e21f7878b95bd05c811250b2c350761791b","tests/entry.rs":"c1411ee09da9edb659b508867f0960e804966dfd33801f4a7afaefda331479dd","tests/header/mod.rs":"02b05639f63c39a47559650c7209817bb60282deb4f679d5b001ed936343d9de"},"package":"4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6"}
\ No newline at end of file
+{"files":{"Cargo.lock":"9872bf9e41b9cadee45b688c9537030a993ca49a266fc7859029d8c74810d1d5","Cargo.toml":"d81f54fd63aff10460d87d583e07702c8475cb32252d691eb03c18e1cb844943","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"71079f1a0962c2cf288058f38d24735bddabd1427ac2dee72ec18cc5ae4bceed","examples/extract_file.rs":"dc487f6631d824175afc3ee33de99e80718a8ca3f9e57fddd7cac0a46c07d3ae","examples/list.rs":"36e412205eaffea8ab7f39be4173594b74e36acb369e091362b1975ee4a7a14b","examples/raw_list.rs":"0a735576ac354457d6d5a4d395d044fae99bf67a7c69960ca784a6f6a1743651","examples/write.rs":"419ac3e4155035e32b52cd8e6ae987a2d99cf82f60abbfb315c2a2c4f8e8fd19","src/archive.rs":"4100bd92149fdb2a331eb84810ac317f59ef2b81925011a9ea44e3fa5dea3dba","src/builder.rs":"2914f394d44c133557532bf5765fe63e0def30ec0b447f8f2bc620e932a2036a","src/entry.rs":"705016636f7fdcad4fe20d7d2672be2b94cc53bb05e47628f5212b89e17a40fe","src/entry_type.rs":"0786688729a96b4a3135b28d40b95c3d4feaad66b9574c490cbea14814ab975f","src/error.rs":"a20813fbc52f1f2e3a79654f62de6001759f6504a06acee5b0819d4865398587","src/header.rs":"fb2b1fa943c19635826b3f2becfb82527be7d08fdac115af840da3ff06152908","src/lib.rs":"5468e413205c907c367c35d28a528389103d68fd6a5b5979bbedba7c9e6b6c99","src/pax.rs":"54002e31151f9c50e02a3da26b3cacd1d3c9a3902daee008ab76d112cf5a2430","tests/all.rs":"3500f9b4d1c3697d11101190cf1142521ec85036ae0f5283c5e68f9aba86ce0a","tests/entry.rs":"c1411ee09da9edb659b508867f0960e804966dfd33801f4a7afaefda331479dd","tests/header/mod.rs":"02b05639f63c39a47559650c7209817bb60282deb4f679d5b001ed936343d9de"},"package":"4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6"}
\ No newline at end of file
diff --git a/vendor/tar/Cargo.toml b/vendor/tar/Cargo.toml
index 23771b56..e55390bd 100644
--- a/vendor/tar/Cargo.toml
+++ b/vendor/tar/Cargo.toml
@@ -24,9 +24,19 @@ license = "MIT/Apache-2.0"
repository = "https://github.com/alexcrichton/tar-rs"
[dependencies.filetime]
version = "0.2.8"
+[dev-dependencies.astral-tokio-tar]
+version = "0.5"
+
[dev-dependencies.tempfile]
version = "3"

+[dev-dependencies.tokio]
+version = "1"
+features = ["macros", "rt"]
+
+[dev-dependencies.tokio-stream]
+version = "0.1"
+
[features]
default = ["xattr"]
[target."cfg(unix)".dependencies.libc]
diff --git a/vendor/tar/src/archive.rs b/vendor/tar/src/archive.rs
index 1bed5124..221d1551 100644
--- a/vendor/tar/src/archive.rs
+++ b/vendor/tar/src/archive.rs
@@ -290,10 +290,11 @@ impl<'a> EntriesFields<'a> {

let file_pos = self.next;
let mut size = header.entry_size()?;
- if size == 0 {
- if let Some(pax_size) = pax_size {
- size = pax_size;
- }
+ // If this exists, it must override the header size. Disagreement among
+ // parsers allows construction of malicious archives that appear different
+ // when parsed.
+ if let Some(pax_size) = pax_size {
+ size = pax_size;
}
let ret = EntryFields {
size: size,
diff --git a/vendor/tar/tests/all.rs b/vendor/tar/tests/all.rs
index 11103bd6..bd31e871 100644
--- a/vendor/tar/tests/all.rs
+++ b/vendor/tar/tests/all.rs
@@ -1385,3 +1385,98 @@ fn header_size_overflow() {
err
);
}
+
+/// Regression test for PAX size smuggling.
+///
+/// A crafted archive uses a PAX extended header to declare a file size (2048)
+/// larger than the header's octal size field (8). Before the fix, `tar-rs`
+/// only applied the PAX size override when the header size was 0, so it would
+/// read the small header size, advance too little, and expose a symlink entry
+/// hidden in the "padding" area. After the fix, the PAX size unconditionally
+/// overrides the header size, causing the parser to skip over the smuggled
+/// symlink — matching the behavior of compliant parsers.
+#[test]
+fn pax_size_smuggled_symlink() {
+ let data = build_pax_smuggle_archive();
+
+ let mut archive = Archive::new(random_cursor_reader(&data[..]));
+ let entries: Vec<_> = archive
+ .entries()
+ .unwrap()
+ .map(|e| {
+ let e = e.unwrap();
+ let path = e.path().unwrap().to_path_buf();
+ let kind = e.header().entry_type();
+ let link = e.link_name().unwrap().map(|l| l.to_path_buf());
+ (path, kind, link)
+ })
+ .collect();
+
+ // With the fix applied, only "regular.txt" should be visible.
+ // The smuggled symlink must NOT appear.
+ let expected: Vec<(PathBuf, EntryType, Option<PathBuf>)> =
+ vec![(PathBuf::from("regular.txt"), EntryType::Regular, None)];
+ assert_eq!(
+ entries, expected,
+ "smuggled symlink visible or unexpected entries\n\
+ got: {entries:?}"
+ );
+}
+
+/// Cross-validate that `tar` and `astral-tokio-tar` parse the PAX size
+/// smuggling archive identically, guarding against parsing differentials.
+#[tokio::test]
+async fn pax_size_smuggle_matches_astral_tokio_tar() {
+ use tokio_stream::StreamExt;
+
+ let data = build_pax_smuggle_archive();
+
+ // Parse with sync tar.
+ let sync_entries: Vec<_> = {
+ let mut ar = Archive::new(&data[..]);
+ ar.entries()
+ .unwrap()
+ .map(|e| {
+ let e = e.unwrap();
+ let path = e.path().unwrap().to_path_buf();
+ let kind = e.header().entry_type();
+ let link = e.link_name().unwrap().map(|l| l.to_path_buf());
+ (path, kind, link)
+ })
+ .collect()
+ };
+
+ // Parse with async astral-tokio-tar.
+ let async_entries: Vec<_> = {
+ let mut ar = tokio_tar::Archive::new(&data[..]);
+ let mut entries = ar.entries().unwrap();
+ let mut result = Vec::new();
+ while let Some(e) = entries.next().await {
+ let e = e.unwrap();
+ let entry_type = e.header().entry_type();
+ result.push((
+ e.path().unwrap().to_path_buf(),
+ // Map through the raw byte so the two crates' EntryTypes compare.
+ EntryType::new(entry_type.as_byte()),
+ e.link_name().unwrap().map(|l| l.to_path_buf()),
+ ));
+ }
+ result
+ };
+
+ // Assert exact expected content for both parsers independently,
+ // so we verify correctness — not just mutual agreement.
+ let expected: Vec<(PathBuf, EntryType, Option<PathBuf>)> =
+ vec![(PathBuf::from("regular.txt"), EntryType::Regular, None)];
+
+ assert_eq!(
+ sync_entries, expected,
+ "tar-rs produced unexpected entries (smuggled symlink visible?)\n\
+ got: {sync_entries:?}"
+ );
+ assert_eq!(
+ async_entries, expected,
+ "astral-tokio-tar produced unexpected entries (smuggled symlink visible?)\n\
+ got: {async_entries:?}"
+ );
+}
\ No newline at end of file
--
2.45.4

160 changes: 160 additions & 0 deletions SPECS/rpm-ostree/CVE-2026-33056.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
From bf01fa7e17e3794c480a6b1a8056525cdfdb2da7 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Thu, 19 Mar 2026 16:58:05 -0500
Subject: [PATCH] archive: Prevent symlink-directory collision chmod attack
(#442)

When unpacking a tarball containing a symlink followed by a directory
entry with the same path, unpack_dir previously used fs::metadata()
which follows symlinks. This allowed an attacker to modify permissions
on arbitrary directories outside the extraction path.

The fix uses fs::symlink_metadata() to detect symlinks and refuse to
treat them as valid existing directories.

Document more exhaustively+consistently security caveats.

Reported-by: Sergei Zimmerman <https://github.com/xokdvium>
Assisted-by: OpenCode (Claude claude-opus-4-5)

Signed-off-by: Colin Walters <walters@verbum.org>
Co-authored-by: Colin Walters <walters@verbum.org>
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: https://github.com/alexcrichton/tar-rs/commit/17b1fd84e632071cb8eef9d3709bf347bd266446.patch
---
vendor/tar/.cargo-checksum.json | 2 +-
vendor/tar/src/archive.rs | 18 +++++++++--
vendor/tar/src/entry.rs | 7 +++--
vendor/tar/tests/entry.rs | 56 +++++++++++++++++++++++++++++++++
4 files changed, 76 insertions(+), 7 deletions(-)

diff --git a/vendor/tar/.cargo-checksum.json b/vendor/tar/.cargo-checksum.json
index af640e3d..e029e340 100644
--- a/vendor/tar/.cargo-checksum.json
+++ b/vendor/tar/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"9872bf9e41b9cadee45b688c9537030a993ca49a266fc7859029d8c74810d1d5","Cargo.toml":"d81f54fd63aff10460d87d583e07702c8475cb32252d691eb03c18e1cb844943","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"71079f1a0962c2cf288058f38d24735bddabd1427ac2dee72ec18cc5ae4bceed","examples/extract_file.rs":"dc487f6631d824175afc3ee33de99e80718a8ca3f9e57fddd7cac0a46c07d3ae","examples/list.rs":"36e412205eaffea8ab7f39be4173594b74e36acb369e091362b1975ee4a7a14b","examples/raw_list.rs":"0a735576ac354457d6d5a4d395d044fae99bf67a7c69960ca784a6f6a1743651","examples/write.rs":"419ac3e4155035e32b52cd8e6ae987a2d99cf82f60abbfb315c2a2c4f8e8fd19","src/archive.rs":"4100bd92149fdb2a331eb84810ac317f59ef2b81925011a9ea44e3fa5dea3dba","src/builder.rs":"2914f394d44c133557532bf5765fe63e0def30ec0b447f8f2bc620e932a2036a","src/entry.rs":"705016636f7fdcad4fe20d7d2672be2b94cc53bb05e47628f5212b89e17a40fe","src/entry_type.rs":"0786688729a96b4a3135b28d40b95c3d4feaad66b9574c490cbea14814ab975f","src/error.rs":"a20813fbc52f1f2e3a79654f62de6001759f6504a06acee5b0819d4865398587","src/header.rs":"fb2b1fa943c19635826b3f2becfb82527be7d08fdac115af840da3ff06152908","src/lib.rs":"5468e413205c907c367c35d28a528389103d68fd6a5b5979bbedba7c9e6b6c99","src/pax.rs":"54002e31151f9c50e02a3da26b3cacd1d3c9a3902daee008ab76d112cf5a2430","tests/all.rs":"3500f9b4d1c3697d11101190cf1142521ec85036ae0f5283c5e68f9aba86ce0a","tests/entry.rs":"c1411ee09da9edb659b508867f0960e804966dfd33801f4a7afaefda331479dd","tests/header/mod.rs":"02b05639f63c39a47559650c7209817bb60282deb4f679d5b001ed936343d9de"},"package":"4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6"}
\ No newline at end of file
+{"files":{"Cargo.lock":"9872bf9e41b9cadee45b688c9537030a993ca49a266fc7859029d8c74810d1d5","Cargo.toml":"d81f54fd63aff10460d87d583e07702c8475cb32252d691eb03c18e1cb844943","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"71079f1a0962c2cf288058f38d24735bddabd1427ac2dee72ec18cc5ae4bceed","examples/extract_file.rs":"dc487f6631d824175afc3ee33de99e80718a8ca3f9e57fddd7cac0a46c07d3ae","examples/list.rs":"36e412205eaffea8ab7f39be4173594b74e36acb369e091362b1975ee4a7a14b","examples/raw_list.rs":"0a735576ac354457d6d5a4d395d044fae99bf67a7c69960ca784a6f6a1743651","examples/write.rs":"419ac3e4155035e32b52cd8e6ae987a2d99cf82f60abbfb315c2a2c4f8e8fd19","src/archive.rs":"7749c1f9b57b671a913dcd4e44c2d22a39dfe0795bf33454c0d97d79705b2c38","src/builder.rs":"2914f394d44c133557532bf5765fe63e0def30ec0b447f8f2bc620e932a2036a","src/entry.rs":"2f3ff18dc0c693f425488f946e8a7d250c4020134ca870fe5522d9a95b6a6ae0","src/entry_type.rs":"0786688729a96b4a3135b28d40b95c3d4feaad66b9574c490cbea14814ab975f","src/error.rs":"a20813fbc52f1f2e3a79654f62de6001759f6504a06acee5b0819d4865398587","src/header.rs":"fb2b1fa943c19635826b3f2becfb82527be7d08fdac115af840da3ff06152908","src/lib.rs":"5468e413205c907c367c35d28a528389103d68fd6a5b5979bbedba7c9e6b6c99","src/pax.rs":"54002e31151f9c50e02a3da26b3cacd1d3c9a3902daee008ab76d112cf5a2430","tests/all.rs":"3500f9b4d1c3697d11101190cf1142521ec85036ae0f5283c5e68f9aba86ce0a","tests/entry.rs":"97b7927f14027c2f9bce2dc5f565ede00b9c37da41d0ee95144be8c0cb8c6983","tests/header/mod.rs":"02b05639f63c39a47559650c7209817bb60282deb4f679d5b001ed936343d9de"},"package":"4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6"}
\ No newline at end of file
diff --git a/vendor/tar/src/archive.rs b/vendor/tar/src/archive.rs
index 221d1551..19e8d13c 100644
--- a/vendor/tar/src/archive.rs
+++ b/vendor/tar/src/archive.rs
@@ -88,9 +88,21 @@ impl<R: Read> Archive<R> {
/// extracting each file in turn to the location specified by the entry's
/// path name.
///
- /// This operation is relatively sensitive in that it will not write files
- /// outside of the path specified by `dst`. Files in the archive which have
- /// a '..' in their path are skipped during the unpacking process.
+ /// # Security
+ ///
+ /// A best-effort is made to prevent writing files outside `dst` (paths
+ /// containing `..` are skipped, symlinks are validated). However, there
+ /// have been historical bugs in this area, and more may exist. For this
+ /// reason, when processing untrusted archives, stronger sandboxing is
+ /// encouraged: e.g. the [`cap-std`] crate and/or OS-level
+ /// containerization/virtualization.
+ ///
+ /// If `dst` does not exist, it is created. Unpacking into an existing
+ /// directory merges content. This function assumes `dst` is not
+ /// concurrently modified by untrusted processes. Protecting against
+ /// TOCTOU races is out of scope for this crate.
+ ///
+ /// [`cap-std`]: https://docs.rs/cap-std/
///
/// # Examples
///
diff --git a/vendor/tar/src/entry.rs b/vendor/tar/src/entry.rs
index 8f0b62ac..287d6890 100644
--- a/vendor/tar/src/entry.rs
+++ b/vendor/tar/src/entry.rs
@@ -210,8 +210,9 @@ impl<'a, R: Read> Entry<'a, R> {
/// also be propagated to the path `dst`. Any existing file at the location
/// `dst` will be overwritten.
///
- /// This function carefully avoids writing outside of `dst`. If the file has
- /// a '..' in its path, this function will skip it and return false.
+ /// # Security
+ ///
+ /// See [`Archive::unpack`].
///
/// # Examples
///
@@ -430,7 +431,7 @@ impl<'a> EntryFields<'a> {
// If the directory already exists just let it slide
fs::create_dir(dst).or_else(|err| {
if err.kind() == ErrorKind::AlreadyExists {
- let prev = fs::metadata(dst);
+ let prev = fs::symlink_metadata(dst);
if prev.map(|m| m.is_dir()).unwrap_or(false) {
return Ok(());
}
diff --git a/vendor/tar/tests/entry.rs b/vendor/tar/tests/entry.rs
index fa8eeaee..5e874fa5 100644
--- a/vendor/tar/tests/entry.rs
+++ b/vendor/tar/tests/entry.rs
@@ -377,3 +377,59 @@ fn modify_symlink_just_created() {
t!(t!(File::open(&test)).read_to_end(&mut contents));
assert_eq!(contents.len(), 0);
}
+
+/// Test that unpacking a tarball with a symlink followed by a directory entry
+/// with the same name does not allow modifying permissions of arbitrary directories
+/// outside the extraction path.
+#[test]
+#[cfg(unix)]
+fn symlink_dir_collision_does_not_modify_external_dir_permissions() {
+ use ::std::fs;
+ use ::std::os::unix::fs::PermissionsExt;
+
+ let td = Builder::new().prefix("tar").tempdir().unwrap();
+
+ let target_dir = td.path().join("target-dir");
+ fs::create_dir(&target_dir).unwrap();
+ fs::set_permissions(&target_dir, fs::Permissions::from_mode(0o700)).unwrap();
+ let before_mode = fs::metadata(&target_dir).unwrap().permissions().mode() & 0o7777;
+ assert_eq!(before_mode, 0o700);
+
+ let extract_dir = td.path().join("extract-dir");
+ fs::create_dir(&extract_dir).unwrap();
+
+ let mut ar = tar::Builder::new(Vec::new());
+
+ let mut header = tar::Header::new_gnu();
+ header.set_size(0);
+ header.set_entry_type(tar::EntryType::Symlink);
+ header.set_path("foo").unwrap();
+ header.set_link_name(&target_dir).unwrap();
+ header.set_mode(0o777);
+ header.set_cksum();
+ ar.append(&header, &[][..]).unwrap();
+
+ let mut header = tar::Header::new_gnu();
+ header.set_size(0);
+ header.set_entry_type(tar::EntryType::Directory);
+ header.set_path("foo").unwrap();
+ header.set_mode(0o777);
+ header.set_cksum();
+ ar.append(&header, &[][..]).unwrap();
+
+ let bytes = ar.into_inner().unwrap();
+ let mut ar = tar::Archive::new(&bytes[..]);
+
+ let result = ar.unpack(&extract_dir);
+ assert!(result.is_err());
+
+ let symlink_path = extract_dir.join("foo");
+ assert!(symlink_path
+ .symlink_metadata()
+ .unwrap()
+ .file_type()
+ .is_symlink());
+
+ let after_mode = fs::metadata(&target_dir).unwrap().permissions().mode() & 0o7777;
+ assert_eq!(after_mode, 0o700);
+}
--
2.45.4

Loading
Loading