lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20230726164535.230515-9-amiculas@cisco.com>
Date:   Wed, 26 Jul 2023 19:45:32 +0300
From:   Ariel Miculas <amiculas@...co.com>
To:     rust-for-linux@...r.kernel.org
Cc:     linux-kernel@...r.kernel.org, linux-fsdevel@...r.kernel.org,
        tycho@...ho.pizza, brauner@...nel.org, viro@...iv.linux.org.uk,
        ojeda@...nel.org, alex.gaynor@...il.com, wedsonaf@...il.com,
        Ariel Miculas <amiculas@...co.com>
Subject: [RFC PATCH v2 08/10] rust: puzzlefs: read the puzzlefs image manifest instead of an individual metadata layer

The puzzlefs image manifest is the file referenced by index.json and it
contains the array of metadata layers that describe the puzzlefs image.
This file represents the root of the puzzlefs filesystem since we can't
parse json files. When this filesystem is mounted, usermode will need to
read the tag from index.json, find the corresponding puzzlefs image
manifest and pass it to the kernel module.

Due to the lack of BTreeMap in the kernel, only image manifests without
fs verity information are supported for now.

Signed-off-by: Ariel Miculas <amiculas@...co.com>
---
 samples/rust/puzzle.rs       |  1 +
 samples/rust/puzzle/inode.rs | 22 ++++++++++++----
 samples/rust/puzzle/oci.rs   | 51 ++++++++++++++++++++++++++++++++++++
 samples/rust/puzzlefs.rs     | 23 ++++++++--------
 4 files changed, 80 insertions(+), 17 deletions(-)
 create mode 100644 samples/rust/puzzle/oci.rs

diff --git a/samples/rust/puzzle.rs b/samples/rust/puzzle.rs
index a809cddfb817..e74a248c39ff 100644
--- a/samples/rust/puzzle.rs
+++ b/samples/rust/puzzle.rs
@@ -2,3 +2,4 @@
 pub(crate) mod types;
 pub(crate) use types::{manifest_capnp, metadata_capnp};
 pub(crate) mod inode;
+pub(crate) mod oci;
diff --git a/samples/rust/puzzle/inode.rs b/samples/rust/puzzle/inode.rs
index d792f661aa00..f63cdbc1eac4 100644
--- a/samples/rust/puzzle/inode.rs
+++ b/samples/rust/puzzle/inode.rs
@@ -3,20 +3,32 @@
 
 use crate::puzzle::error::Result;
 use crate::puzzle::error::WireFormatError;
+use crate::puzzle::oci::Image;
 use crate::puzzle::types as format;
-use crate::puzzle::types::{Inode, InodeMode, MetadataBlob};
+use crate::puzzle::types::{Digest, Inode, InodeMode};
 use alloc::vec::Vec;
+use kernel::mount::Vfsmount;
 use kernel::prelude::ENOENT;
+use kernel::str::CStr;
+use kernel::sync::Arc;
 
 pub(crate) struct PuzzleFS {
+    pub(crate) oci: Image,
     layers: Vec<format::MetadataBlob>,
 }
 
 impl PuzzleFS {
-    pub(crate) fn new(md: MetadataBlob) -> Result<Self> {
-        let mut v = Vec::new();
-        v.try_push(md)?;
-        Ok(PuzzleFS { layers: v })
+    pub(crate) fn open(vfsmount: Arc<Vfsmount>, rootfs_path: &CStr) -> Result<PuzzleFS> {
+        let oci = Image::open(vfsmount)?;
+        let rootfs = oci.open_rootfs_blob(rootfs_path)?;
+
+        let mut layers = Vec::new();
+        for md in rootfs.metadatas.iter() {
+            let digest = Digest::try_from(md)?;
+            layers.try_push(oci.open_metadata_blob(&digest)?)?;
+        }
+
+        Ok(PuzzleFS { oci, layers })
     }
 
     pub(crate) fn find_inode(&self, ino: u64) -> Result<Inode> {
diff --git a/samples/rust/puzzle/oci.rs b/samples/rust/puzzle/oci.rs
new file mode 100644
index 000000000000..becb2b868450
--- /dev/null
+++ b/samples/rust/puzzle/oci.rs
@@ -0,0 +1,51 @@
+use crate::puzzle::error::Result;
+use crate::puzzle::types::{Digest, MetadataBlob, Rootfs};
+use kernel::c_str;
+use kernel::file;
+use kernel::file::RegularFile;
+use kernel::mount::Vfsmount;
+use kernel::pr_info;
+use kernel::str::{CStr, CString};
+use kernel::sync::Arc;
+
+pub(crate) struct Image {
+    vfs_mount: Arc<Vfsmount>,
+}
+
+impl Image {
+    pub(crate) fn open(vfsmount: Arc<Vfsmount>) -> Result<Self> {
+        Ok(Image {
+            vfs_mount: vfsmount,
+        })
+    }
+
+    pub(crate) fn blob_path_relative(&self) -> &CStr {
+        c_str!("blobs/sha256")
+    }
+
+    fn open_raw_blob(&self, digest: &Digest) -> Result<RegularFile> {
+        let filename =
+            CString::try_from_fmt(format_args!("{}/{digest}", self.blob_path_relative()))?;
+        pr_info!("trying to open {:?}\n", &filename);
+
+        let file = RegularFile::from_path_in_root_mnt(
+            &self.vfs_mount,
+            &filename,
+            file::flags::O_RDONLY.try_into().unwrap(),
+            0,
+        )?;
+
+        Ok(file)
+    }
+
+    pub(crate) fn open_metadata_blob(&self, digest: &Digest) -> Result<MetadataBlob> {
+        let f = self.open_raw_blob(digest)?;
+        MetadataBlob::new(f)
+    }
+
+    pub(crate) fn open_rootfs_blob(&self, path: &CStr) -> Result<Rootfs> {
+        let digest = Digest::try_from(path)?;
+        let rootfs = Rootfs::open(self.open_raw_blob(&digest)?)?;
+        Ok(rootfs)
+    }
+}
diff --git a/samples/rust/puzzlefs.rs b/samples/rust/puzzlefs.rs
index 1f0073716d91..76dc59403db3 100644
--- a/samples/rust/puzzlefs.rs
+++ b/samples/rust/puzzlefs.rs
@@ -14,7 +14,7 @@
 mod puzzle;
 // Required by the autogenerated '_capnp.rs' files
 use puzzle::inode::PuzzleFS;
-use puzzle::types::{Inode, InodeMode, MetadataBlob};
+use puzzle::types::{Inode, InodeMode};
 use puzzle::{manifest_capnp, metadata_capnp};
 
 use kernel::fs::{DEntry, INodeParams, NeedsRoot, NewSuperBlock, RootDEntry};
@@ -69,7 +69,7 @@ fn puzzlefs_populate_dir(
         return Err(E2BIG);
     }
 
-    let inode = Arc::try_new(pfs.find_inode(ino).map_err(|_| EINVAL)?)?;
+    let inode = Arc::try_new(pfs.find_inode(ino)?)?;
     match &inode.mode {
         InodeMode::File { chunks: _ } => {
             let params = INodeParams {
@@ -154,18 +154,17 @@ fn fill_super(_data: (), sb: fs::NewSuperBlock<'_, Self>) -> Result<&fs::SuperBl
             },
         )?;
 
-        let file = file::RegularFile::from_path_in_root_mnt(
-            &arc_vfs_mount,
-            c_str!("997eed138af30d187e87d682dd2ae9f240fae78f668907a0519460b397c82467"),
-            file::flags::O_RDONLY.try_into().unwrap(),
-            0,
-        )?;
+        let puzzlefs = PuzzleFS::open(
+            arc_vfs_mount,
+            c_str!("2d6602d678140540dc7e96de652a76a8b16e8aca190bae141297bcffdcae901b"),
+        );
 
-        // TODO: figure out how to go from WireFormatError to kernel::error::Error
-        let metadata = MetadataBlob::new(file).map_err(|_| EINVAL)?;
+        if let Err(ref e) = puzzlefs {
+            pr_info!("error opening puzzlefs {e}\n");
+        }
 
-        let mut puzzlefs = PuzzleFS::new(metadata).map_err(|_| EINVAL)?;
-        let root_inode = Arc::try_new(puzzlefs.find_inode(1).map_err(|_| EINVAL)?)?;
+        let mut puzzlefs = puzzlefs?;
+        let root_inode = Arc::try_new(puzzlefs.find_inode(1)?)?;
 
         let root = try_new_populated_root_puzzlefs_dentry(&sb, &mut puzzlefs, root_inode)?;
         let sb = sb.init_root(root)?;
-- 
2.41.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ