From d331f72f2a51fa577072f24bc2587829fd87368b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 14 Feb 2021 13:45:03 -0700 Subject: [PATCH] Use UTF-8 for all paths --- Cargo.lock | 36 +++++++++++----------- Cargo.toml | 2 +- rmm | 2 +- src/context/context.rs | 40 ++++++++++++------------ src/lib.rs | 12 ++++---- src/scheme/acpi.rs | 5 ++- src/scheme/debug.rs | 2 +- src/scheme/event.rs | 2 +- src/scheme/initfs.rs | 5 ++- src/scheme/irq.rs | 5 ++- src/scheme/itimer.rs | 6 ++-- src/scheme/live.rs | 2 +- src/scheme/memory.rs | 2 +- src/scheme/mod.rs | 59 +++++++++++++++++++----------------- src/scheme/proc.rs | 10 +++--- src/scheme/root.rs | 40 ++++++++++++------------ src/scheme/serio.rs | 5 ++- src/scheme/sys/mod.rs | 46 ++++++++++++++-------------- src/scheme/sys/scheme.rs | 2 +- src/scheme/sys/scheme_num.rs | 2 +- src/scheme/time.rs | 6 ++-- src/scheme/user.rs | 42 ++++++++++++++++--------- src/syscall/fs.rs | 42 +++++++++++++------------ src/syscall/mod.rs | 12 ++++---- src/syscall/privilege.rs | 4 +-- src/syscall/process.rs | 8 +++-- src/syscall/validate.rs | 9 +++++- syscall | 2 +- 28 files changed, 217 insertions(+), 193 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d887aa2..8121fd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,17 +17,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.10" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -35,7 +35,7 @@ name = "fdt" version = "0.1.0" source = "git+https://gitlab.redox-os.org/thomhuds/fdt.git#baca9b0070c281dc99521ee901efcb10e5f84218" dependencies = [ - "byteorder 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -49,19 +49,19 @@ dependencies = [ [[package]] name = "kernel" -version = "0.1.54" +version = "0.2.5" dependencies = [ "bitfield 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.67 (registry+https://github.com/rust-lang/crates.io-index)", "fdt 0.1.0 (git+https://gitlab.redox-os.org/thomhuds/fdt.git)", "goblin 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "linked_list_allocator 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "raw-cpuid 8.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.2.4", + "redox_syscall 0.2.7", "rmm 0.1.0", "rustc-cfg 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", @@ -96,10 +96,10 @@ dependencies = [ [[package]] name = "log" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -135,7 +135,7 @@ version = "7.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.67 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -145,13 +145,13 @@ version = "8.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.67 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.2.4" +version = "0.2.7" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -241,15 +241,15 @@ dependencies = [ "checksum bit_field 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" "checksum bitfield 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum byteorder 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" -"checksum cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)" = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" -"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum byteorder 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +"checksum cc 1.0.67 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" +"checksum cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" "checksum fdt 0.1.0 (git+https://gitlab.redox-os.org/thomhuds/fdt.git)" = "" "checksum goblin 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d20fd25aa456527ce4f544271ae4fea65d2eda4a6561ea56f39fb3ee4f7e3884" "checksum linked_list_allocator 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "47de1a43fad0250ee197e9e124e5b5deab3d7b39d4428ae8a6d741ceb340c362" "checksum linked_list_allocator 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "822add9edb1860698b79522510da17bef885171f75aa395cff099d770c609c24" "checksum lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" -"checksum log 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2" +"checksum log 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" "checksum paste 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" "checksum paste-impl 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" "checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" diff --git a/Cargo.toml b/Cargo.toml index 77990ef..8eaecf6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kernel" -version = "0.1.54" +version = "0.2.5" build = "build.rs" edition = "2018" diff --git a/rmm b/rmm index 132d91d..7fd1218 160000 --- a/rmm +++ b/rmm @@ -1 +1 @@ -Subproject commit 132d91d3aaa624d1bc8709555a64ff289f7d5e4f +Subproject commit 7fd1218465b58bd88ecdaeaf63683019ad74ed41 diff --git a/src/context/context.rs b/src/context/context.rs index 8e7c3b8..5d6b444 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -1,7 +1,7 @@ use alloc::{ boxed::Box, collections::VecDeque, - string::String, + string::{String, ToString}, sync::Arc, vec::Vec, }; @@ -237,7 +237,7 @@ pub struct Context { /// The name of the context pub name: Arc>>, /// The current working directory - pub cwd: Arc>>, + pub cwd: Arc>, /// The open files in the scheme pub files: Arc>>>, /// Signal actions @@ -293,7 +293,7 @@ impl Context { tls: None, grants: Arc::new(RwLock::new(UserGrants::default())), name: Arc::new(RwLock::new(String::new().into_boxed_str())), - cwd: Arc::new(RwLock::new(Vec::new())), + cwd: Arc::new(RwLock::new(String::new())), files: Arc::new(RwLock::new(Vec::new())), actions: Arc::new(RwLock::new(vec![( SigAction { @@ -313,35 +313,34 @@ impl Context { /// This function will turn "foo" into "scheme:/path/foo" /// "/foo" will turn into "scheme:/foo" /// "bar:/foo" will be used directly, as it is already absolute - pub fn canonicalize(&self, path: &[u8]) -> Vec { - let mut canon = if path.iter().position(|&b| b == b':').is_none() { + pub fn canonicalize(&self, path: &str) -> String { + let mut canon = if path.find(':').is_none() { let cwd = self.cwd.read(); - let mut canon = if !path.starts_with(b"/") { + let mut canon = if !path.starts_with('/') { let mut c = cwd.clone(); - if ! c.ends_with(b"/") { - c.push(b'/'); + if ! c.ends_with('/') { + c.push('/'); } c } else { - cwd[..cwd.iter().position(|&b| b == b':').map_or(1, |i| i + 1)].to_vec() + cwd[..cwd.find(':').map_or(1, |i| i + 1)].to_string() }; - canon.extend_from_slice(&path); + canon.push_str(&path); canon } else { - path.to_vec() + path.to_string() }; // NOTE: assumes the scheme does not include anything like "../" or "./" let mut result = { - let parts = canon.split(|&c| c == b'/') - .filter(|&part| part != b".") + let parts = canon.split('/') .rev() .scan(0, |nskip, part| { - if part == b"." { + if part == "." { Some(None) - } else if part == b".." { + } else if part == ".." { *nskip += 1; Some(None) } else if *nskip > 0 { @@ -357,18 +356,17 @@ impl Context { parts .iter() .rev() - .fold(Vec::new(), |mut vec, &part| { - vec.extend_from_slice(part); - vec.push(b'/'); - vec + .fold(String::new(), |mut string, &part| { + string.push_str(part); + string.push('/'); + string }) }; result.pop(); // remove extra '/' // replace with the root of the scheme if it's empty if result.is_empty() { - let pos = canon.iter() - .position(|&b| b == b':') + let pos = canon.find(':') .map_or(canon.len(), |p| p + 1); canon.truncate(pos); canon diff --git a/src/lib.rs b/src/lib.rs index ec36059..0770027 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -168,24 +168,24 @@ static mut INIT_ENV: &[u8] = &[]; /// Initialize userspace by running the initfs:bin/init process /// This function will also set the CWD to initfs:bin and open debug: as stdio pub extern fn userspace_init() { - let path = b"initfs:/bin/init"; + let path = "initfs:/bin/init"; let env = unsafe { INIT_ENV }; - if let Err(err) = syscall::chdir(b"initfs:") { + if let Err(err) = syscall::chdir("initfs:") { info!("Failed to enter initfs ({}).", err); info!("Perhaps the kernel was compiled with an incorrect INITFS_FOLDER \ environment variable value?"); panic!("Unexpected error while trying to enter initfs:."); } - assert_eq!(syscall::open(b"debug:", syscall::flag::O_RDONLY).map(FileHandle::into), Ok(0)); - assert_eq!(syscall::open(b"debug:", syscall::flag::O_WRONLY).map(FileHandle::into), Ok(1)); - assert_eq!(syscall::open(b"debug:", syscall::flag::O_WRONLY).map(FileHandle::into), Ok(2)); + assert_eq!(syscall::open("debug:", syscall::flag::O_RDONLY).map(FileHandle::into), Ok(0)); + assert_eq!(syscall::open("debug:", syscall::flag::O_WRONLY).map(FileHandle::into), Ok(1)); + assert_eq!(syscall::open("debug:", syscall::flag::O_WRONLY).map(FileHandle::into), Ok(2)); let fd = syscall::open(path, syscall::flag::O_RDONLY).expect("failed to open init"); let mut args = Vec::new(); - args.push(path.to_vec().into_boxed_slice()); + args.push(path.as_bytes().to_vec().into_boxed_slice()); let mut vars = Vec::new(); for var in env.split(|b| *b == b'\n') { diff --git a/src/scheme/acpi.rs b/src/scheme/acpi.rs index 9fe6020..f5fb2fc 100644 --- a/src/scheme/acpi.rs +++ b/src/scheme/acpi.rs @@ -217,13 +217,12 @@ fn serialize_table_filename( } impl Scheme for AcpiScheme { - fn open(&self, path: &[u8], flags: usize, opener_uid: u32, _opener_gid: u32) -> Result { + fn open(&self, path: &str, flags: usize, opener_uid: u32, _opener_gid: u32) -> Result { if opener_uid != 0 { return Err(Error::new(EACCES)); } - let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?; - let path_str = path_str.trim_start_matches('/'); + let path_str = path.trim_start_matches('/'); // TODO: Use some kind of component iterator. diff --git a/src/scheme/debug.rs b/src/scheme/debug.rs index 6b82441..b470953 100644 --- a/src/scheme/debug.rs +++ b/src/scheme/debug.rs @@ -57,7 +57,7 @@ impl DebugScheme { } impl Scheme for DebugScheme { - fn open(&self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { + fn open(&self, path: &str, flags: usize, uid: u32, _gid: u32) -> Result { if uid != 0 { return Err(Error::new(EPERM)); } diff --git a/src/scheme/event.rs b/src/scheme/event.rs index e7ea1ff..3ae5015 100644 --- a/src/scheme/event.rs +++ b/src/scheme/event.rs @@ -9,7 +9,7 @@ use crate::syscall::scheme::Scheme; pub struct EventScheme; impl Scheme for EventScheme { - fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { + fn open(&self, _path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result { let id = next_queue_id(); queues_mut().insert(id, Arc::new(EventQueue::new(id))); diff --git a/src/scheme/initfs.rs b/src/scheme/initfs.rs index d5d6447..80a557d 100644 --- a/src/scheme/initfs.rs +++ b/src/scheme/initfs.rs @@ -41,9 +41,8 @@ impl InitFsScheme { } impl Scheme for InitFsScheme { - fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { - let path_utf8 = str::from_utf8(path).or(Err(Error::new(ENOENT)))?; - let path_trimmed = path_utf8.trim_matches('/'); + fn open(&self, path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result { + let path_trimmed = path.trim_matches('/'); //Have to iterate to get the path without allocation for entry in self.files.iter() { diff --git a/src/scheme/irq.rs b/src/scheme/irq.rs index d5938d0..ee24f7d 100644 --- a/src/scheme/irq.rs +++ b/src/scheme/irq.rs @@ -139,11 +139,10 @@ const fn vector_to_irq(vector: u8) -> u8 { } impl Scheme for IrqScheme { - fn open(&self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { + fn open(&self, path: &str, flags: usize, uid: u32, _gid: u32) -> Result { if uid != 0 { return Err(Error::new(EACCES)) } - let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?; - let path_str = path_str.trim_start_matches('/'); + let path_str = path.trim_start_matches('/'); let handle: Handle = if path_str.is_empty() { if flags & O_DIRECTORY == 0 && flags & O_STAT == 0 { return Err(Error::new(EISDIR)) } diff --git a/src/scheme/itimer.rs b/src/scheme/itimer.rs index 92ca1ab..11bc559 100644 --- a/src/scheme/itimer.rs +++ b/src/scheme/itimer.rs @@ -23,10 +23,8 @@ impl ITimerScheme { } impl Scheme for ITimerScheme { - fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { - let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?; - - let clock = path_str.parse::().or(Err(Error::new(ENOENT)))?; + fn open(&self, path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result { + let clock = path.parse::().or(Err(Error::new(ENOENT)))?; match clock { CLOCK_REALTIME => (), diff --git a/src/scheme/live.rs b/src/scheme/live.rs index c66c860..678845e 100644 --- a/src/scheme/live.rs +++ b/src/scheme/live.rs @@ -52,7 +52,7 @@ impl DiskScheme { } impl Scheme for DiskScheme { - fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { + fn open(&self, _path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result { let id = self.next_id.fetch_add(1, Ordering::SeqCst); self.handles.write().insert(id, Handle { path: b"0", diff --git a/src/scheme/memory.rs b/src/scheme/memory.rs index 9ee45c1..2991921 100644 --- a/src/scheme/memory.rs +++ b/src/scheme/memory.rs @@ -15,7 +15,7 @@ impl MemoryScheme { } } impl Scheme for MemoryScheme { - fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { + fn open(&self, _path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result { Ok(0) } diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index 6638e34..55d1cb9 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -6,10 +6,13 @@ //! The kernel validates paths and file descriptors before they are passed to schemes, //! also stripping the scheme identifier of paths if necessary. -use alloc::sync::Arc; -use alloc::boxed::Box; -use alloc::collections::BTreeMap; -use alloc::vec::Vec; +use alloc::{ + boxed::Box, + collections::BTreeMap, + string::ToString, + sync::Arc, + vec::Vec, +}; use core::sync::atomic::AtomicUsize; use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; @@ -92,11 +95,11 @@ int_like!(SchemeId, AtomicSchemeId, usize, AtomicUsize); int_like!(FileHandle, AtomicFileHandle, usize, AtomicUsize); pub struct SchemeIter<'a> { - inner: Option<::alloc::collections::btree_map::Iter<'a, Box<[u8]>, SchemeId>> + inner: Option<::alloc::collections::btree_map::Iter<'a, Box, SchemeId>> } impl<'a> Iterator for SchemeIter<'a> { - type Item = (&'a Box<[u8]>, &'a SchemeId); + type Item = (&'a Box, &'a SchemeId); fn next(&mut self) -> Option { self.inner.as_mut().and_then(|iter| iter.next()) @@ -106,7 +109,7 @@ impl<'a> Iterator for SchemeIter<'a> { /// Scheme list type pub struct SchemeList { map: BTreeMap>, - names: BTreeMap, SchemeId>>, + names: BTreeMap, SchemeId>>, next_ns: usize, next_id: usize } @@ -133,7 +136,7 @@ impl SchemeList { //TODO: Only memory: is in the null namespace right now. It should be removed when //anonymous mmap's are implemented - self.insert(ns, Box::new(*b"memory"), |_| Arc::new(MemoryScheme::new())).unwrap(); + self.insert(ns, "memory", |_| Arc::new(MemoryScheme::new())).unwrap(); } /// Initialize a new namespace @@ -142,12 +145,12 @@ impl SchemeList { self.next_ns += 1; self.names.insert(ns, BTreeMap::new()); - self.insert(ns, Box::new(*b""), |scheme_id| Arc::new(RootScheme::new(ns, scheme_id))).unwrap(); - self.insert(ns, Box::new(*b"event"), |_| Arc::new(EventScheme)).unwrap(); - self.insert(ns, Box::new(*b"itimer"), |_| Arc::new(ITimerScheme::new())).unwrap(); - self.insert(ns, Box::new(*b"memory"), |_| Arc::new(MemoryScheme::new())).unwrap(); - self.insert(ns, Box::new(*b"sys"), |_| Arc::new(SysScheme::new())).unwrap(); - self.insert(ns, Box::new(*b"time"), |scheme_id| Arc::new(TimeScheme::new(scheme_id))).unwrap(); + self.insert(ns, "", |scheme_id| Arc::new(RootScheme::new(ns, scheme_id))).unwrap(); + self.insert(ns, "event", |_| Arc::new(EventScheme)).unwrap(); + self.insert(ns, "itimer", |_| Arc::new(ITimerScheme::new())).unwrap(); + self.insert(ns, "memory", |_| Arc::new(MemoryScheme::new())).unwrap(); + self.insert(ns, "sys", |_| Arc::new(SysScheme::new())).unwrap(); + self.insert(ns, "time", |scheme_id| Arc::new(TimeScheme::new(scheme_id))).unwrap(); ns } @@ -159,23 +162,23 @@ impl SchemeList { // These schemes should only be available on the root #[cfg(feature = "acpi")] { - self.insert(ns, Box::new(*b"acpi"), |_| Arc::new(AcpiScheme::new())).unwrap(); + self.insert(ns, "acpi", |_| Arc::new(AcpiScheme::new())).unwrap(); } - self.insert(ns, Box::new(*b"debug"), |scheme_id| Arc::new(DebugScheme::new(scheme_id))).unwrap(); - self.insert(ns, Box::new(*b"initfs"), |_| Arc::new(InitFsScheme::new())).unwrap(); - self.insert(ns, Box::new(*b"irq"), |scheme_id| Arc::new(IrqScheme::new(scheme_id))).unwrap(); - self.insert(ns, Box::new(*b"proc"), |scheme_id| Arc::new(ProcScheme::new(scheme_id))).unwrap(); - self.insert(ns, Box::new(*b"serio"), |scheme_id| Arc::new(SerioScheme::new(scheme_id))).unwrap(); + self.insert(ns, "debug", |scheme_id| Arc::new(DebugScheme::new(scheme_id))).unwrap(); + self.insert(ns, "initfs", |_| Arc::new(InitFsScheme::new())).unwrap(); + self.insert(ns, "irq", |scheme_id| Arc::new(IrqScheme::new(scheme_id))).unwrap(); + self.insert(ns, "proc", |scheme_id| Arc::new(ProcScheme::new(scheme_id))).unwrap(); + self.insert(ns, "serio", |scheme_id| Arc::new(SerioScheme::new(scheme_id))).unwrap(); #[cfg(feature = "live")] { - self.insert(ns, Box::new(*b"disk/live"), |_| Arc::new(self::live::DiskScheme::new())).unwrap(); + self.insert(ns, "disk/live", |_| Arc::new(self::live::DiskScheme::new())).unwrap(); } // Pipe is special and needs to be in the root namespace - self.insert(ns, Box::new(*b"pipe"), |scheme_id| Arc::new(PipeScheme::new(scheme_id))).unwrap(); + self.insert(ns, "pipe", |scheme_id| Arc::new(PipeScheme::new(scheme_id))).unwrap(); } - pub fn make_ns(&mut self, from: SchemeNamespace, names: &[&[u8]]) -> Result { + pub fn make_ns(&mut self, from: SchemeNamespace, names: &[&str]) -> Result { // Create an empty namespace let to = self.new_ns(); @@ -188,7 +191,7 @@ impl SchemeList { }; if let Some(ref mut names) = self.names.get_mut(&to) { - assert!(names.insert(name.to_vec().into_boxed_slice(), id).is_none()); + assert!(names.insert(name.to_string().into_boxed_str(), id).is_none()); } else { panic!("scheme namespace not found"); } @@ -212,7 +215,7 @@ impl SchemeList { self.map.get(&id) } - pub fn get_name(&self, ns: SchemeNamespace, name: &[u8]) -> Option<(SchemeId, &Arc)> { + pub fn get_name(&self, ns: SchemeNamespace, name: &str) -> Option<(SchemeId, &Arc)> { if let Some(names) = self.names.get(&ns) { if let Some(&id) = names.get(name) { return self.get(id).map(|scheme| (id, scheme)); @@ -222,11 +225,11 @@ impl SchemeList { } /// Create a new scheme. - pub fn insert(&mut self, ns: SchemeNamespace, name: Box<[u8]>, scheme_fn: F) -> Result + pub fn insert(&mut self, ns: SchemeNamespace, name: &str, scheme_fn: F) -> Result where F: Fn(SchemeId) -> Arc { if let Some(names) = self.names.get(&ns) { - if names.contains_key(&name) { + if names.contains_key(name) { return Err(Error::new(EEXIST)); } } @@ -252,7 +255,7 @@ impl SchemeList { assert!(self.map.insert(id, scheme).is_none()); if let Some(ref mut names) = self.names.get_mut(&ns) { - assert!(names.insert(name, id).is_none()); + assert!(names.insert(name.to_string().into_boxed_str(), id).is_none()); } else { // Nonexistent namespace, posssibly null namespace return Err(Error::new(ENODEV)); diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index 60a7395..a842641 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -24,6 +24,7 @@ use core::{ cmp, mem, slice, + str, sync::atomic::{AtomicUsize, Ordering}, }; use spin::RwLock; @@ -208,8 +209,7 @@ impl ProcScheme { } impl Scheme for ProcScheme { - fn open(&self, path: &[u8], flags: usize, uid: u32, gid: u32) -> Result { - let path = core::str::from_utf8(path).map_err(|_| Error::new(EINVAL))?; + fn open(&self, path: &str, flags: usize, uid: u32, gid: u32) -> Result { let mut parts = path.splitn(2, '/'); let pid = parts.next() .and_then(|s| s.parse().ok()) @@ -310,8 +310,10 @@ impl Scheme for ProcScheme { handle.info }; - let mut path = format!("{}/", info.pid.into()).into_bytes(); - path.extend_from_slice(buf); + let buf_str = str::from_utf8(buf).map_err(|_| Error::new(EINVAL))?; + + let mut path = format!("{}/", info.pid.into()); + path.push_str(buf_str); let (uid, gid) = { let contexts = context::contexts(); diff --git a/src/scheme/root.rs b/src/scheme/root.rs index ca5e789..248c4b5 100644 --- a/src/scheme/root.rs +++ b/src/scheme/root.rs @@ -1,7 +1,10 @@ -use alloc::sync::Arc; -use alloc::boxed::Box; -use alloc::collections::BTreeMap; -use alloc::vec::Vec; +use alloc::{ + boxed::Box, + collections::BTreeMap, + string::ToString, + sync::Arc, + vec::Vec, +}; use core::str; use core::sync::atomic::{AtomicUsize, Ordering}; use spin::{Mutex, RwLock}; @@ -67,9 +70,8 @@ impl RootScheme { } impl Scheme for RootScheme { - fn open(&self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - let path_utf8 = str::from_utf8(path).or(Err(Error::new(ENOENT)))?; - let path_trimmed = path_utf8.trim_matches('/'); + fn open(&self, path: &str, flags: usize, uid: u32, _gid: u32) -> Result { + let path = path.trim_matches('/'); //TODO: Make this follow standards for flags and errors if flags & O_CREAT == O_CREAT { @@ -83,10 +85,10 @@ impl Scheme for RootScheme { let id = self.next_id.fetch_add(1, Ordering::SeqCst); let inner = { - let path_box = path_trimmed.as_bytes().to_vec().into_boxed_slice(); + let path_box = path.to_string().into_boxed_str(); let mut schemes = scheme::schemes_mut(); - let inner = Arc::new(UserInner::new(self.scheme_id, id, path_box.clone(), flags, context)); - schemes.insert(self.scheme_ns, path_box, |scheme_id| { + let inner = Arc::new(UserInner::new(self.scheme_id, id, path_box, flags, context)); + schemes.insert(self.scheme_ns, path, |scheme_id| { inner.scheme_id.store(scheme_id, Ordering::SeqCst); Arc::new(UserScheme::new(Arc::downgrade(&inner))) })?; @@ -99,7 +101,7 @@ impl Scheme for RootScheme { } else { Err(Error::new(EACCES)) } - } else if path_trimmed.is_empty() { + } else if path.is_empty() { let scheme_ns = { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -111,7 +113,7 @@ impl Scheme for RootScheme { { let schemes = scheme::schemes(); for (name, _scheme_id) in schemes.iter_name(scheme_ns) { - data.extend_from_slice(name); + data.extend_from_slice(name.as_bytes()); data.push(b'\n'); } } @@ -126,7 +128,7 @@ impl Scheme for RootScheme { Ok(id) } else { let inner = Arc::new( - path_trimmed.as_bytes().to_vec().into_boxed_slice() + path.as_bytes().to_vec().into_boxed_slice() ); let id = self.next_id.fetch_add(1, Ordering::SeqCst); @@ -135,9 +137,8 @@ impl Scheme for RootScheme { } } - fn unlink(&self, path: &[u8], uid: u32, _gid: u32) -> Result { - let path_utf8 = str::from_utf8(path).or(Err(Error::new(ENOENT)))?; - let path_trimmed = path_utf8.trim_matches('/'); + fn unlink(&self, path: &str, uid: u32, _gid: u32) -> Result { + let path = path.trim_matches('/'); if uid == 0 { let inner = { @@ -145,7 +146,7 @@ impl Scheme for RootScheme { handles.iter().find_map(|(_id, handle)| { match handle { Handle::Scheme(inner) => { - if path_trimmed.as_bytes() == inner.name.as_ref() { + if path == inner.name.as_ref() { return Some(inner.clone()); } }, @@ -257,9 +258,10 @@ impl Scheme for RootScheme { match handle { Handle::Scheme(inner) => { + let name = inner.name.as_bytes(); let mut j = 0; - while i < buf.len() && j < inner.name.len() { - buf[i] = inner.name[j]; + while i < buf.len() && j < name.len() { + buf[i] = name[j]; i += 1; j += 1; } diff --git a/src/scheme/serio.rs b/src/scheme/serio.rs index f5b79ed..0a74742 100644 --- a/src/scheme/serio.rs +++ b/src/scheme/serio.rs @@ -60,13 +60,12 @@ impl SerioScheme { } impl Scheme for SerioScheme { - fn open(&self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { + fn open(&self, path: &str, flags: usize, uid: u32, _gid: u32) -> Result { if uid != 0 { return Err(Error::new(EPERM)); } - let index = str::from_utf8(path) - .or(Err(Error::new(ENOENT)))? + let index = path .parse::() .or(Err(Error::new(ENOENT)))?; if index >= INPUT.len() { diff --git a/src/scheme/sys/mod.rs b/src/scheme/sys/mod.rs index ef7947b..da6576c 100644 --- a/src/scheme/sys/mod.rs +++ b/src/scheme/sys/mod.rs @@ -23,7 +23,7 @@ mod syscall; mod uname; struct Handle { - path: &'static [u8], + path: &'static str, data: Vec, mode: u16, seek: usize @@ -34,26 +34,26 @@ type SysFn = dyn Fn() -> Result> + Send + Sync; /// System information scheme pub struct SysScheme { next_id: AtomicUsize, - files: BTreeMap<&'static [u8], Box>, + files: BTreeMap<&'static str, Box>, handles: RwLock> } impl SysScheme { pub fn new() -> SysScheme { - let mut files: BTreeMap<&'static [u8], Box> = BTreeMap::new(); + let mut files: BTreeMap<&'static str, Box> = BTreeMap::new(); - files.insert(b"block", Box::new(block::resource)); - files.insert(b"context", Box::new(context::resource)); - files.insert(b"cpu", Box::new(cpu::resource)); - files.insert(b"exe", Box::new(exe::resource)); - files.insert(b"iostat", Box::new(iostat::resource)); - files.insert(b"log", Box::new(log::resource)); - files.insert(b"scheme", Box::new(scheme::resource)); - files.insert(b"scheme_num", Box::new(scheme_num::resource)); - files.insert(b"syscall", Box::new(syscall::resource)); - files.insert(b"uname", Box::new(uname::resource)); + files.insert("block", Box::new(block::resource)); + files.insert("context", Box::new(context::resource)); + files.insert("cpu", Box::new(cpu::resource)); + files.insert("exe", Box::new(exe::resource)); + files.insert("iostat", Box::new(iostat::resource)); + files.insert("log", Box::new(log::resource)); + files.insert("scheme", Box::new(scheme::resource)); + files.insert("scheme_num", Box::new(scheme_num::resource)); + files.insert("syscall", Box::new(syscall::resource)); + files.insert("uname", Box::new(uname::resource)); #[cfg(target_arch = "x86_64")] - files.insert(b"spurious_irq", Box::new(irq::spurious_irq_resource)); + files.insert("spurious_irq", Box::new(irq::spurious_irq_resource)); SysScheme { next_id: AtomicUsize::new(0), @@ -64,22 +64,21 @@ impl SysScheme { } impl Scheme for SysScheme { - fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { - let path_utf8 = str::from_utf8(path).or(Err(Error::new(ENOENT)))?; - let path_trimmed = path_utf8.trim_matches('/'); + fn open(&self, path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result { + let path = path.trim_matches('/'); - if path_trimmed.is_empty() { + if path.is_empty() { let mut data = Vec::new(); for entry in self.files.iter() { if ! data.is_empty() { data.push(b'\n'); } - data.extend_from_slice(entry.0); + data.extend_from_slice(entry.0.as_bytes()); } let id = self.next_id.fetch_add(1, Ordering::SeqCst); self.handles.write().insert(id, Handle { - path: b"", + path: "", data, mode: MODE_DIR | 0o444, seek: 0 @@ -88,7 +87,7 @@ impl Scheme for SysScheme { } else { //Have to iterate to get the path without allocation for entry in self.files.iter() { - if entry.0 == &path_trimmed.as_bytes() { + if entry.0 == &path { let id = self.next_id.fetch_add(1, Ordering::SeqCst); let data = entry.1()?; self.handles.write().insert(id, Handle { @@ -139,9 +138,10 @@ impl Scheme for SysScheme { i += 1; } + let path = handle.path.as_bytes(); let mut j = 0; - while i < buf.len() && j < handle.path.len() { - buf[i] = handle.path[j]; + while i < buf.len() && j < path.len() { + buf[i] = path[j]; i += 1; j += 1; } diff --git a/src/scheme/sys/scheme.rs b/src/scheme/sys/scheme.rs index f97c6e3..e0a367a 100644 --- a/src/scheme/sys/scheme.rs +++ b/src/scheme/sys/scheme.rs @@ -16,7 +16,7 @@ pub fn resource() -> Result> { let schemes = scheme::schemes(); for (name, _scheme_id) in schemes.iter_name(scheme_ns) { - data.extend_from_slice(name); + data.extend_from_slice(name.as_bytes()); data.push(b'\n'); } diff --git a/src/scheme/sys/scheme_num.rs b/src/scheme/sys/scheme_num.rs index fbd85ac..37e5649 100644 --- a/src/scheme/sys/scheme_num.rs +++ b/src/scheme/sys/scheme_num.rs @@ -17,7 +17,7 @@ pub fn resource() -> Result> { let schemes = scheme::schemes(); for (name, &scheme_id) in schemes.iter_name(scheme_ns) { data.extend_from_slice(format!("{:>4}: ", scheme_id.into()).as_bytes()); - data.extend_from_slice(name); + data.extend_from_slice(name.as_bytes()); data.push(b'\n'); } diff --git a/src/scheme/time.rs b/src/scheme/time.rs index 2ff548d..bc0143b 100644 --- a/src/scheme/time.rs +++ b/src/scheme/time.rs @@ -28,10 +28,8 @@ impl TimeScheme { } impl Scheme for TimeScheme { - fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { - let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?; - - let clock = path_str.parse::().or(Err(Error::new(ENOENT)))?; + fn open(&self, path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result { + let clock = path.parse::().or(Err(Error::new(ENOENT)))?; match clock { CLOCK_REALTIME => (), diff --git a/src/scheme/user.rs b/src/scheme/user.rs index a0e3046..4dab187 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -23,7 +23,7 @@ use crate::syscall::scheme::Scheme; pub struct UserInner { root_id: SchemeId, handle_id: usize, - pub name: Box<[u8]>, + pub name: Box, pub flags: usize, pub scheme_id: AtomicSchemeId, next_id: AtomicU64, @@ -36,7 +36,7 @@ pub struct UserInner { } impl UserInner { - pub fn new(root_id: SchemeId, handle_id: usize, name: Box<[u8]>, flags: usize, context: Weak>) -> UserInner { + pub fn new(root_id: SchemeId, handle_id: usize, name: Box, flags: usize, context: Weak>) -> UserInner { UserInner { root_id, handle_id, @@ -103,13 +103,27 @@ impl UserInner { /// Map a readable structure to the scheme's userspace and return the /// pointer pub fn capture(&self, buf: &[u8]) -> Result { - UserInner::capture_inner(&self.context, 0, buf.as_ptr() as usize, buf.len(), PROT_READ, None).map(|addr| addr.data()) + UserInner::capture_inner( + &self.context, + 0, + buf.as_ptr() as usize, + buf.len(), + PROT_READ, + None + ).map(|addr| addr.data()) } /// Map a writeable structure to the scheme's userspace and return the /// pointer pub fn capture_mut(&self, buf: &mut [u8]) -> Result { - UserInner::capture_inner(&self.context, 0, buf.as_mut_ptr() as usize, buf.len(), PROT_WRITE, None).map(|addr| addr.data()) + UserInner::capture_inner( + &self.context, + 0, + buf.as_mut_ptr() as usize, + buf.len(), + PROT_WRITE, + None + ).map(|addr| addr.data()) } fn capture_inner(context_weak: &Weak>, to_address: usize, address: usize, size: usize, flags: MapFlags, desc_opt: Option) @@ -257,33 +271,33 @@ impl UserScheme { } impl Scheme for UserScheme { - fn open(&self, path: &[u8], flags: usize, _uid: u32, _gid: u32) -> Result { + fn open(&self, path: &str, flags: usize, _uid: u32, _gid: u32) -> Result { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.capture(path)?; + let address = inner.capture(path.as_bytes())?; let result = inner.call(SYS_OPEN, address, path.len(), flags); let _ = inner.release(address); result } - fn chmod(&self, path: &[u8], mode: u16, _uid: u32, _gid: u32) -> Result { + fn chmod(&self, path: &str, mode: u16, _uid: u32, _gid: u32) -> Result { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.capture(path)?; + let address = inner.capture(path.as_bytes())?; let result = inner.call(SYS_CHMOD, address, path.len(), mode as usize); let _ = inner.release(address); result } - fn rmdir(&self, path: &[u8], _uid: u32, _gid: u32) -> Result { + fn rmdir(&self, path: &str, _uid: u32, _gid: u32) -> Result { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.capture(path)?; + let address = inner.capture(path.as_bytes())?; let result = inner.call(SYS_RMDIR, address, path.len(), 0); let _ = inner.release(address); result } - fn unlink(&self, path: &[u8], _uid: u32, _gid: u32) -> Result { + fn unlink(&self, path: &str, _uid: u32, _gid: u32) -> Result { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.capture(path)?; + let address = inner.capture(path.as_bytes())?; let result = inner.call(SYS_UNLINK, address, path.len(), 0); let _ = inner.release(address); result @@ -513,9 +527,9 @@ impl Scheme for UserScheme { result } - fn frename(&self, file: usize, path: &[u8], _uid: u32, _gid: u32) -> Result { + fn frename(&self, file: usize, path: &str, _uid: u32, _gid: u32) -> Result { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.capture(path)?; + let address = inner.capture(path.as_bytes())?; let result = inner.call(SYS_FRENAME, file, address, path.len()); let _ = inner.release(address); result diff --git a/src/syscall/fs.rs b/src/syscall/fs.rs index bd4684a..a271e5d 100644 --- a/src/syscall/fs.rs +++ b/src/syscall/fs.rs @@ -1,6 +1,7 @@ //! Filesystem syscalls use alloc::sync::Arc; use alloc::vec::Vec; +use core::str; use core::sync::atomic::Ordering; use spin::RwLock; @@ -55,7 +56,7 @@ pub fn file_op_mut_slice(a: usize, fd: FileHandle, slice: &mut [u8]) -> Result Result { +pub fn chdir(path: &str) -> Result { let fd = open(path, O_RDONLY | O_DIRECTORY)?; let mut stat = Stat::default(); let stat_res = file_op_mut_slice(syscall::number::SYS_FSTAT, fd, &mut stat); @@ -79,16 +80,17 @@ pub fn getcwd(buf: &mut [u8]) -> Result { let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context = context_lock.read(); let cwd = context.cwd.read(); + let cwd_bytes = cwd.as_bytes(); let mut i = 0; - while i < buf.len() && i < cwd.len() { - buf[i] = cwd[i]; + while i < buf.len() && i < cwd_bytes.len() { + buf[i] = cwd_bytes[i]; i += 1; } Ok(i) } /// Open syscall -pub fn open(path: &[u8], flags: usize) -> Result { +pub fn open(path: &str, flags: usize) -> Result { let (mut path_canon, uid, gid, scheme_ns, umask) = { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -103,7 +105,7 @@ pub fn open(path: &[u8], flags: usize) -> Result { for _level in 0..32 { // XXX What should the limit be? //println!(" level {} = {:?}", _level, ::core::str::from_utf8(&path_canon)); - let mut parts = path_canon.splitn(2, |&b| b == b':'); + let mut parts = path_canon.splitn(2, ':'); let scheme_name_opt = parts.next(); let reference_opt = parts.next(); @@ -114,7 +116,7 @@ pub fn open(path: &[u8], flags: usize) -> Result { let (scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; (scheme_id, Arc::clone(&scheme)) }; - let reference = reference_opt.unwrap_or(b""); + let reference = reference_opt.unwrap_or(""); let file_id = match scheme.open(reference, flags, uid, gid) { Ok(ok) => ok, Err(err) => if err.errno == EXDEV { @@ -128,10 +130,12 @@ pub fn open(path: &[u8], flags: usize) -> Result { let count = res?; + let buf_str = str::from_utf8(&buf[..count]).map_err(|_| Error::new(EINVAL))?; + let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context = context_lock.read(); - path_canon = context.canonicalize(&buf[..count]); + path_canon = context.canonicalize(buf_str); continue; } else { @@ -196,7 +200,7 @@ pub fn pipe2(fds: &mut [usize], flags: usize) -> Result { } /// chmod syscall -pub fn chmod(path: &[u8], mode: u16) -> Result { +pub fn chmod(path: &str, mode: u16) -> Result { let (path_canon, uid, gid, scheme_ns) = { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -204,7 +208,7 @@ pub fn chmod(path: &[u8], mode: u16) -> Result { (context.canonicalize(path), context.euid, context.egid, context.ens) }; - let mut parts = path_canon.splitn(2, |&b| b == b':'); + let mut parts = path_canon.splitn(2, ':'); let scheme_name_opt = parts.next(); let reference_opt = parts.next(); @@ -214,11 +218,11 @@ pub fn chmod(path: &[u8], mode: u16) -> Result { let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; Arc::clone(&scheme) }; - scheme.chmod(reference_opt.unwrap_or(b""), mode, uid, gid) + scheme.chmod(reference_opt.unwrap_or(""), mode, uid, gid) } /// rmdir syscall -pub fn rmdir(path: &[u8]) -> Result { +pub fn rmdir(path: &str) -> Result { let (path_canon, uid, gid, scheme_ns) = { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -226,7 +230,7 @@ pub fn rmdir(path: &[u8]) -> Result { (context.canonicalize(path), context.euid, context.egid, context.ens) }; - let mut parts = path_canon.splitn(2, |&b| b == b':'); + let mut parts = path_canon.splitn(2, ':'); let scheme_name_opt = parts.next(); let reference_opt = parts.next(); @@ -236,11 +240,11 @@ pub fn rmdir(path: &[u8]) -> Result { let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; Arc::clone(&scheme) }; - scheme.rmdir(reference_opt.unwrap_or(b""), uid, gid) + scheme.rmdir(reference_opt.unwrap_or(""), uid, gid) } /// Unlink syscall -pub fn unlink(path: &[u8]) -> Result { +pub fn unlink(path: &str) -> Result { let (path_canon, uid, gid, scheme_ns) = { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -248,7 +252,7 @@ pub fn unlink(path: &[u8]) -> Result { (context.canonicalize(path), context.euid, context.egid, context.ens) }; - let mut parts = path_canon.splitn(2, |&b| b == b':'); + let mut parts = path_canon.splitn(2, ':'); let scheme_name_opt = parts.next(); let reference_opt = parts.next(); @@ -258,7 +262,7 @@ pub fn unlink(path: &[u8]) -> Result { let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; Arc::clone(&scheme) }; - scheme.unlink(reference_opt.unwrap_or(b""), uid, gid) + scheme.unlink(reference_opt.unwrap_or(""), uid, gid) } /// Close syscall @@ -409,7 +413,7 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result { } } -pub fn frename(fd: FileHandle, path: &[u8]) -> Result { +pub fn frename(fd: FileHandle, path: &str) -> Result { let file = { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -424,7 +428,7 @@ pub fn frename(fd: FileHandle, path: &[u8]) -> Result { (context.canonicalize(path), context.euid, context.egid, context.ens) }; - let mut parts = path_canon.splitn(2, |&b| b == b':'); + let mut parts = path_canon.splitn(2, ':'); let scheme_name_opt = parts.next(); let reference_opt = parts.next(); @@ -438,7 +442,7 @@ pub fn frename(fd: FileHandle, path: &[u8]) -> Result { let description = file.description.read(); if scheme_id == description.scheme { - scheme.frename(description.number, reference_opt.unwrap_or(b""), uid, gid) + scheme.frename(description.number, reference_opt.unwrap_or(""), uid, gid) } else { Err(Error::new(EXDEV)) } diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index 9f8139b..2287e25 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -75,7 +75,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u SYS_DUP2 => dup2(fd, FileHandle::from(c), validate_slice(d as *const u8, e)?).map(FileHandle::into), SYS_FCNTL => fcntl(fd, c, d), SYS_FEXEC => fexec(fd, validate_slice(c as *const [usize; 2], d)?, validate_slice(e as *const [usize; 2], f)?), - SYS_FRENAME => frename(fd, validate_slice(c as *const u8, d)?), + SYS_FRENAME => frename(fd, validate_str(c as *const u8, d)?), SYS_FUNMAP => funmap(b, c), SYS_FMAP_OLD => { { @@ -100,10 +100,10 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u } }, SYS_CLASS_PATH => match a { - SYS_OPEN => open(validate_slice(b as *const u8, c)?, d).map(FileHandle::into), - SYS_CHMOD => chmod(validate_slice(b as *const u8, c)?, d as u16), - SYS_RMDIR => rmdir(validate_slice(b as *const u8, c)?), - SYS_UNLINK => unlink(validate_slice(b as *const u8, c)?), + SYS_OPEN => open(validate_str(b as *const u8, c)?, d).map(FileHandle::into), + SYS_CHMOD => chmod(validate_str(b as *const u8, c)?, d as u16), + SYS_RMDIR => rmdir(validate_str(b as *const u8, c)?), + SYS_UNLINK => unlink(validate_str(b as *const u8, c)?), _ => Err(Error::new(ENOSYS)) }, _ => match a { @@ -145,7 +145,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u SYS_EXIT => exit((b & 0xFF) << 8), SYS_KILL => kill(ContextId::from(b), c), SYS_WAITPID => waitpid(ContextId::from(b), c, WaitFlags::from_bits_truncate(d)).map(ContextId::into), - SYS_CHDIR => chdir(validate_slice(b as *const u8, c)?), + SYS_CHDIR => chdir(validate_str(b as *const u8, c)?), SYS_IOPL => iopl(b, stack), SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?), SYS_GETEGID => getegid(), diff --git a/src/syscall/privilege.rs b/src/syscall/privilege.rs index 2ad14d5..bd07278 100644 --- a/src/syscall/privilege.rs +++ b/src/syscall/privilege.rs @@ -3,7 +3,7 @@ use alloc::vec::Vec; use crate::context; use crate::scheme::{self, SchemeNamespace}; use crate::syscall::error::*; -use crate::syscall::validate::validate_slice; +use crate::syscall::validate::validate_str; pub fn getegid() -> Result { let contexts = context::contexts(); @@ -50,7 +50,7 @@ pub fn getuid() -> Result { pub fn mkns(name_ptrs: &[[usize; 2]]) -> Result { let mut names = Vec::new(); for name_ptr in name_ptrs { - names.push(validate_slice(name_ptr[0] as *const u8, name_ptr[1])?); + names.push(validate_str(name_ptr[0] as *const u8, name_ptr[1])?); } let (uid, from) = { diff --git a/src/syscall/process.rs b/src/syscall/process.rs index d91d049..3710001 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -7,7 +7,7 @@ use alloc::{ }; use core::alloc::{GlobalAlloc, Layout}; use core::ops::DerefMut; -use core::{intrinsics, mem}; +use core::{intrinsics, mem, str}; use spin::RwLock; use crate::context::file::FileDescriptor; @@ -1030,9 +1030,11 @@ pub fn fexec_kernel(fd: FileHandle, args: Box<[Box<[u8]>]>, vars: Box<[Box<[u8]> } interp.truncate(i); - println!(" interpreter: {:?}", ::core::str::from_utf8(&interp)); + let interp_str = str::from_utf8(&interp).map_err(|_| Error::new(EINVAL))?; - let interp_fd = super::fs::open(&interp, super::flag::O_RDONLY | super::flag::O_CLOEXEC)?; + println!(" interpreter: {}", interp_str); + + let interp_fd = super::fs::open(interp_str, super::flag::O_RDONLY | super::flag::O_CLOEXEC)?; let mut args_vec = Vec::from(args); //TODO: pass file handle in auxv diff --git a/src/syscall/validate.rs b/src/syscall/validate.rs index 5806a53..346dcd0 100644 --- a/src/syscall/validate.rs +++ b/src/syscall/validate.rs @@ -1,4 +1,4 @@ -use core::{mem, slice}; +use core::{mem, slice, str}; use crate::paging::{ActivePageTable, PageTableType, Page, VirtualAddress, VirtualAddressType}; use crate::paging::entry::EntryFlags; @@ -51,3 +51,10 @@ pub fn validate_slice_mut(ptr: *mut T, len: usize) -> Result<&'static mut [T] Ok(unsafe { slice::from_raw_parts_mut(ptr, len) }) } } + +/// Convert a pointer and length to str, if valid +//TODO: Mark unsafe +pub fn validate_str(ptr: *const u8, len: usize) -> Result<&'static str> { + let slice = validate_slice(ptr, len)?; + str::from_utf8(slice).map_err(|_| Error::new(EINVAL)) +} diff --git a/syscall b/syscall index bfdd0bb..87e913d 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit bfdd0bb8d64c078192e44e83719a8aa4b3bf85a1 +Subproject commit 87e913d991810374688f3284154d9216ffa8f73e