Remove SYS_CHMOD and cwd related syscalls/files.

This commit is contained in:
4lDO2
2022-08-12 13:04:35 +02:00
parent ac70c76922
commit 431407aff0
6 changed files with 41 additions and 243 deletions

View File

@@ -122,7 +122,6 @@ pub struct ContextSnapshot {
//TODO: is there a faster way than allocation?
pub name: Box<str>,
pub files: Vec<Option<FileDescription>>,
// pub cwd: Box<[u8]>,
}
impl ContextSnapshot {
@@ -234,8 +233,6 @@ pub struct Context {
pub addr_space: Option<Arc<RwLock<AddrSpace>>>,
/// The name of the context
pub name: Arc<RwLock<Box<str>>>,
/// The current working directory
pub cwd: Arc<RwLock<String>>,
/// The open files in the scheme
pub files: Arc<RwLock<Vec<Option<FileDescriptor>>>>,
/// 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::<Vec<_>>();
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 {

View File

@@ -113,7 +113,6 @@ enum Operation {
Trace,
Static(&'static str),
Name,
Cwd,
Sigstack,
Attr(Attr),
Filetable { filetable: Arc<RwLock<Vec<Option<FileDescriptor>>>> },
@@ -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::<PtraceEvent>())
}
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::<u64>())
},
// 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::<usize>()]>::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",

View File

@@ -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()"),

View File

@@ -51,110 +51,41 @@ pub fn file_op_mut_slice(a: usize, fd: FileHandle, slice: &mut [u8]) -> Result<u
file_op(a, fd, slice.as_mut_ptr() as usize, slice.len())
}
/// Change the current working directory
pub fn chdir(path: &str) -> Result<usize> {
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<usize> {
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<FileHandle> {
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<usize> {
@@ -195,70 +126,46 @@ pub fn pipe2(fds: &mut [usize], flags: usize) -> Result<usize> {
Ok(0)
}
/// chmod syscall
pub fn chmod(path: &str, mode: u16) -> Result<usize> {
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<usize> {
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<usize> {
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<usize> {
}
pub fn frename(fd: FileHandle, path: &str) -> Result<usize> {
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<usize> {
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))
}

View File

@@ -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(),

Submodule syscall updated: 90c9253678...e7c9a81b15