Remove SYS_CHMOD and cwd related syscalls/files.
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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()"),
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
2
syscall
2
syscall
Submodule syscall updated: 90c9253678...e7c9a81b15
Reference in New Issue
Block a user