From 431407aff0fa5546fc030f3a07a7fffebb81b59c Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 12 Aug 2022 13:04:35 +0200 Subject: [PATCH] Remove SYS_CHMOD and cwd related syscalls/files. --- src/context/context.rs | 71 ---------------- src/scheme/proc.rs | 10 --- src/syscall/debug.rs | 14 ---- src/syscall/fs.rs | 184 +++++++++-------------------------------- src/syscall/mod.rs | 3 - syscall | 2 +- 6 files changed, 41 insertions(+), 243 deletions(-) diff --git a/src/context/context.rs b/src/context/context.rs index 182c6b1..507c9d5 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -122,7 +122,6 @@ pub struct ContextSnapshot { //TODO: is there a faster way than allocation? pub name: Box, pub files: Vec>, - // pub cwd: Box<[u8]>, } impl ContextSnapshot { @@ -234,8 +233,6 @@ pub struct Context { pub addr_space: Option>>, /// The name of the context pub name: Arc>>, - /// The current working directory - pub cwd: Arc>, /// The open files in the scheme pub files: Arc>>>, /// Signal actions @@ -366,7 +363,6 @@ impl Context { ksig_restore: false, addr_space: None, name: Arc::new(RwLock::new(String::new().into_boxed_str())), - cwd: Arc::new(RwLock::new(String::new())), files: Arc::new(RwLock::new(Vec::new())), actions: Self::empty_actions(), regs: None, @@ -377,73 +373,6 @@ impl Context { Ok(this) } - /// Make a relative path absolute - /// Given a cwd of "scheme:/path" - /// 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: &str) -> String { - let mut canon = if path.find(':').is_none() { - let cwd = self.cwd.read(); - - let mut canon = if !path.starts_with('/') { - let mut c = cwd.clone(); - if ! c.ends_with('/') { - c.push('/'); - } - c - } else { - cwd[..cwd.find(':').map_or(1, |i| i + 1)].to_string() - }; - - canon.push_str(&path); - canon - } else { - path.to_string() - }; - - // NOTE: assumes the scheme does not include anything like "../" or "./" - let mut result = { - let parts = canon.split('/') - .rev() - .scan(0, |nskip, part| { - if part == "." { - Some(None) - } else if part == ".." { - *nskip += 1; - Some(None) - } else if *nskip > 0 { - *nskip -= 1; - Some(None) - } else { - Some(Some(part)) - } - }) - .filter_map(|x| x) - .filter(|x| !x.is_empty()) - .collect::>(); - parts - .iter() - .rev() - .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.find(':') - .map_or(canon.len(), |p| p + 1); - canon.truncate(pos); - canon - } else { - result - } - } - /// Block the context, and return true if it was runnable before being blocked pub fn block(&mut self, reason: &'static str) -> bool { if self.status == Status::Runnable { diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index 4c13ed5..ec6b7b1 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -113,7 +113,6 @@ enum Operation { Trace, Static(&'static str), Name, - Cwd, Sigstack, Attr(Attr), Filetable { filetable: Arc>>> }, @@ -301,7 +300,6 @@ impl ProcScheme { Some("trace") => Operation::Trace, Some("exe") => Operation::Static("exe"), Some("name") => Operation::Name, - Some("cwd") => Operation::Cwd, Some("sigstack") => Operation::Sigstack, Some("uid") => Operation::Attr(Attr::Uid), Some("gid") => Operation::Attr(Attr::Gid), @@ -682,7 +680,6 @@ impl Scheme for ProcScheme { Ok(read * mem::size_of::()) } Operation::Name => read_from(buf, context::contexts().get(info.pid).ok_or(Error::new(ESRCH))?.read().name.read().as_bytes(), &mut 0), - Operation::Cwd => read_from(buf, context::contexts().get(info.pid).ok_or(Error::new(ESRCH))?.read().cwd.read().as_bytes(), &mut 0), Operation::Sigstack => read_from(buf, &context::contexts().get(info.pid).ok_or(Error::new(ESRCH))?.read().sigstack.unwrap_or(!0).to_ne_bytes(), &mut 0), Operation::Attr(attr) => { let src_buf = match (attr, &*Arc::clone(context::contexts().get(info.pid).ok_or(Error::new(ESRCH))?).read()) { @@ -937,17 +934,11 @@ impl Scheme for ProcScheme { Ok(mem::size_of::()) }, - // TODO: Deduplicate name and cwd Operation::Name => { let utf8 = alloc::string::String::from_utf8(buf.to_vec()).map_err(|_| Error::new(EINVAL))?.into_boxed_str(); *context::contexts().get(info.pid).ok_or(Error::new(ESRCH))?.read().name.write() = utf8; Ok(buf.len()) } - Operation::Cwd => { - let utf8 = alloc::string::String::from_utf8(buf.to_vec()).map_err(|_| Error::new(EINVAL))?; - *context::contexts().get(info.pid).ok_or(Error::new(ESRCH))?.read().cwd.write() = utf8; - Ok(buf.len()) - } Operation::Sigstack => { let bytes = <[u8; mem::size_of::()]>::try_from(buf).map_err(|_| Error::new(EINVAL))?; let sigstack = usize::from_ne_bytes(bytes); @@ -1041,7 +1032,6 @@ impl Scheme for ProcScheme { Operation::Trace => "trace", Operation::Static(path) => path, Operation::Name => "name", - Operation::Cwd => "cwd", Operation::Sigstack => "sigstack", Operation::Attr(Attr::Uid) => "uid", Operation::Attr(Attr::Gid) => "gid", diff --git a/src/syscall/debug.rs b/src/syscall/debug.rs index 53e6ac5..7927a83 100644 --- a/src/syscall/debug.rs +++ b/src/syscall/debug.rs @@ -29,11 +29,6 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) - validate_slice(b as *const u8, c).map(ByteStr), d ), - SYS_CHMOD => format!( - "chmod({:?}, {:#o})", - validate_slice(b as *const u8, c).map(ByteStr), - d - ), SYS_RMDIR => format!( "rmdir({:?})", validate_slice(b as *const u8, c).map(ByteStr) @@ -161,10 +156,6 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) - ), ), - SYS_CHDIR => format!( - "chdir({:?})", - validate_slice(b as *const u8, c).map(ByteStr) - ), SYS_CLOCK_GETTIME => format!( "clock_gettime({}, {:?})", b, @@ -183,11 +174,6 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) - e, f ), - SYS_GETCWD => format!( - "getcwd({:#X}, {})", - b, - c - ), SYS_GETEGID => format!("getegid()"), SYS_GETENS => format!("getens()"), SYS_GETEUID => format!("geteuid()"), diff --git a/src/syscall/fs.rs b/src/syscall/fs.rs index 42ec136..20b0f6d 100644 --- a/src/syscall/fs.rs +++ b/src/syscall/fs.rs @@ -51,110 +51,41 @@ pub fn file_op_mut_slice(a: usize, fd: FileHandle, slice: &mut [u8]) -> Result 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); - let _ = close(fd); - stat_res?; - if stat.st_mode & (MODE_FILE | MODE_DIR) == MODE_DIR { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - let canonical = context.canonicalize(path); - *context.cwd.write() = canonical; - Ok(0) - } else { - Err(Error::new(ENOTDIR)) - } -} - -/// Get the current working directory -pub fn getcwd(buf: &mut [u8]) -> Result { - let contexts = context::contexts(); - 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_bytes.len() { - buf[i] = cwd_bytes[i]; - i += 1; - } - Ok(i) -} - /// Open syscall pub fn open(path: &str, flags: usize) -> Result { - let (mut path_canon, uid, gid, scheme_ns, umask) = { + let (uid, gid, scheme_ns, umask) = { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context = context_lock.read(); - (context.canonicalize(path), context.euid, context.egid, context.ens, context.umask) + (context.euid, context.egid, context.ens, context.umask) }; let flags = (flags & (!0o777)) | ((flags & 0o777) & (!(umask & 0o777))); - //println!("open {}", unsafe { ::core::str::from_utf8_unchecked(&path_canon) }); - for _level in 0..32 { // XXX What should the limit be? - //println!(" level {} = {:?}", _level, ::core::str::from_utf8(&path_canon)); + let mut parts = path.splitn(2, ':'); + let scheme_name = parts.next().ok_or(Error::new(EINVAL))?; + let reference = parts.next().unwrap_or(""); - let mut parts = path_canon.splitn(2, ':'); - let scheme_name_opt = parts.next(); - let reference_opt = parts.next(); - - let (scheme_id, file_id) = { - let scheme_name = scheme_name_opt.ok_or(Error::new(ENODEV))?; - let (scheme_id, scheme) = { - let schemes = scheme::schemes(); - 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(""); - let file_id = match scheme.open(reference, flags, uid, gid) { - Ok(ok) => ok, - Err(err) => if err.errno == EXDEV { - let resolve_flags = O_CLOEXEC | O_SYMLINK | O_RDONLY; - let resolve_id = scheme.open(reference, resolve_flags, uid, gid)?; - - let mut buf = [0; 4096]; - let res = scheme.read(resolve_id, &mut buf); - - let _ = scheme.close(resolve_id); - - 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_str); - - continue; - } else { - return Err(err); - } - }; - (scheme_id, file_id) + let (scheme_id, file_id) = { + let (scheme_id, scheme) = { + let schemes = scheme::schemes(); + let (scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; + (scheme_id, Arc::clone(&scheme)) }; - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - return context.add_file(FileDescriptor { - description: Arc::new(RwLock::new(FileDescription { - namespace: scheme_ns, - scheme: scheme_id, - number: file_id, - flags: flags & !O_CLOEXEC, - })), - cloexec: flags & O_CLOEXEC == O_CLOEXEC, - }).ok_or(Error::new(EMFILE)); - } - Err(Error::new(ELOOP)) + (scheme_id, scheme.open(reference, flags, uid, gid)?) + }; + + context::current()?.read().add_file(FileDescriptor { + description: Arc::new(RwLock::new(FileDescription { + namespace: scheme_ns, + scheme: scheme_id, + number: file_id, + flags: flags & !O_CLOEXEC, + })), + cloexec: flags & O_CLOEXEC == O_CLOEXEC, + }).ok_or(Error::new(EMFILE)) } pub fn pipe2(fds: &mut [usize], flags: usize) -> Result { @@ -195,70 +126,46 @@ pub fn pipe2(fds: &mut [usize], flags: usize) -> Result { Ok(0) } -/// chmod syscall -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))?; - let context = context_lock.read(); - (context.canonicalize(path), context.euid, context.egid, context.ens) - }; - - let mut parts = path_canon.splitn(2, ':'); - let scheme_name_opt = parts.next(); - let reference_opt = parts.next(); - - let scheme_name = scheme_name_opt.ok_or(Error::new(ENODEV))?; - let scheme = { - let schemes = scheme::schemes(); - 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(""), mode, uid, gid) -} - /// rmdir syscall pub fn rmdir(path: &str) -> Result { - let (path_canon, uid, gid, scheme_ns) = { + let (uid, gid, scheme_ns) = { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context = context_lock.read(); - (context.canonicalize(path), context.euid, context.egid, context.ens) + (context.euid, context.egid, context.ens) }; - let mut parts = path_canon.splitn(2, ':'); - let scheme_name_opt = parts.next(); - let reference_opt = parts.next(); + let mut parts = path.splitn(2, ':'); + let scheme_name = parts.next().ok_or(Error::new(EINVAL))?; + let reference = parts.next().unwrap_or(""); - let scheme_name = scheme_name_opt.ok_or(Error::new(ENODEV))?; let scheme = { let schemes = scheme::schemes(); 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(""), uid, gid) + scheme.rmdir(reference, uid, gid) } /// Unlink syscall pub fn unlink(path: &str) -> Result { - let (path_canon, uid, gid, scheme_ns) = { + let (uid, gid, scheme_ns) = { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context = context_lock.read(); - (context.canonicalize(path), context.euid, context.egid, context.ens) + (context.euid, context.egid, context.ens) }; - let mut parts = path_canon.splitn(2, ':'); - let scheme_name_opt = parts.next(); - let reference_opt = parts.next(); + let mut parts = path.splitn(2, ':'); + let scheme_name = parts.next().ok_or(Error::new(EINVAL))?; + let reference = parts.next().unwrap_or(""); - let scheme_name = scheme_name_opt.ok_or(Error::new(ENODEV))?; let scheme = { let schemes = scheme::schemes(); 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(""), uid, gid) + scheme.unlink(reference, uid, gid) } /// Close syscall @@ -410,25 +317,14 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> 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))?; - let context = context_lock.read(); - context.get_file(fd).ok_or(Error::new(EBADF))? + let (file, uid, gid, scheme_ns) = match context::current()?.read() { + ref context => (context.get_file(fd).ok_or(Error::new(EBADF))?, context.euid, context.egid, context.ens), }; - let (path_canon, uid, gid, scheme_ns) = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - (context.canonicalize(path), context.euid, context.egid, context.ens) - }; + let mut parts = path.splitn(2, ':'); + let scheme_name = parts.next().ok_or(Error::new(ENOENT))?; + let reference = parts.next().unwrap_or(""); - let mut parts = path_canon.splitn(2, ':'); - let scheme_name_opt = parts.next(); - let reference_opt = parts.next(); - - let scheme_name = scheme_name_opt.ok_or(Error::new(ENODEV))?; let (scheme_id, scheme) = { let schemes = scheme::schemes(); let (scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; @@ -438,7 +334,7 @@ pub fn frename(fd: FileHandle, path: &str) -> Result { let description = file.description.read(); if scheme_id == description.scheme { - scheme.frename(description.number, reference_opt.unwrap_or(""), uid, gid) + scheme.frename(description.number, reference, uid, gid) } else { Err(Error::new(EXDEV)) } diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index f6bf8a4..57dde0e 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -93,7 +93,6 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack }, SYS_CLASS_PATH => match a { 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)) @@ -117,9 +116,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack 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_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(), SYS_GETENS => getens(), SYS_GETEUID => geteuid(), diff --git a/syscall b/syscall index 90c9253..e7c9a81 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit 90c9253678c633133326a239557a755fea4a29eb +Subproject commit e7c9a81b15d9787d45b0be779400aa98e61c634d