Add rustfmt from relibc and apply it with cargo fmt
This commit is contained in:
+41
-143
@@ -1,15 +1,17 @@
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use core::{ascii, mem};
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use super::data::{Map, Stat, TimeSpec};
|
||||
use super::{flag::*, copy_path_to_buf};
|
||||
use super::number::*;
|
||||
use super::usercopy::UserSlice;
|
||||
use super::{
|
||||
copy_path_to_buf,
|
||||
data::{Map, Stat, TimeSpec},
|
||||
flag::*,
|
||||
number::*,
|
||||
usercopy::UserSlice,
|
||||
};
|
||||
|
||||
use crate::syscall::error::Result;
|
||||
|
||||
struct ByteStr<'a>(&'a[u8]);
|
||||
struct ByteStr<'a>(&'a [u8]);
|
||||
|
||||
impl<'a> ::core::fmt::Debug for ByteStr<'a> {
|
||||
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
||||
@@ -29,7 +31,7 @@ fn debug_path(ptr: usize, len: usize) -> Result<String> {
|
||||
}
|
||||
fn debug_buf(ptr: usize, len: usize) -> Result<Vec<u8>> {
|
||||
UserSlice::ro(ptr, len).and_then(|user| {
|
||||
let mut buf = vec! [0_u8; 4096];
|
||||
let mut buf = vec![0_u8; 4096];
|
||||
let count = user.copy_common_bytes_to_slice(&mut buf)?;
|
||||
buf.truncate(count);
|
||||
Ok(buf)
|
||||
@@ -55,9 +57,7 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -
|
||||
"unlink({:?})",
|
||||
debug_path(b, c).as_ref().map(|p| ByteStr(p.as_bytes())),
|
||||
),
|
||||
SYS_CLOSE => format!(
|
||||
"close({})", b
|
||||
),
|
||||
SYS_CLOSE => format!("close({})", b),
|
||||
SYS_DUP => format!(
|
||||
"dup({}, {:?})",
|
||||
b,
|
||||
@@ -69,26 +69,9 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -
|
||||
c,
|
||||
debug_buf(d, e).as_ref().map(|b| ByteStr(&*b)),
|
||||
),
|
||||
SYS_SENDFD => format!(
|
||||
"sendfd({}, {}, {:#0x} {:#0x} {:#0x})",
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
e,
|
||||
f,
|
||||
),
|
||||
SYS_READ => format!(
|
||||
"read({}, {:#X}, {})",
|
||||
b,
|
||||
c,
|
||||
d
|
||||
),
|
||||
SYS_WRITE => format!(
|
||||
"write({}, {:#X}, {})",
|
||||
b,
|
||||
c,
|
||||
d
|
||||
),
|
||||
SYS_SENDFD => format!("sendfd({}, {}, {:#0x} {:#0x} {:#0x})", b, c, d, e, f,),
|
||||
SYS_READ => format!("read({}, {:#X}, {})", b, c, d),
|
||||
SYS_WRITE => format!("write({}, {:#X}, {})", b, c, d),
|
||||
SYS_LSEEK => format!(
|
||||
"lseek({}, {}, {} ({}))",
|
||||
b,
|
||||
@@ -97,21 +80,12 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -
|
||||
SEEK_SET => "SEEK_SET",
|
||||
SEEK_CUR => "SEEK_CUR",
|
||||
SEEK_END => "SEEK_END",
|
||||
_ => "UNKNOWN"
|
||||
_ => "UNKNOWN",
|
||||
},
|
||||
d
|
||||
),
|
||||
SYS_FCHMOD => format!(
|
||||
"fchmod({}, {:#o})",
|
||||
b,
|
||||
c
|
||||
),
|
||||
SYS_FCHOWN => format!(
|
||||
"fchown({}, {}, {})",
|
||||
b,
|
||||
c,
|
||||
d
|
||||
),
|
||||
SYS_FCHMOD => format!("fchmod({}, {:#o})", b, c),
|
||||
SYS_FCHOWN => format!("fchown({}, {}, {})", b, c, d),
|
||||
SYS_FCNTL => format!(
|
||||
"fcntl({}, {} ({}), {:#X})",
|
||||
b,
|
||||
@@ -121,7 +95,7 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -
|
||||
F_SETFD => "F_SETFD",
|
||||
F_SETFL => "F_SETFL",
|
||||
F_GETFL => "F_GETFL",
|
||||
_ => "UNKNOWN"
|
||||
_ => "UNKNOWN",
|
||||
},
|
||||
c,
|
||||
d
|
||||
@@ -131,47 +105,22 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -
|
||||
b,
|
||||
UserSlice::ro(c, d).and_then(|buf| unsafe { buf.read_exact::<Map>() }),
|
||||
),
|
||||
SYS_FUNMAP => format!(
|
||||
"funmap({:#X}, {:#X})",
|
||||
b,
|
||||
c,
|
||||
),
|
||||
SYS_FPATH => format!(
|
||||
"fpath({}, {:#X}, {})",
|
||||
b,
|
||||
c,
|
||||
d
|
||||
),
|
||||
SYS_FRENAME => format!(
|
||||
"frename({}, {:?})",
|
||||
b,
|
||||
debug_path(c, d),
|
||||
),
|
||||
SYS_FUNMAP => format!("funmap({:#X}, {:#X})", b, c,),
|
||||
SYS_FPATH => format!("fpath({}, {:#X}, {})", b, c, d),
|
||||
SYS_FRENAME => format!("frename({}, {:?})", b, debug_path(c, d),),
|
||||
SYS_FSTAT => format!(
|
||||
"fstat({}, {:?})",
|
||||
b,
|
||||
UserSlice::ro(c, d).and_then(|buf| unsafe { buf.read_exact::<Stat>() }),
|
||||
),
|
||||
SYS_FSTATVFS => format!(
|
||||
"fstatvfs({}, {:#X}, {})",
|
||||
b,
|
||||
c,
|
||||
d
|
||||
),
|
||||
SYS_FSYNC => format!(
|
||||
"fsync({})",
|
||||
b
|
||||
),
|
||||
SYS_FTRUNCATE => format!(
|
||||
"ftruncate({}, {})",
|
||||
b,
|
||||
c
|
||||
),
|
||||
SYS_FSTATVFS => format!("fstatvfs({}, {:#X}, {})", b, c, d),
|
||||
SYS_FSYNC => format!("fsync({})", b),
|
||||
SYS_FTRUNCATE => format!("ftruncate({}, {})", b, c),
|
||||
SYS_FUTIMENS => format!(
|
||||
"futimens({}, {:?})",
|
||||
b,
|
||||
UserSlice::ro(c, d).and_then(|buf| {
|
||||
let mut times = vec! [unsafe { buf.read_exact::<TimeSpec>()? }];
|
||||
let mut times = vec![unsafe { buf.read_exact::<TimeSpec>()? }];
|
||||
|
||||
// One or two timespecs
|
||||
if let Some(second) = buf.advance(mem::size_of::<TimeSpec>()) {
|
||||
@@ -181,15 +130,10 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -
|
||||
}),
|
||||
),
|
||||
|
||||
SYS_CLOCK_GETTIME => format!(
|
||||
"clock_gettime({}, {:?})",
|
||||
b,
|
||||
unsafe { read_struct::<TimeSpec>(c) }
|
||||
),
|
||||
SYS_EXIT => format!(
|
||||
"exit({})",
|
||||
b
|
||||
),
|
||||
SYS_CLOCK_GETTIME => format!("clock_gettime({}, {:?})", b, unsafe {
|
||||
read_struct::<TimeSpec>(c)
|
||||
}),
|
||||
SYS_EXIT => format!("exit({})", b),
|
||||
SYS_FUTEX => format!(
|
||||
"futex({:#X} [{:?}], {}, {}, {}, {})",
|
||||
b,
|
||||
@@ -208,23 +152,10 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -
|
||||
SYS_GETPID => format!("getpid()"),
|
||||
SYS_GETPPID => format!("getppid()"),
|
||||
SYS_GETUID => format!("getuid()"),
|
||||
SYS_IOPL => format!(
|
||||
"iopl({})",
|
||||
b
|
||||
),
|
||||
SYS_KILL => format!(
|
||||
"kill({}, {})",
|
||||
b,
|
||||
c
|
||||
),
|
||||
SYS_IOPL => format!("iopl({})", b),
|
||||
SYS_KILL => format!("kill({}, {})", b, c),
|
||||
SYS_SIGRETURN => format!("sigreturn()"),
|
||||
SYS_SIGACTION => format!(
|
||||
"sigaction({}, {:#X}, {:#X}, {:#X})",
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
e
|
||||
),
|
||||
SYS_SIGACTION => format!("sigaction({}, {:#X}, {:#X}, {:#X})", b, c, d, e),
|
||||
SYS_SIGPROCMASK => format!(
|
||||
"sigprocmask({}, {:?}, {:?})",
|
||||
b,
|
||||
@@ -240,56 +171,23 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -
|
||||
b as *const u8,
|
||||
c,
|
||||
),
|
||||
SYS_MPROTECT => format!(
|
||||
"mprotect({:#X}, {}, {:?})",
|
||||
b,
|
||||
c,
|
||||
MapFlags::from_bits(d)
|
||||
),
|
||||
SYS_MPROTECT => format!("mprotect({:#X}, {}, {:?})", b, c, MapFlags::from_bits(d)),
|
||||
SYS_NANOSLEEP => format!(
|
||||
"nanosleep({:?}, ({}, {}))",
|
||||
unsafe { read_struct::<TimeSpec>(b) },
|
||||
c,
|
||||
d
|
||||
),
|
||||
SYS_VIRTTOPHYS => format!(
|
||||
"virttophys({:#X})",
|
||||
b
|
||||
),
|
||||
SYS_SETREGID => format!(
|
||||
"setregid({}, {})",
|
||||
b,
|
||||
c
|
||||
),
|
||||
SYS_SETRENS => format!(
|
||||
"setrens({}, {})",
|
||||
b,
|
||||
c
|
||||
),
|
||||
SYS_SETREUID => format!(
|
||||
"setreuid({}, {})",
|
||||
b,
|
||||
c
|
||||
),
|
||||
SYS_UMASK => format!(
|
||||
"umask({:#o}",
|
||||
b
|
||||
),
|
||||
SYS_WAITPID => format!(
|
||||
"waitpid({}, {:#X}, {:?})",
|
||||
b,
|
||||
c,
|
||||
WaitFlags::from_bits(d)
|
||||
),
|
||||
SYS_VIRTTOPHYS => format!("virttophys({:#X})", b),
|
||||
SYS_SETREGID => format!("setregid({}, {})", b, c),
|
||||
SYS_SETRENS => format!("setrens({}, {})", b, c),
|
||||
SYS_SETREUID => format!("setreuid({}, {})", b, c),
|
||||
SYS_UMASK => format!("umask({:#o}", b),
|
||||
SYS_WAITPID => format!("waitpid({}, {:#X}, {:?})", b, c, WaitFlags::from_bits(d)),
|
||||
SYS_YIELD => format!("yield()"),
|
||||
_ => format!(
|
||||
"UNKNOWN{} {:#X}({:#X}, {:#X}, {:#X}, {:#X}, {:#X})",
|
||||
a, a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
e,
|
||||
f
|
||||
)
|
||||
a, a, b, c, d, e, f
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
+12
-6
@@ -1,9 +1,11 @@
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use crate::interrupt::InterruptStack;
|
||||
use crate::paging::VirtualAddress;
|
||||
use crate::context;
|
||||
use crate::syscall::error::{Error, EFAULT, EINVAL, EPERM, ESRCH, Result};
|
||||
use crate::{
|
||||
context,
|
||||
interrupt::InterruptStack,
|
||||
paging::VirtualAddress,
|
||||
syscall::error::{Error, Result, EFAULT, EINVAL, EPERM, ESRCH},
|
||||
};
|
||||
fn enforce_root() -> Result<()> {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
@@ -52,8 +54,12 @@ pub fn virttophys(virtual_address: usize) -> Result<usize> {
|
||||
let addr_space = Arc::clone(context::current()?.read().addr_space()?);
|
||||
let addr_space = addr_space.read();
|
||||
|
||||
match addr_space.table.utable.translate(VirtualAddress::new(virtual_address)) {
|
||||
match addr_space
|
||||
.table
|
||||
.utable
|
||||
.translate(VirtualAddress::new(virtual_address))
|
||||
{
|
||||
Some((physical_address, _)) => Ok(physical_address.data()),
|
||||
None => Err(Error::new(EFAULT))
|
||||
None => Err(Error::new(EFAULT)),
|
||||
}
|
||||
}
|
||||
|
||||
+153
-54
@@ -1,34 +1,55 @@
|
||||
//! Filesystem syscalls
|
||||
use alloc::sync::Arc;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use spin::RwLock;
|
||||
|
||||
use crate::context::file::{FileDescriptor, FileDescription};
|
||||
use crate::context;
|
||||
use crate::context::memory::{PageSpan, AddrSpace};
|
||||
use crate::paging::{PAGE_SIZE, VirtualAddress, Page};
|
||||
use crate::scheme::{self, FileHandle, OpenResult, KernelScheme, SchemeId, CallerCtx};
|
||||
use crate::syscall::data::Stat;
|
||||
use crate::syscall::error::*;
|
||||
use crate::syscall::flag::*;
|
||||
use crate::{
|
||||
context,
|
||||
context::{
|
||||
file::{FileDescription, FileDescriptor},
|
||||
memory::{AddrSpace, PageSpan},
|
||||
},
|
||||
paging::{Page, VirtualAddress, PAGE_SIZE},
|
||||
scheme::{self, CallerCtx, FileHandle, KernelScheme, OpenResult, SchemeId},
|
||||
syscall::{data::Stat, error::*, flag::*},
|
||||
};
|
||||
|
||||
use super::usercopy::{UserSlice, UserSliceWo, UserSliceRo};
|
||||
use super::usercopy::{UserSlice, UserSliceRo, UserSliceWo};
|
||||
|
||||
pub fn file_op_generic<T>(fd: FileHandle, op: impl FnOnce(&dyn KernelScheme, &CallerCtx, usize) -> Result<T>) -> Result<T> {
|
||||
pub fn file_op_generic<T>(
|
||||
fd: FileHandle,
|
||||
op: impl FnOnce(&dyn KernelScheme, &CallerCtx, usize) -> Result<T>,
|
||||
) -> Result<T> {
|
||||
file_op_generic_ext(fd, |s, _, ctx, no| op(s, ctx, no))
|
||||
}
|
||||
pub fn file_op_generic_ext<T>(fd: FileHandle, op: impl FnOnce(&dyn KernelScheme, SchemeId, &CallerCtx, usize) -> Result<T>) -> Result<T> {
|
||||
pub fn file_op_generic_ext<T>(
|
||||
fd: FileHandle,
|
||||
op: impl FnOnce(&dyn KernelScheme, SchemeId, &CallerCtx, usize) -> Result<T>,
|
||||
) -> Result<T> {
|
||||
let (ctx, file) = match context::current()?.read() {
|
||||
ref context => (CallerCtx { pid: context.id.into(), uid: context.euid, gid: context.egid }, context.get_file(fd).ok_or(Error::new(EBADF))?),
|
||||
ref context => (
|
||||
CallerCtx {
|
||||
pid: context.id.into(),
|
||||
uid: context.euid,
|
||||
gid: context.egid,
|
||||
},
|
||||
context.get_file(fd).ok_or(Error::new(EBADF))?,
|
||||
),
|
||||
};
|
||||
let FileDescription { scheme: scheme_id, number, .. } = *file.description.read();
|
||||
let FileDescription {
|
||||
scheme: scheme_id,
|
||||
number,
|
||||
..
|
||||
} = *file.description.read();
|
||||
|
||||
let scheme = scheme::schemes().get(scheme_id).ok_or(Error::new(EBADF))?.clone();
|
||||
let scheme = scheme::schemes()
|
||||
.get(scheme_id)
|
||||
.ok_or(Error::new(EBADF))?
|
||||
.clone();
|
||||
|
||||
op(&*scheme, scheme_id, &ctx, number)
|
||||
}
|
||||
pub fn copy_path_to_buf(raw_path: UserSliceRo, max_len: usize) -> Result<alloc::string::String> {
|
||||
let mut path_buf = vec! [0_u8; max_len];
|
||||
let mut path_buf = vec![0_u8; max_len];
|
||||
if raw_path.len() > path_buf.len() {
|
||||
return Err(Error::new(ENAMETOOLONG));
|
||||
}
|
||||
@@ -43,7 +64,13 @@ const PATH_MAX: usize = PAGE_SIZE;
|
||||
/// Open syscall
|
||||
pub fn open(raw_path: UserSliceRo, flags: usize) -> Result<FileHandle> {
|
||||
let (pid, uid, gid, scheme_ns, umask) = match context::current()?.read() {
|
||||
ref context => (context.id.into(), context.euid, context.egid, context.ens, context.umask),
|
||||
ref context => (
|
||||
context.id.into(),
|
||||
context.euid,
|
||||
context.egid,
|
||||
context.ens,
|
||||
context.umask,
|
||||
),
|
||||
};
|
||||
|
||||
let flags = (flags & (!0o777)) | ((flags & 0o777) & (!(umask & 0o777)));
|
||||
@@ -63,7 +90,9 @@ pub fn open(raw_path: UserSliceRo, flags: usize) -> Result<FileHandle> {
|
||||
let description = {
|
||||
let (scheme_id, scheme) = {
|
||||
let schemes = scheme::schemes();
|
||||
let (scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?;
|
||||
let (scheme_id, scheme) = schemes
|
||||
.get_name(scheme_ns, scheme_name)
|
||||
.ok_or(Error::new(ENODEV))?;
|
||||
(scheme_id, scheme.clone())
|
||||
};
|
||||
|
||||
@@ -79,10 +108,13 @@ pub fn open(raw_path: UserSliceRo, flags: usize) -> Result<FileHandle> {
|
||||
};
|
||||
//drop(path_buf);
|
||||
|
||||
context::current()?.read().add_file(FileDescriptor {
|
||||
description,
|
||||
cloexec: flags & O_CLOEXEC == O_CLOEXEC,
|
||||
}).ok_or(Error::new(EMFILE))
|
||||
context::current()?
|
||||
.read()
|
||||
.add_file(FileDescriptor {
|
||||
description,
|
||||
cloexec: flags & O_CLOEXEC == O_CLOEXEC,
|
||||
})
|
||||
.ok_or(Error::new(EMFILE))
|
||||
}
|
||||
|
||||
/// rmdir syscall
|
||||
@@ -103,7 +135,9 @@ pub fn rmdir(raw_path: UserSliceRo) -> Result<()> {
|
||||
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?;
|
||||
let (_scheme_id, scheme) = schemes
|
||||
.get_name(scheme_ns, scheme_name)
|
||||
.ok_or(Error::new(ENODEV))?;
|
||||
scheme.clone()
|
||||
};
|
||||
scheme.rmdir(reference, caller_ctx)
|
||||
@@ -126,7 +160,9 @@ pub fn unlink(raw_path: UserSliceRo) -> Result<()> {
|
||||
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?;
|
||||
let (_scheme_id, scheme) = schemes
|
||||
.get_name(scheme_ns, scheme_name)
|
||||
.ok_or(Error::new(ENODEV))?;
|
||||
scheme.clone()
|
||||
};
|
||||
scheme.unlink(reference, caller_ctx)
|
||||
@@ -146,7 +182,10 @@ pub fn close(fd: FileHandle) -> Result<()> {
|
||||
|
||||
fn duplicate_file(fd: FileHandle, user_buf: UserSliceRo) -> Result<FileDescriptor> {
|
||||
let (file, caller_ctx) = match context::current()?.read() {
|
||||
ref context => (context.get_file(fd).ok_or(Error::new(EBADF))?, context.caller_ctx()),
|
||||
ref context => (
|
||||
context.get_file(fd).ok_or(Error::new(EBADF))?,
|
||||
context.caller_ctx(),
|
||||
),
|
||||
};
|
||||
|
||||
if user_buf.is_empty() {
|
||||
@@ -159,7 +198,8 @@ fn duplicate_file(fd: FileHandle, user_buf: UserSliceRo) -> Result<FileDescripto
|
||||
|
||||
let new_description = {
|
||||
let scheme = scheme::schemes()
|
||||
.get(description.scheme).ok_or(Error::new(EBADF))?
|
||||
.get(description.scheme)
|
||||
.ok_or(Error::new(EBADF))?
|
||||
.clone();
|
||||
|
||||
match scheme.kdup(description.number, user_buf, caller_ctx)? {
|
||||
@@ -184,7 +224,10 @@ fn duplicate_file(fd: FileHandle, user_buf: UserSliceRo) -> Result<FileDescripto
|
||||
pub fn dup(fd: FileHandle, buf: UserSliceRo) -> Result<FileHandle> {
|
||||
let new_file = duplicate_file(fd, buf)?;
|
||||
|
||||
context::current()?.read().add_file(new_file).ok_or(Error::new(EMFILE))
|
||||
context::current()?
|
||||
.read()
|
||||
.add_file(new_file)
|
||||
.ok_or(Error::new(EMFILE))
|
||||
}
|
||||
|
||||
/// Duplicate file descriptor, replacing another
|
||||
@@ -199,7 +242,9 @@ pub fn dup2(fd: FileHandle, new_fd: FileHandle, buf: UserSliceRo) -> Result<File
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
|
||||
context.insert_file(new_fd, new_file).ok_or(Error::new(EMFILE))
|
||||
context
|
||||
.insert_file(new_fd, new_file)
|
||||
.ok_or(Error::new(EMFILE))
|
||||
}
|
||||
}
|
||||
pub fn sendfd(socket: FileHandle, fd: FileHandle, flags_raw: usize, arg: u64) -> Result<usize> {
|
||||
@@ -211,12 +256,27 @@ pub fn sendfd(socket: FileHandle, fd: FileHandle, flags_raw: usize, arg: u64) ->
|
||||
|
||||
// TODO: Ensure deadlocks can't happen
|
||||
|
||||
let (scheme, number) = match current.get_file(socket).ok_or(Error::new(EBADF))?.description.read() {
|
||||
let (scheme, number) = match current
|
||||
.get_file(socket)
|
||||
.ok_or(Error::new(EBADF))?
|
||||
.description
|
||||
.read()
|
||||
{
|
||||
ref desc => (desc.scheme, desc.number),
|
||||
};
|
||||
let scheme = scheme::schemes().get(scheme).ok_or(Error::new(ENODEV))?.clone();
|
||||
let scheme = scheme::schemes()
|
||||
.get(scheme)
|
||||
.ok_or(Error::new(ENODEV))?
|
||||
.clone();
|
||||
|
||||
(scheme, number, current.remove_file(fd).ok_or(Error::new(EBADF))?.description)
|
||||
(
|
||||
scheme,
|
||||
number,
|
||||
current
|
||||
.remove_file(fd)
|
||||
.ok_or(Error::new(EBADF))?
|
||||
.description,
|
||||
)
|
||||
};
|
||||
|
||||
// Inform the scheme whether there are still references to the file description to be sent,
|
||||
@@ -249,7 +309,8 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
|
||||
// Communicate fcntl with scheme
|
||||
if cmd != F_DUPFD && cmd != F_GETFD && cmd != F_SETFD {
|
||||
let scheme = scheme::schemes()
|
||||
.get(description.scheme).ok_or(Error::new(EBADF))?
|
||||
.get(description.scheme)
|
||||
.ok_or(Error::new(EBADF))?
|
||||
.clone();
|
||||
|
||||
scheme.fcntl(description.number, cmd, arg)?;
|
||||
@@ -265,7 +326,8 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
|
||||
return context.add_file_min(new_file, arg)
|
||||
return context
|
||||
.add_file_min(new_file, arg)
|
||||
.ok_or(Error::new(EMFILE))
|
||||
.map(FileHandle::into);
|
||||
}
|
||||
@@ -283,32 +345,36 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
},
|
||||
}
|
||||
F_SETFD => {
|
||||
file.cloexec = arg & O_CLOEXEC == O_CLOEXEC;
|
||||
Ok(0)
|
||||
},
|
||||
F_GETFL => {
|
||||
Ok(description.flags)
|
||||
},
|
||||
}
|
||||
F_GETFL => Ok(description.flags),
|
||||
F_SETFL => {
|
||||
let new_flags = (description.flags & O_ACCMODE) | (arg & ! O_ACCMODE);
|
||||
let new_flags = (description.flags & O_ACCMODE) | (arg & !O_ACCMODE);
|
||||
drop(description);
|
||||
file.description.write().flags = new_flags;
|
||||
Ok(0)
|
||||
},
|
||||
_ => {
|
||||
Err(Error::new(EINVAL))
|
||||
}
|
||||
_ => Err(Error::new(EINVAL)),
|
||||
},
|
||||
None => Err(Error::new(EBADF))
|
||||
None => Err(Error::new(EBADF)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn frename(fd: FileHandle, raw_path: UserSliceRo) -> Result<()> {
|
||||
let (file, caller_ctx, scheme_ns) = match context::current()?.read() {
|
||||
ref context => (context.get_file(fd).ok_or(Error::new(EBADF))?, CallerCtx { uid: context.euid, gid: context.egid, pid: context.id.get() }, context.ens),
|
||||
ref context => (
|
||||
context.get_file(fd).ok_or(Error::new(EBADF))?,
|
||||
CallerCtx {
|
||||
uid: context.euid,
|
||||
gid: context.egid,
|
||||
pid: context.id.get(),
|
||||
},
|
||||
context.ens,
|
||||
),
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -323,7 +389,9 @@ pub fn frename(fd: FileHandle, raw_path: UserSliceRo) -> Result<()> {
|
||||
|
||||
let (scheme_id, scheme) = {
|
||||
let schemes = scheme::schemes();
|
||||
let (scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?;
|
||||
let (scheme_id, scheme) = schemes
|
||||
.get_name(scheme_ns, scheme_name)
|
||||
.ok_or(Error::new(ENODEV))?;
|
||||
(scheme_id, scheme.clone())
|
||||
};
|
||||
|
||||
@@ -344,8 +412,15 @@ pub fn fstat(fd: FileHandle, user_buf: UserSliceWo) -> Result<()> {
|
||||
// TODO: Ensure only the kernel can access the stat when st_dev is set, or use another API
|
||||
// for retrieving the scheme ID from a file descriptor.
|
||||
// TODO: Less hacky method.
|
||||
let st_dev = scheme_id.get().try_into().map_err(|_| Error::new(EOVERFLOW))?;
|
||||
user_buf.advance(core::mem::offset_of!(Stat, st_dev)).and_then(|b| b.limit(8)).ok_or(Error::new(EIO))?.copy_from_slice(&u64::to_ne_bytes(st_dev))?;
|
||||
let st_dev = scheme_id
|
||||
.get()
|
||||
.try_into()
|
||||
.map_err(|_| Error::new(EOVERFLOW))?;
|
||||
user_buf
|
||||
.advance(core::mem::offset_of!(Stat, st_dev))
|
||||
.and_then(|b| b.limit(8))
|
||||
.ok_or(Error::new(EIO))?
|
||||
.copy_from_slice(&u64::to_ne_bytes(st_dev))?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
@@ -360,11 +435,16 @@ pub fn funmap(virtual_address: usize, length: usize) -> Result<usize> {
|
||||
|
||||
let length_aligned = length.next_multiple_of(PAGE_SIZE);
|
||||
if length != length_aligned {
|
||||
log::warn!("funmap passed length {:#x} instead of {:#x}", length, length_aligned);
|
||||
log::warn!(
|
||||
"funmap passed length {:#x} instead of {:#x}",
|
||||
length,
|
||||
length_aligned
|
||||
);
|
||||
}
|
||||
|
||||
let addr_space = Arc::clone(context::current()?.read().addr_space()?);
|
||||
let span = PageSpan::validate_nonempty(VirtualAddress::new(virtual_address), length_aligned).ok_or(Error::new(EINVAL))?;
|
||||
let span = PageSpan::validate_nonempty(VirtualAddress::new(virtual_address), length_aligned)
|
||||
.ok_or(Error::new(EINVAL))?;
|
||||
let unpin = false;
|
||||
let notify = addr_space.write().munmap(span, unpin)?;
|
||||
|
||||
@@ -375,8 +455,18 @@ pub fn funmap(virtual_address: usize, length: usize) -> Result<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub fn mremap(old_address: usize, old_size: usize, new_address: usize, new_size: usize, flags: usize) -> Result<usize> {
|
||||
if old_address % PAGE_SIZE != 0 || old_size % PAGE_SIZE != 0 || new_address % PAGE_SIZE != 0 || new_size % PAGE_SIZE != 0 {
|
||||
pub fn mremap(
|
||||
old_address: usize,
|
||||
old_size: usize,
|
||||
new_address: usize,
|
||||
new_size: usize,
|
||||
flags: usize,
|
||||
) -> Result<usize> {
|
||||
if old_address % PAGE_SIZE != 0
|
||||
|| old_size % PAGE_SIZE != 0
|
||||
|| new_address % PAGE_SIZE != 0
|
||||
|| new_size % PAGE_SIZE != 0
|
||||
{
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
if old_size == 0 || new_size == 0 {
|
||||
@@ -387,7 +477,8 @@ pub fn mremap(old_address: usize, old_size: usize, new_address: usize, new_size:
|
||||
let new_base = Page::containing_address(VirtualAddress::new(new_address));
|
||||
|
||||
let mremap_flags = MremapFlags::from_bits_truncate(flags);
|
||||
let prot_flags = MapFlags::from_bits_truncate(flags) & (MapFlags::PROT_READ | MapFlags::PROT_WRITE | MapFlags::PROT_EXEC);
|
||||
let prot_flags = MapFlags::from_bits_truncate(flags)
|
||||
& (MapFlags::PROT_READ | MapFlags::PROT_WRITE | MapFlags::PROT_EXEC);
|
||||
|
||||
let map_flags = if mremap_flags.contains(MremapFlags::FIXED_REPLACE) {
|
||||
MapFlags::MAP_FIXED
|
||||
@@ -404,7 +495,15 @@ pub fn mremap(old_address: usize, old_size: usize, new_address: usize, new_size:
|
||||
|
||||
let mut guard = addr_space.write();
|
||||
|
||||
let base = AddrSpace::r#move(&mut *guard, None, src_span, requested_dst_base, new_page_count, map_flags, &mut Vec::new())?;
|
||||
let base = AddrSpace::r#move(
|
||||
&mut *guard,
|
||||
None,
|
||||
src_span,
|
||||
requested_dst_base,
|
||||
new_page_count,
|
||||
map_flags,
|
||||
&mut Vec::new(),
|
||||
)?;
|
||||
|
||||
Ok(base.start_address().data())
|
||||
}
|
||||
|
||||
+22
-14
@@ -2,20 +2,23 @@
|
||||
//! Futex or Fast Userspace Mutex is "a method for waiting until a certain condition becomes true."
|
||||
//!
|
||||
//! For more information about futexes, please read [this](https://eli.thegreenplace.net/2018/basics-of-futexes/) blog post, and the [futex(2)](http://man7.org/linux/man-pages/man2/futex.2.html) man page
|
||||
use alloc::collections::VecDeque;
|
||||
use alloc::sync::Arc;
|
||||
use rmm::Arch;
|
||||
use alloc::{collections::VecDeque, sync::Arc};
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use rmm::Arch;
|
||||
use spin::RwLock;
|
||||
|
||||
use crate::context::{self, memory::AddrSpace, Context};
|
||||
use crate::memory::PhysicalAddress;
|
||||
use crate::paging::{Page, VirtualAddress};
|
||||
use crate::time;
|
||||
use crate::{
|
||||
context::{self, memory::AddrSpace, Context},
|
||||
memory::PhysicalAddress,
|
||||
paging::{Page, VirtualAddress},
|
||||
time,
|
||||
};
|
||||
|
||||
use crate::syscall::data::TimeSpec;
|
||||
use crate::syscall::error::{Error, Result, EAGAIN, EFAULT, EINVAL, ESRCH};
|
||||
use crate::syscall::flag::{FUTEX_REQUEUE, FUTEX_WAIT, FUTEX_WAIT64, FUTEX_WAKE};
|
||||
use crate::syscall::{
|
||||
data::TimeSpec,
|
||||
error::{Error, Result, EAGAIN, EFAULT, EINVAL, ESRCH},
|
||||
flag::{FUTEX_REQUEUE, FUTEX_WAIT, FUTEX_WAIT64, FUTEX_WAKE},
|
||||
};
|
||||
|
||||
use super::usercopy::UserSlice;
|
||||
|
||||
@@ -58,8 +61,10 @@ pub fn futex(addr: usize, op: usize, val: usize, val2: usize, addr2: usize) -> R
|
||||
match op {
|
||||
// TODO: FUTEX_WAIT_MULTIPLE?
|
||||
FUTEX_WAIT | FUTEX_WAIT64 => {
|
||||
let timeout_opt = UserSlice::ro(val2, core::mem::size_of::<TimeSpec>())?.none_if_null()
|
||||
.map(|buf| unsafe { buf.read_exact::<TimeSpec>() }).transpose()?;
|
||||
let timeout_opt = UserSlice::ro(val2, core::mem::size_of::<TimeSpec>())?
|
||||
.none_if_null()
|
||||
.map(|buf| unsafe { buf.read_exact::<TimeSpec>() })
|
||||
.transpose()?;
|
||||
|
||||
{
|
||||
let mut futexes = FUTEXES.write();
|
||||
@@ -75,7 +80,8 @@ pub fn futex(addr: usize, op: usize, val: usize, val2: usize, addr2: usize) -> R
|
||||
|
||||
// On systems where virtual memory is not abundant, we might instead add an
|
||||
// atomic usercopy function.
|
||||
let accessible_addr = unsafe { crate::paging::RmmA::phys_to_virt(target_physaddr) }.data();
|
||||
let accessible_addr =
|
||||
unsafe { crate::paging::RmmA::phys_to_virt(target_physaddr) }.data();
|
||||
|
||||
(
|
||||
u64::from(unsafe {
|
||||
@@ -93,7 +99,9 @@ pub fn futex(addr: usize, op: usize, val: usize, val2: usize, addr2: usize) -> R
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
(
|
||||
u64::from(unsafe { (*(addr as *const AtomicU64)).load(Ordering::SeqCst) }),
|
||||
u64::from(unsafe {
|
||||
(*(addr as *const AtomicU64)).load(Ordering::SeqCst)
|
||||
}),
|
||||
val as u64,
|
||||
)
|
||||
}
|
||||
|
||||
+110
-55
@@ -7,35 +7,26 @@ extern crate syscall;
|
||||
use syscall::{EventFlags, EOVERFLOW};
|
||||
|
||||
pub use self::syscall::{
|
||||
FloatRegisters,
|
||||
IntRegisters,
|
||||
EnvRegisters,
|
||||
data,
|
||||
error,
|
||||
flag,
|
||||
io,
|
||||
number,
|
||||
ptrace_event,
|
||||
data, error, flag, io, number, ptrace_event, EnvRegisters, FloatRegisters, IntRegisters,
|
||||
};
|
||||
|
||||
pub use self::driver::*;
|
||||
pub use self::fs::*;
|
||||
pub use self::futex::futex;
|
||||
pub use self::privilege::*;
|
||||
pub use self::process::*;
|
||||
pub use self::time::*;
|
||||
pub use self::usercopy::validate_region;
|
||||
pub use self::{
|
||||
driver::*, fs::*, futex::futex, privilege::*, process::*, time::*, usercopy::validate_region,
|
||||
};
|
||||
|
||||
use self::data::{Map, SigAction, TimeSpec};
|
||||
use self::error::{Error, Result, ENOSYS};
|
||||
use self::flag::{MapFlags, WaitFlags};
|
||||
use self::number::*;
|
||||
use self::{
|
||||
data::{Map, SigAction, TimeSpec},
|
||||
error::{Error, Result, ENOSYS},
|
||||
flag::{MapFlags, WaitFlags},
|
||||
number::*,
|
||||
};
|
||||
|
||||
use crate::context::ContextId;
|
||||
use crate::context::memory::AddrSpace;
|
||||
use crate::interrupt::InterruptStack;
|
||||
use crate::scheme::{FileHandle, SchemeNamespace, memory::MemoryScheme};
|
||||
use crate::syscall::usercopy::UserSlice;
|
||||
use crate::{
|
||||
context::{memory::AddrSpace, ContextId},
|
||||
interrupt::InterruptStack,
|
||||
scheme::{memory::MemoryScheme, FileHandle, SchemeNamespace},
|
||||
syscall::usercopy::UserSlice,
|
||||
};
|
||||
|
||||
/// Debug
|
||||
pub mod debug;
|
||||
@@ -63,79 +54,128 @@ pub mod usercopy;
|
||||
|
||||
/// This function is the syscall handler of the kernel, it is composed of an inner function that returns a `Result<usize>`. After the inner function runs, the syscall
|
||||
/// function calls [`Error::mux`] on it.
|
||||
pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack: &mut InterruptStack) -> usize {
|
||||
pub fn syscall(
|
||||
a: usize,
|
||||
b: usize,
|
||||
c: usize,
|
||||
d: usize,
|
||||
e: usize,
|
||||
f: usize,
|
||||
stack: &mut InterruptStack,
|
||||
) -> usize {
|
||||
#[inline(always)]
|
||||
fn inner(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack: &mut InterruptStack) -> Result<usize> {
|
||||
fn inner(
|
||||
a: usize,
|
||||
b: usize,
|
||||
c: usize,
|
||||
d: usize,
|
||||
e: usize,
|
||||
f: usize,
|
||||
stack: &mut InterruptStack,
|
||||
) -> Result<usize> {
|
||||
//SYS_* is declared in kernel/syscall/src/number.rs
|
||||
match a & SYS_CLASS {
|
||||
SYS_CLASS_FILE => {
|
||||
let fd = FileHandle::from(b);
|
||||
match a & SYS_ARG {
|
||||
SYS_ARG_SLICE => match a {
|
||||
SYS_WRITE => file_op_generic(fd, |scheme, _, number| scheme.kwrite(number, UserSlice::ro(c, d)?)),
|
||||
SYS_WRITE => file_op_generic(fd, |scheme, _, number| {
|
||||
scheme.kwrite(number, UserSlice::ro(c, d)?)
|
||||
}),
|
||||
SYS_FMAP => {
|
||||
let addrspace = AddrSpace::current()?;
|
||||
let map = unsafe { UserSlice::ro(c, d)?.read_exact::<Map>()? };
|
||||
if b == !0 {
|
||||
MemoryScheme::fmap_anonymous(&addrspace, &map, false)
|
||||
} else {
|
||||
file_op_generic(fd, |scheme, _, number| scheme.kfmap(number, &addrspace, &map, false))
|
||||
file_op_generic(fd, |scheme, _, number| {
|
||||
scheme.kfmap(number, &addrspace, &map, false)
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
// SYS_FMAP_OLD is ignored
|
||||
SYS_FUTIMENS => file_op_generic(fd, |scheme, _, number| scheme.kfutimens(number, UserSlice::ro(c, d)?)),
|
||||
SYS_FUTIMENS => file_op_generic(fd, |scheme, _, number| {
|
||||
scheme.kfutimens(number, UserSlice::ro(c, d)?)
|
||||
}),
|
||||
|
||||
_ => return Err(Error::new(ENOSYS)),
|
||||
}
|
||||
},
|
||||
SYS_ARG_MSLICE => match a {
|
||||
SYS_READ => file_op_generic(fd, |scheme, _, number| scheme.kread(number, UserSlice::wo(c, d)?)),
|
||||
SYS_FPATH => file_op_generic(fd, |scheme, _, number| scheme.kfpath(number, UserSlice::wo(c, d)?)),
|
||||
SYS_READ => file_op_generic(fd, |scheme, _, number| {
|
||||
scheme.kread(number, UserSlice::wo(c, d)?)
|
||||
}),
|
||||
SYS_FPATH => file_op_generic(fd, |scheme, _, number| {
|
||||
scheme.kfpath(number, UserSlice::wo(c, d)?)
|
||||
}),
|
||||
SYS_FSTAT => fstat(fd, UserSlice::wo(c, d)?).map(|()| 0),
|
||||
SYS_FSTATVFS => file_op_generic(fd, |scheme, _, number| scheme.kfstatvfs(number, UserSlice::wo(c, d)?).map(|()| 0)),
|
||||
SYS_FSTATVFS => file_op_generic(fd, |scheme, _, number| {
|
||||
scheme.kfstatvfs(number, UserSlice::wo(c, d)?).map(|()| 0)
|
||||
}),
|
||||
|
||||
_ => return Err(Error::new(ENOSYS)),
|
||||
},
|
||||
_ => match a {
|
||||
SYS_DUP => dup(fd, UserSlice::ro(c, d)?).map(FileHandle::into),
|
||||
SYS_DUP2 => dup2(fd, FileHandle::from(c), UserSlice::ro(d, e)?).map(FileHandle::into),
|
||||
SYS_DUP2 => dup2(fd, FileHandle::from(c), UserSlice::ro(d, e)?)
|
||||
.map(FileHandle::into),
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
SYS_SENDFD => sendfd(fd, FileHandle::from(c), d, e as u64 | ((f as u64) << 32)),
|
||||
SYS_SENDFD => {
|
||||
sendfd(fd, FileHandle::from(c), d, e as u64 | ((f as u64) << 32))
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
SYS_SENDFD => sendfd(fd, FileHandle::from(c), d, e as u64),
|
||||
|
||||
SYS_LSEEK => file_op_generic(fd, |scheme, _, number| scheme.seek(number, c as isize, d)),
|
||||
SYS_FCHMOD => file_op_generic(fd, |scheme, _, number| scheme.fchmod(number, c as u16).map(|()| 0)),
|
||||
SYS_FCHOWN => file_op_generic(fd, |scheme, _, number| scheme.fchown(number, c as u32, d as u32).map(|()| 0)),
|
||||
SYS_LSEEK => file_op_generic(fd, |scheme, _, number| {
|
||||
scheme.seek(number, c as isize, d)
|
||||
}),
|
||||
SYS_FCHMOD => file_op_generic(fd, |scheme, _, number| {
|
||||
scheme.fchmod(number, c as u16).map(|()| 0)
|
||||
}),
|
||||
SYS_FCHOWN => file_op_generic(fd, |scheme, _, number| {
|
||||
scheme.fchown(number, c as u32, d as u32).map(|()| 0)
|
||||
}),
|
||||
SYS_FCNTL => fcntl(fd, c, d),
|
||||
SYS_FEVENT => file_op_generic(fd, |scheme, _, number| Ok(scheme.fevent(number, EventFlags::from_bits_truncate(c))?.bits())),
|
||||
SYS_FEVENT => file_op_generic(fd, |scheme, _, number| {
|
||||
Ok(scheme
|
||||
.fevent(number, EventFlags::from_bits_truncate(c))?
|
||||
.bits())
|
||||
}),
|
||||
SYS_FRENAME => frename(fd, UserSlice::ro(c, d)?).map(|()| 0),
|
||||
SYS_FUNMAP => funmap(b, c),
|
||||
|
||||
SYS_FSYNC => file_op_generic(fd, |scheme, _, number| scheme.fsync(number).map(|()| 0)),
|
||||
SYS_FSYNC => file_op_generic(fd, |scheme, _, number| {
|
||||
scheme.fsync(number).map(|()| 0)
|
||||
}),
|
||||
// TODO: 64-bit lengths on 32-bit platforms
|
||||
SYS_FTRUNCATE => file_op_generic(fd, |scheme, _, number| scheme.ftruncate(number, c).map(|()| 0)),
|
||||
SYS_FTRUNCATE => file_op_generic(fd, |scheme, _, number| {
|
||||
scheme.ftruncate(number, c).map(|()| 0)
|
||||
}),
|
||||
|
||||
SYS_CLOSE => close(fd).map(|()| 0),
|
||||
|
||||
_ => return Err(Error::new(ENOSYS)),
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
SYS_CLASS_PATH => match a {
|
||||
SYS_OPEN => open(UserSlice::ro(b, c)?, d).map(FileHandle::into),
|
||||
SYS_RMDIR => rmdir(UserSlice::ro(b, c)?).map(|()| 0),
|
||||
SYS_UNLINK => unlink(UserSlice::ro(b, c)?).map(|()| 0),
|
||||
_ => Err(Error::new(ENOSYS))
|
||||
_ => Err(Error::new(ENOSYS)),
|
||||
},
|
||||
_ => match a {
|
||||
SYS_YIELD => sched_yield().map(|()| 0),
|
||||
SYS_NANOSLEEP => nanosleep(
|
||||
UserSlice::ro(b, core::mem::size_of::<TimeSpec>())?,
|
||||
UserSlice::wo(c, core::mem::size_of::<TimeSpec>())?.none_if_null(),
|
||||
).map(|()| 0),
|
||||
SYS_CLOCK_GETTIME => clock_gettime(b, UserSlice::wo(c, core::mem::size_of::<TimeSpec>())?).map(|()| 0),
|
||||
)
|
||||
.map(|()| 0),
|
||||
SYS_CLOCK_GETTIME => {
|
||||
clock_gettime(b, UserSlice::wo(c, core::mem::size_of::<TimeSpec>())?)
|
||||
.map(|()| 0)
|
||||
}
|
||||
SYS_FUTEX => futex(b, c, d, e, f),
|
||||
SYS_GETPID => getpid().map(ContextId::into),
|
||||
SYS_GETPGID => getpgid(ContextId::from(b)).map(ContextId::into),
|
||||
@@ -143,7 +183,16 @@ 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), if c == 0 { None } else { Some(UserSlice::wo(c, core::mem::size_of::<usize>())?) }, WaitFlags::from_bits_truncate(d)).map(ContextId::into),
|
||||
SYS_WAITPID => waitpid(
|
||||
ContextId::from(b),
|
||||
if c == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(UserSlice::wo(c, core::mem::size_of::<usize>())?)
|
||||
},
|
||||
WaitFlags::from_bits_truncate(d),
|
||||
)
|
||||
.map(ContextId::into),
|
||||
SYS_IOPL => iopl(b, stack),
|
||||
SYS_GETEGID => getegid(),
|
||||
SYS_GETENS => getens(),
|
||||
@@ -152,7 +201,11 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack
|
||||
SYS_GETNS => getns(),
|
||||
SYS_GETUID => getuid(),
|
||||
SYS_MPROTECT => mprotect(b, c, MapFlags::from_bits_truncate(d)),
|
||||
SYS_MKNS => mkns(UserSlice::ro(b, c.checked_mul(core::mem::size_of::<[usize; 2]>()).ok_or(Error::new(EOVERFLOW))?)?),
|
||||
SYS_MKNS => mkns(UserSlice::ro(
|
||||
b,
|
||||
c.checked_mul(core::mem::size_of::<[usize; 2]>())
|
||||
.ok_or(Error::new(EOVERFLOW))?,
|
||||
)?),
|
||||
SYS_SETPGID => setpgid(ContextId::from(b), ContextId::from(c)),
|
||||
SYS_SETREUID => setreuid(b as u32, c as u32),
|
||||
SYS_SETRENS => setrens(SchemeNamespace::from(b), SchemeNamespace::from(c)),
|
||||
@@ -162,20 +215,22 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack
|
||||
UserSlice::ro(c, core::mem::size_of::<SigAction>())?.none_if_null(),
|
||||
UserSlice::wo(d, core::mem::size_of::<SigAction>())?.none_if_null(),
|
||||
e,
|
||||
).map(|()| 0),
|
||||
)
|
||||
.map(|()| 0),
|
||||
SYS_SIGPROCMASK => sigprocmask(
|
||||
b,
|
||||
UserSlice::ro(c, 16)?.none_if_null(),
|
||||
UserSlice::wo(d, 16)?.none_if_null(),
|
||||
).map(|()| 0),
|
||||
)
|
||||
.map(|()| 0),
|
||||
SYS_SIGRETURN => sigreturn(),
|
||||
SYS_UMASK => umask(b),
|
||||
SYS_VIRTTOPHYS => virttophys(b),
|
||||
|
||||
SYS_MREMAP => mremap(b, c, d, e, f),
|
||||
|
||||
_ => Err(Error::new(ENOSYS))
|
||||
}
|
||||
_ => Err(Error::new(ENOSYS)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,7 +313,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack
|
||||
match result {
|
||||
Ok(ref ok) => {
|
||||
print!("Ok({} ({:#X}))", ok, ok);
|
||||
},
|
||||
}
|
||||
Err(ref err) => {
|
||||
print!("Err({} ({:#X}))", err, err.errno);
|
||||
}
|
||||
|
||||
+120
-120
@@ -1,11 +1,15 @@
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::context;
|
||||
use crate::scheme::{self, SchemeNamespace};
|
||||
use crate::syscall::error::*;
|
||||
use crate::{
|
||||
context,
|
||||
scheme::{self, SchemeNamespace},
|
||||
syscall::error::*,
|
||||
};
|
||||
|
||||
use super::copy_path_to_buf;
|
||||
use super::usercopy::{UserSlice, UserSliceRo};
|
||||
use super::{
|
||||
copy_path_to_buf,
|
||||
usercopy::{UserSlice, UserSliceRo},
|
||||
};
|
||||
|
||||
pub fn getegid() -> Result<usize> {
|
||||
let contexts = context::contexts();
|
||||
@@ -61,7 +65,9 @@ pub fn mkns(mut user_buf: UserSliceRo) -> Result<usize> {
|
||||
|
||||
let mut names = Vec::with_capacity(user_buf.len() / core::mem::size_of::<[usize; 2]>());
|
||||
|
||||
while let Some((current_name_ptr_buf, next_part)) = user_buf.split_at(core::mem::size_of::<[usize; 2]>()) {
|
||||
while let Some((current_name_ptr_buf, next_part)) =
|
||||
user_buf.split_at(core::mem::size_of::<[usize; 2]>())
|
||||
{
|
||||
let mut iter = current_name_ptr_buf.usizes();
|
||||
let ptr = iter.next().ok_or(Error::new(EINVAL))??;
|
||||
let len = iter.next().ok_or(Error::new(EINVAL))??;
|
||||
@@ -85,41 +91,39 @@ pub fn setregid(rgid: u32, egid: u32) -> Result<usize> {
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let mut context = context_lock.write();
|
||||
|
||||
let setrgid =
|
||||
if context.euid == 0 {
|
||||
// Allow changing RGID if root
|
||||
true
|
||||
} else if rgid == context.egid {
|
||||
// Allow changing RGID if used for EGID
|
||||
true
|
||||
} else if rgid == context.rgid {
|
||||
// Allow changing RGID if used for RGID
|
||||
true
|
||||
} else if rgid as i32 == -1 {
|
||||
// Ignore RGID if -1 is passed
|
||||
false
|
||||
} else {
|
||||
// Not permitted otherwise
|
||||
return Err(Error::new(EPERM));
|
||||
};
|
||||
let setrgid = if context.euid == 0 {
|
||||
// Allow changing RGID if root
|
||||
true
|
||||
} else if rgid == context.egid {
|
||||
// Allow changing RGID if used for EGID
|
||||
true
|
||||
} else if rgid == context.rgid {
|
||||
// Allow changing RGID if used for RGID
|
||||
true
|
||||
} else if rgid as i32 == -1 {
|
||||
// Ignore RGID if -1 is passed
|
||||
false
|
||||
} else {
|
||||
// Not permitted otherwise
|
||||
return Err(Error::new(EPERM));
|
||||
};
|
||||
|
||||
let setegid =
|
||||
if context.euid == 0 {
|
||||
// Allow changing EGID if root
|
||||
true
|
||||
} else if egid == context.egid {
|
||||
// Allow changing EGID if used for EGID
|
||||
true
|
||||
} else if egid == context.rgid {
|
||||
// Allow changing EGID if used for RGID
|
||||
true
|
||||
} else if egid as i32 == -1 {
|
||||
// Ignore EGID if -1 is passed
|
||||
false
|
||||
} else {
|
||||
// Not permitted otherwise
|
||||
return Err(Error::new(EPERM));
|
||||
};
|
||||
let setegid = if context.euid == 0 {
|
||||
// Allow changing EGID if root
|
||||
true
|
||||
} else if egid == context.egid {
|
||||
// Allow changing EGID if used for EGID
|
||||
true
|
||||
} else if egid == context.rgid {
|
||||
// Allow changing EGID if used for RGID
|
||||
true
|
||||
} else if egid as i32 == -1 {
|
||||
// Ignore EGID if -1 is passed
|
||||
false
|
||||
} else {
|
||||
// Not permitted otherwise
|
||||
return Err(Error::new(EPERM));
|
||||
};
|
||||
|
||||
if setrgid {
|
||||
context.rgid = rgid;
|
||||
@@ -137,53 +141,51 @@ pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result<usize> {
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let mut context = context_lock.write();
|
||||
|
||||
let setrns =
|
||||
if rns.get() as isize == -1 {
|
||||
// Ignore RNS if -1 is passed
|
||||
false
|
||||
} else if rns.get() == 0 {
|
||||
// Allow entering capability mode
|
||||
true
|
||||
} else if context.rns.get() == 0 {
|
||||
// Do not allow leaving capability mode
|
||||
return Err(Error::new(EPERM));
|
||||
} else if context.euid == 0 {
|
||||
// Allow setting RNS if root
|
||||
true
|
||||
} else if rns == context.ens {
|
||||
// Allow setting RNS if used for ENS
|
||||
true
|
||||
} else if rns == context.rns {
|
||||
// Allow setting RNS if used for RNS
|
||||
true
|
||||
} else {
|
||||
// Not permitted otherwise
|
||||
return Err(Error::new(EPERM));
|
||||
};
|
||||
let setrns = if rns.get() as isize == -1 {
|
||||
// Ignore RNS if -1 is passed
|
||||
false
|
||||
} else if rns.get() == 0 {
|
||||
// Allow entering capability mode
|
||||
true
|
||||
} else if context.rns.get() == 0 {
|
||||
// Do not allow leaving capability mode
|
||||
return Err(Error::new(EPERM));
|
||||
} else if context.euid == 0 {
|
||||
// Allow setting RNS if root
|
||||
true
|
||||
} else if rns == context.ens {
|
||||
// Allow setting RNS if used for ENS
|
||||
true
|
||||
} else if rns == context.rns {
|
||||
// Allow setting RNS if used for RNS
|
||||
true
|
||||
} else {
|
||||
// Not permitted otherwise
|
||||
return Err(Error::new(EPERM));
|
||||
};
|
||||
|
||||
let setens =
|
||||
if ens.get() as isize == -1 {
|
||||
// Ignore ENS if -1 is passed
|
||||
false
|
||||
} else if ens.get() == 0 {
|
||||
// Allow entering capability mode
|
||||
true
|
||||
} else if context.ens.get() == 0 {
|
||||
// Do not allow leaving capability mode
|
||||
return Err(Error::new(EPERM));
|
||||
} else if context.euid == 0 {
|
||||
// Allow setting ENS if root
|
||||
true
|
||||
} else if ens == context.ens {
|
||||
// Allow setting ENS if used for ENS
|
||||
true
|
||||
} else if ens == context.rns {
|
||||
// Allow setting ENS if used for RNS
|
||||
true
|
||||
} else {
|
||||
// Not permitted otherwise
|
||||
return Err(Error::new(EPERM));
|
||||
};
|
||||
let setens = if ens.get() as isize == -1 {
|
||||
// Ignore ENS if -1 is passed
|
||||
false
|
||||
} else if ens.get() == 0 {
|
||||
// Allow entering capability mode
|
||||
true
|
||||
} else if context.ens.get() == 0 {
|
||||
// Do not allow leaving capability mode
|
||||
return Err(Error::new(EPERM));
|
||||
} else if context.euid == 0 {
|
||||
// Allow setting ENS if root
|
||||
true
|
||||
} else if ens == context.ens {
|
||||
// Allow setting ENS if used for ENS
|
||||
true
|
||||
} else if ens == context.rns {
|
||||
// Allow setting ENS if used for RNS
|
||||
true
|
||||
} else {
|
||||
// Not permitted otherwise
|
||||
return Err(Error::new(EPERM));
|
||||
};
|
||||
|
||||
if setrns {
|
||||
assert_ne!(rns.get() as isize, -1);
|
||||
@@ -203,41 +205,39 @@ pub fn setreuid(ruid: u32, euid: u32) -> Result<usize> {
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let mut context = context_lock.write();
|
||||
|
||||
let setruid =
|
||||
if context.euid == 0 {
|
||||
// Allow setting RUID if root
|
||||
true
|
||||
} else if ruid == context.euid {
|
||||
// Allow setting RUID if used for EUID
|
||||
true
|
||||
} else if ruid == context.ruid {
|
||||
// Allow setting RUID if used for RUID
|
||||
true
|
||||
} else if ruid as i32 == -1 {
|
||||
// Ignore RUID if -1 is passed
|
||||
false
|
||||
} else {
|
||||
// Not permitted otherwise
|
||||
return Err(Error::new(EPERM));
|
||||
};
|
||||
let setruid = if context.euid == 0 {
|
||||
// Allow setting RUID if root
|
||||
true
|
||||
} else if ruid == context.euid {
|
||||
// Allow setting RUID if used for EUID
|
||||
true
|
||||
} else if ruid == context.ruid {
|
||||
// Allow setting RUID if used for RUID
|
||||
true
|
||||
} else if ruid as i32 == -1 {
|
||||
// Ignore RUID if -1 is passed
|
||||
false
|
||||
} else {
|
||||
// Not permitted otherwise
|
||||
return Err(Error::new(EPERM));
|
||||
};
|
||||
|
||||
let seteuid =
|
||||
if context.euid == 0 {
|
||||
// Allow setting EUID if root
|
||||
true
|
||||
} else if euid == context.euid {
|
||||
// Allow setting EUID if used for EUID
|
||||
true
|
||||
} else if euid == context.ruid {
|
||||
// Allow setting EUID if used for RUID
|
||||
true
|
||||
} else if euid as i32 == -1 {
|
||||
// Ignore EUID if -1 is passed
|
||||
false
|
||||
} else {
|
||||
// Not permitted otherwise
|
||||
return Err(Error::new(EPERM));
|
||||
};
|
||||
let seteuid = if context.euid == 0 {
|
||||
// Allow setting EUID if root
|
||||
true
|
||||
} else if euid == context.euid {
|
||||
// Allow setting EUID if used for EUID
|
||||
true
|
||||
} else if euid == context.ruid {
|
||||
// Allow setting EUID if used for RUID
|
||||
true
|
||||
} else if euid as i32 == -1 {
|
||||
// Ignore EUID if -1 is passed
|
||||
false
|
||||
} else {
|
||||
// Not permitted otherwise
|
||||
return Err(Error::new(EPERM));
|
||||
};
|
||||
|
||||
if setruid {
|
||||
context.ruid = ruid;
|
||||
|
||||
+132
-82
@@ -1,32 +1,37 @@
|
||||
use alloc::{
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
};
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use core::mem;
|
||||
|
||||
use spin::RwLock;
|
||||
|
||||
use crate::context::memory::PageSpan;
|
||||
use crate::context::{ContextId, memory::AddrSpace, WaitpidKey};
|
||||
use crate::context::{
|
||||
memory::{AddrSpace, PageSpan},
|
||||
ContextId, WaitpidKey,
|
||||
};
|
||||
|
||||
use crate::Bootstrap;
|
||||
use crate::context;
|
||||
use crate::interrupt;
|
||||
use crate::paging::mapper::PageFlushAll;
|
||||
use crate::paging::{Page, PageFlags, VirtualAddress, PAGE_SIZE};
|
||||
use crate::ptrace;
|
||||
use crate::start::usermode;
|
||||
use crate::syscall::data::SigAction;
|
||||
use crate::syscall::error::*;
|
||||
use crate::syscall::flag::{wifcontinued, wifstopped, MapFlags,
|
||||
PTRACE_STOP_EXIT, SIG_BLOCK, SIG_SETMASK, SIG_UNBLOCK,
|
||||
SIGCONT, SIGTERM, WaitFlags, WCONTINUED, WNOHANG, WUNTRACED};
|
||||
use crate::syscall::ptrace_event;
|
||||
use crate::{
|
||||
context, interrupt,
|
||||
paging::{mapper::PageFlushAll, Page, PageFlags, VirtualAddress, PAGE_SIZE},
|
||||
ptrace,
|
||||
start::usermode,
|
||||
syscall::{
|
||||
data::SigAction,
|
||||
error::*,
|
||||
flag::{
|
||||
wifcontinued, wifstopped, MapFlags, WaitFlags, PTRACE_STOP_EXIT, SIGCONT, SIGTERM,
|
||||
SIG_BLOCK, SIG_SETMASK, SIG_UNBLOCK, WCONTINUED, WNOHANG, WUNTRACED,
|
||||
},
|
||||
ptrace_event,
|
||||
},
|
||||
Bootstrap,
|
||||
};
|
||||
|
||||
use super::usercopy::{UserSliceWo, UserSliceRo};
|
||||
use super::usercopy::{UserSliceRo, UserSliceWo};
|
||||
|
||||
pub fn exit(status: usize) -> ! {
|
||||
ptrace::breakpoint_callback(PTRACE_STOP_EXIT, Some(ptrace_event!(PTRACE_STOP_EXIT, status)));
|
||||
ptrace::breakpoint_callback(
|
||||
PTRACE_STOP_EXIT,
|
||||
Some(ptrace_event!(PTRACE_STOP_EXIT, status)),
|
||||
);
|
||||
|
||||
{
|
||||
let context_lock = context::current().expect("exit failed to find context");
|
||||
@@ -36,8 +41,10 @@ pub fn exit(status: usize) -> ! {
|
||||
|
||||
let pid = {
|
||||
let mut context = context_lock.write();
|
||||
close_files = Arc::try_unwrap(mem::take(&mut context.files)).map_or_else(|_| Vec::new(), RwLock::into_inner);
|
||||
addrspace_opt = mem::take(&mut context.addr_space).and_then(|a| Arc::try_unwrap(a).ok());
|
||||
close_files = Arc::try_unwrap(mem::take(&mut context.files))
|
||||
.map_or_else(|_| Vec::new(), RwLock::into_inner);
|
||||
addrspace_opt =
|
||||
mem::take(&mut context.addr_space).and_then(|a| Arc::try_unwrap(a).ok());
|
||||
drop(context.syscall_head.take());
|
||||
drop(context.syscall_tail.take());
|
||||
context.id
|
||||
@@ -47,15 +54,19 @@ pub fn exit(status: usize) -> ! {
|
||||
if pid == ContextId::from(1) {
|
||||
println!("Main kernel thread exited with status {:X}", status);
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
fn kreset() -> !;
|
||||
fn kstop() -> !;
|
||||
}
|
||||
|
||||
if status == SIGTERM {
|
||||
unsafe { kreset(); }
|
||||
unsafe {
|
||||
kreset();
|
||||
}
|
||||
} else {
|
||||
unsafe { kstop(); }
|
||||
unsafe {
|
||||
kstop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,10 +112,13 @@ pub fn exit(status: usize) -> ! {
|
||||
waitpid.send(c_pid, c_status);
|
||||
}
|
||||
|
||||
waitpid.send(WaitpidKey {
|
||||
pid: Some(pid),
|
||||
pgid: Some(pgid)
|
||||
}, (pid, status));
|
||||
waitpid.send(
|
||||
WaitpidKey {
|
||||
pid: Some(pid),
|
||||
pgid: Some(pgid),
|
||||
},
|
||||
(pid, status),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,10 +172,7 @@ pub fn kill(pid: ContextId, sig: usize) -> Result<usize> {
|
||||
let contexts = context::contexts();
|
||||
|
||||
let send = |context: &mut context::Context| -> bool {
|
||||
if euid == 0
|
||||
|| euid == context.ruid
|
||||
|| ruid == context.ruid
|
||||
{
|
||||
if euid == 0 || euid == context.ruid || ruid == context.ruid {
|
||||
// If sig = 0, test that process exists and can be
|
||||
// signalled, but don't send any signal.
|
||||
if sig != 0 {
|
||||
@@ -231,7 +242,9 @@ pub fn kill(pid: ContextId, sig: usize) -> Result<usize> {
|
||||
Err(Error::new(EPERM))
|
||||
} else {
|
||||
// Switch to ensure delivery to self
|
||||
unsafe { context::switch(); }
|
||||
unsafe {
|
||||
context::switch();
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
@@ -243,9 +256,13 @@ pub fn kill(pid: ContextId, sig: usize) -> Result<usize> {
|
||||
pub fn mprotect(address: usize, size: usize, flags: MapFlags) -> Result<usize> {
|
||||
// println!("mprotect {:#X}, {}, {:#X}", address, size, flags);
|
||||
|
||||
let span = PageSpan::validate_nonempty(VirtualAddress::new(address), size).ok_or(Error::new(EINVAL))?;
|
||||
let span = PageSpan::validate_nonempty(VirtualAddress::new(address), size)
|
||||
.ok_or(Error::new(EINVAL))?;
|
||||
|
||||
AddrSpace::current()?.write().mprotect(span, flags).map(|()| 0)
|
||||
AddrSpace::current()?
|
||||
.write()
|
||||
.mprotect(span, flags)
|
||||
.map(|()| 0)
|
||||
}
|
||||
|
||||
pub fn setpgid(pid: ContextId, pgid: ContextId) -> Result<usize> {
|
||||
@@ -276,7 +293,12 @@ pub fn setpgid(pid: ContextId, pgid: ContextId) -> Result<usize> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sigaction(sig: usize, act_opt: Option<UserSliceRo>, oldact_opt: Option<UserSliceWo>, restorer: usize) -> Result<()> {
|
||||
pub fn sigaction(
|
||||
sig: usize,
|
||||
act_opt: Option<UserSliceRo>,
|
||||
oldact_opt: Option<UserSliceWo>,
|
||||
restorer: usize,
|
||||
) -> Result<()> {
|
||||
if sig == 0 || sig > 0x7F {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
@@ -296,7 +318,11 @@ pub fn sigaction(sig: usize, act_opt: Option<UserSliceRo>, oldact_opt: Option<Us
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn sigprocmask(how: usize, mask_opt: Option<UserSliceRo>, oldmask_opt: Option<UserSliceWo>) -> Result<()> {
|
||||
pub fn sigprocmask(
|
||||
how: usize,
|
||||
mask_opt: Option<UserSliceRo>,
|
||||
oldmask_opt: Option<UserSliceWo>,
|
||||
) -> Result<()> {
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
@@ -306,26 +332,24 @@ pub fn sigprocmask(how: usize, mask_opt: Option<UserSliceRo>, oldmask_opt: Optio
|
||||
|
||||
if let Some(oldmask) = oldmask_opt {
|
||||
// TODO: sigprocmask should be u64
|
||||
let (lo_dst, hi_dst) = oldmask.split_at(core::mem::size_of::<u64>()).ok_or(Error::new(EINVAL))?;
|
||||
let (lo_dst, hi_dst) = oldmask
|
||||
.split_at(core::mem::size_of::<u64>())
|
||||
.ok_or(Error::new(EINVAL))?;
|
||||
lo_dst.write_u64(old_lo)?;
|
||||
hi_dst.write_u64(old_hi)?;
|
||||
}
|
||||
|
||||
if let Some(mask) = mask_opt {
|
||||
let (lo_src, hi_src) = mask.split_at(core::mem::size_of::<u64>()).ok_or(Error::new(EINVAL))?;
|
||||
let (lo_src, hi_src) = mask
|
||||
.split_at(core::mem::size_of::<u64>())
|
||||
.ok_or(Error::new(EINVAL))?;
|
||||
let lo_arg = lo_src.read_u64()?;
|
||||
let hi_arg = hi_src.read_u64()?;
|
||||
|
||||
context.sigmask = match how {
|
||||
SIG_BLOCK => {
|
||||
[old_lo | lo_arg, old_hi | hi_arg]
|
||||
},
|
||||
SIG_UNBLOCK => {
|
||||
[old_lo & !lo_arg, old_hi & !hi_arg]
|
||||
},
|
||||
SIG_SETMASK => {
|
||||
[lo_arg, hi_arg]
|
||||
},
|
||||
SIG_BLOCK => [old_lo | lo_arg, old_hi | hi_arg],
|
||||
SIG_UNBLOCK => [old_lo & !lo_arg, old_hi & !hi_arg],
|
||||
SIG_SETMASK => [lo_arg, hi_arg],
|
||||
_ => {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
@@ -382,19 +406,28 @@ fn reap(pid: ContextId) -> Result<ContextId> {
|
||||
}
|
||||
|
||||
let _ = context::contexts_mut()
|
||||
.remove(pid).ok_or(Error::new(ESRCH))?;
|
||||
.remove(pid)
|
||||
.ok_or(Error::new(ESRCH))?;
|
||||
|
||||
Ok(pid)
|
||||
}
|
||||
|
||||
pub fn waitpid(pid: ContextId, status_ptr: Option<UserSliceWo>, flags: WaitFlags) -> Result<ContextId> {
|
||||
pub fn waitpid(
|
||||
pid: ContextId,
|
||||
status_ptr: Option<UserSliceWo>,
|
||||
flags: WaitFlags,
|
||||
) -> Result<ContextId> {
|
||||
let (ppid, waitpid) = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
(context.id, Arc::clone(&context.waitpid))
|
||||
};
|
||||
let write_status = |value| status_ptr.map(|ptr| ptr.write_usize(value)).unwrap_or(Ok(()));
|
||||
let write_status = |value| {
|
||||
status_ptr
|
||||
.map(|ptr| ptr.write_usize(value))
|
||||
.unwrap_or(Ok(()))
|
||||
};
|
||||
|
||||
let grim_reaper = |w_pid: ContextId, status: usize| -> Option<Result<ContextId>> {
|
||||
if wifcontinued(status) {
|
||||
@@ -429,7 +462,7 @@ pub fn waitpid(pid: ContextId, status_ptr: Option<UserSliceWo>, flags: WaitFlags
|
||||
}
|
||||
}
|
||||
|
||||
if ! found {
|
||||
if !found {
|
||||
return Err(Error::new(ECHILD));
|
||||
}
|
||||
}
|
||||
@@ -460,7 +493,7 @@ pub fn waitpid(pid: ContextId, status_ptr: Option<UserSliceWo>, flags: WaitFlags
|
||||
}
|
||||
}
|
||||
|
||||
if ! found {
|
||||
if !found {
|
||||
return Err(Error::new(ECHILD));
|
||||
}
|
||||
}
|
||||
@@ -468,17 +501,20 @@ pub fn waitpid(pid: ContextId, status_ptr: Option<UserSliceWo>, flags: WaitFlags
|
||||
if flags & WNOHANG == WNOHANG {
|
||||
if let Some((w_pid, status)) = waitpid.receive_nonblock(&WaitpidKey {
|
||||
pid: None,
|
||||
pgid: Some(pgid)
|
||||
pgid: Some(pgid),
|
||||
}) {
|
||||
grim_reaper(w_pid, status)
|
||||
} else {
|
||||
Some(Ok(ContextId::from(0)))
|
||||
}
|
||||
} else {
|
||||
let (w_pid, status) = waitpid.receive(&WaitpidKey {
|
||||
pid: None,
|
||||
pgid: Some(pgid)
|
||||
}, "waitpid pgid");
|
||||
let (w_pid, status) = waitpid.receive(
|
||||
&WaitpidKey {
|
||||
pid: None,
|
||||
pgid: Some(pgid),
|
||||
},
|
||||
"waitpid pgid",
|
||||
);
|
||||
grim_reaper(w_pid, status)
|
||||
}
|
||||
} else {
|
||||
@@ -487,7 +523,12 @@ pub fn waitpid(pid: ContextId, status_ptr: Option<UserSliceWo>, flags: WaitFlags
|
||||
let context_lock = contexts.get(pid).ok_or(Error::new(ECHILD))?;
|
||||
let mut context = context_lock.write();
|
||||
if context.ppid != ppid {
|
||||
println!("TODO: Hack for rustc - changing ppid of {} from {} to {}", context.id.get(), context.ppid.get(), ppid.get());
|
||||
println!(
|
||||
"TODO: Hack for rustc - changing ppid of {} from {} to {}",
|
||||
context.id.get(),
|
||||
context.ppid.get(),
|
||||
ppid.get()
|
||||
);
|
||||
context.ppid = ppid;
|
||||
//return Err(Error::new(ECHILD));
|
||||
Some(context.status.clone())
|
||||
@@ -499,23 +540,26 @@ pub fn waitpid(pid: ContextId, status_ptr: Option<UserSliceWo>, flags: WaitFlags
|
||||
if let Some(context::Status::Exited(status)) = hack_status {
|
||||
let _ = waitpid.receive_nonblock(&WaitpidKey {
|
||||
pid: Some(pid),
|
||||
pgid: None
|
||||
pgid: None,
|
||||
});
|
||||
grim_reaper(pid, status)
|
||||
} else if flags & WNOHANG == WNOHANG {
|
||||
if let Some((w_pid, status)) = waitpid.receive_nonblock(&WaitpidKey {
|
||||
pid: Some(pid),
|
||||
pgid: None
|
||||
pgid: None,
|
||||
}) {
|
||||
grim_reaper(w_pid, status)
|
||||
} else {
|
||||
Some(Ok(ContextId::from(0)))
|
||||
}
|
||||
} else {
|
||||
let (w_pid, status) = waitpid.receive(&WaitpidKey {
|
||||
pid: Some(pid),
|
||||
pgid: None
|
||||
}, "waitpid pid");
|
||||
let (w_pid, status) = waitpid.receive(
|
||||
&WaitpidKey {
|
||||
pid: Some(pid),
|
||||
pgid: None,
|
||||
},
|
||||
"waitpid pid",
|
||||
);
|
||||
grim_reaper(w_pid, status)
|
||||
}
|
||||
};
|
||||
@@ -530,10 +574,14 @@ pub unsafe fn usermode_bootstrap(bootstrap: &Bootstrap) -> ! {
|
||||
assert_ne!(bootstrap.page_count, 0);
|
||||
|
||||
{
|
||||
let addr_space = Arc::clone(context::contexts().current()
|
||||
.expect("expected a context to exist when executing init")
|
||||
.read().addr_space()
|
||||
.expect("expected bootstrap context to have an address space"));
|
||||
let addr_space = Arc::clone(
|
||||
context::contexts()
|
||||
.current()
|
||||
.expect("expected a context to exist when executing init")
|
||||
.read()
|
||||
.addr_space()
|
||||
.expect("expected bootstrap context to have an address space"),
|
||||
);
|
||||
|
||||
// TODO: Use AddrSpace::mmap.
|
||||
let mut addr_space = addr_space.write();
|
||||
@@ -541,17 +589,19 @@ pub unsafe fn usermode_bootstrap(bootstrap: &Bootstrap) -> ! {
|
||||
|
||||
// TODO: Mark as owned and then support reclaiming the memory to the allocator if
|
||||
// deallocated?
|
||||
addr_space.grants.insert(context::memory::Grant::zeroed(
|
||||
PageSpan::new(
|
||||
Page::containing_address(VirtualAddress::new(0)),
|
||||
bootstrap.page_count,
|
||||
),
|
||||
PageFlags::new().user(true).write(true).execute(true),
|
||||
&mut addr_space.table.utable,
|
||||
PageFlushAll::new(),
|
||||
false, // is_shared
|
||||
).expect("failed to physmap bootstrap memory"));
|
||||
|
||||
addr_space.grants.insert(
|
||||
context::memory::Grant::zeroed(
|
||||
PageSpan::new(
|
||||
Page::containing_address(VirtualAddress::new(0)),
|
||||
bootstrap.page_count,
|
||||
),
|
||||
PageFlags::new().user(true).write(true).execute(true),
|
||||
&mut addr_space.table.utable,
|
||||
PageFlushAll::new(),
|
||||
false, // is_shared
|
||||
)
|
||||
.expect("failed to physmap bootstrap memory"),
|
||||
);
|
||||
}
|
||||
// TODO: Not all arches do linear mapping
|
||||
UserSliceWo::new(0, bootstrap.page_count * PAGE_SIZE)
|
||||
|
||||
+16
-8
@@ -1,8 +1,12 @@
|
||||
use crate::time;
|
||||
use crate::context;
|
||||
use crate::syscall::data::TimeSpec;
|
||||
use crate::syscall::error::*;
|
||||
use crate::syscall::flag::{CLOCK_REALTIME, CLOCK_MONOTONIC};
|
||||
use crate::{
|
||||
context,
|
||||
syscall::{
|
||||
data::TimeSpec,
|
||||
error::*,
|
||||
flag::{CLOCK_MONOTONIC, CLOCK_REALTIME},
|
||||
},
|
||||
time,
|
||||
};
|
||||
|
||||
use super::usercopy::{UserSliceRo, UserSliceWo};
|
||||
|
||||
@@ -10,7 +14,7 @@ pub fn clock_gettime(clock: usize, buf: UserSliceWo) -> Result<()> {
|
||||
let arch_time = match clock {
|
||||
CLOCK_REALTIME => time::realtime(),
|
||||
CLOCK_MONOTONIC => time::monotonic(),
|
||||
_ => return Err(Error::new(EINVAL))
|
||||
_ => return Err(Error::new(EINVAL)),
|
||||
};
|
||||
|
||||
buf.copy_exactly(&TimeSpec {
|
||||
@@ -38,7 +42,9 @@ pub fn nanosleep(req_buf: UserSliceRo, rem_buf_opt: Option<UserSliceWo>) -> Resu
|
||||
|
||||
//TODO: Find out wake reason
|
||||
loop {
|
||||
unsafe { context::switch(); }
|
||||
unsafe {
|
||||
context::switch();
|
||||
}
|
||||
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
@@ -71,6 +77,8 @@ pub fn nanosleep(req_buf: UserSliceRo, rem_buf_opt: Option<UserSliceWo>) -> Resu
|
||||
}
|
||||
|
||||
pub fn sched_yield() -> Result<()> {
|
||||
unsafe { context::switch(); }
|
||||
unsafe {
|
||||
context::switch();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+79
-31
@@ -1,9 +1,11 @@
|
||||
use crate::paging::{Page, VirtualAddress};
|
||||
use crate::memory::PAGE_SIZE;
|
||||
use crate::{
|
||||
memory::PAGE_SIZE,
|
||||
paging::{Page, VirtualAddress},
|
||||
};
|
||||
|
||||
use crate::arch::{arch_copy_to_user, arch_copy_from_user};
|
||||
use crate::arch::{arch_copy_from_user, arch_copy_to_user};
|
||||
|
||||
use crate::syscall::error::{Error, EINVAL, EFAULT, Result};
|
||||
use crate::syscall::error::{Error, Result, EFAULT, EINVAL};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct UserSlice<const READ: bool, const WRITE: bool> {
|
||||
@@ -16,10 +18,7 @@ pub type UserSliceRw = UserSlice<true, true>;
|
||||
|
||||
impl<const READ: bool, const WRITE: bool> UserSlice<READ, WRITE> {
|
||||
pub fn empty() -> Self {
|
||||
Self {
|
||||
base: 0,
|
||||
len: 0,
|
||||
}
|
||||
Self { base: 0, len: 0 }
|
||||
}
|
||||
pub fn len(&self) -> usize {
|
||||
self.len
|
||||
@@ -42,7 +41,16 @@ impl<const READ: bool, const WRITE: bool> UserSlice<READ, WRITE> {
|
||||
if idx > self.len {
|
||||
return None;
|
||||
}
|
||||
Some((Self { base: self.base, len: idx }, Self { base: self.base + idx, len: self.len - idx }))
|
||||
Some((
|
||||
Self {
|
||||
base: self.base,
|
||||
len: idx,
|
||||
},
|
||||
Self {
|
||||
base: self.base + idx,
|
||||
len: self.len - idx,
|
||||
},
|
||||
))
|
||||
}
|
||||
pub fn advance(self, by: usize) -> Option<Self> {
|
||||
Some(self.split_at(by)?.1)
|
||||
@@ -51,25 +59,35 @@ impl<const READ: bool, const WRITE: bool> UserSlice<READ, WRITE> {
|
||||
Some(self.split_at(to)?.0)
|
||||
}
|
||||
pub fn none_if_null(self) -> Option<Self> {
|
||||
if self.addr() == 0 { None } else { Some(self) }
|
||||
if self.addr() == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
/// Not unsafe, because user memory is not covered by the memory model that decides if
|
||||
/// something is UB, but it can break logic invariants
|
||||
pub fn reinterpret_unchecked<const NEW_READ: bool, const NEW_WRITE: bool>(self) -> UserSlice<NEW_READ, NEW_WRITE> {
|
||||
pub fn reinterpret_unchecked<const NEW_READ: bool, const NEW_WRITE: bool>(
|
||||
self,
|
||||
) -> UserSlice<NEW_READ, NEW_WRITE> {
|
||||
UserSlice {
|
||||
base: self.base,
|
||||
len: self.len,
|
||||
}
|
||||
}
|
||||
pub fn in_variable_chunks(self, chunk_size: usize) -> impl Iterator<Item = Self> {
|
||||
(0..self.len()).step_by(chunk_size).map(move |i| self.advance(i).expect("already limited by length, must succeed"))
|
||||
(0..self.len()).step_by(chunk_size).map(move |i| {
|
||||
self.advance(i)
|
||||
.expect("already limited by length, must succeed")
|
||||
})
|
||||
}
|
||||
pub fn in_exact_chunks(self, chunk_size: usize) -> impl Iterator<Item = Self> {
|
||||
(0..self.len().div_floor(chunk_size))
|
||||
.map(move |i| {
|
||||
self.advance(i * chunk_size).expect("already limited by length, must succeed")
|
||||
.limit(chunk_size).expect("length is aligned")
|
||||
})
|
||||
(0..self.len().div_floor(chunk_size)).map(move |i| {
|
||||
self.advance(i * chunk_size)
|
||||
.expect("already limited by length, must succeed")
|
||||
.limit(chunk_size)
|
||||
.expect("length is aligned")
|
||||
})
|
||||
}
|
||||
}
|
||||
impl<const WRITE: bool> UserSlice<true, WRITE> {
|
||||
@@ -88,35 +106,51 @@ impl<const WRITE: bool> UserSlice<true, WRITE> {
|
||||
}
|
||||
pub unsafe fn read_exact<T>(self) -> Result<T> {
|
||||
let mut t: T = core::mem::zeroed();
|
||||
let slice = unsafe { core::slice::from_raw_parts_mut((&mut t as *mut T).cast::<u8>(), core::mem::size_of::<T>()) };
|
||||
let slice = unsafe {
|
||||
core::slice::from_raw_parts_mut(
|
||||
(&mut t as *mut T).cast::<u8>(),
|
||||
core::mem::size_of::<T>(),
|
||||
)
|
||||
};
|
||||
|
||||
self.limit(core::mem::size_of::<T>()).ok_or(Error::new(EINVAL))?.copy_to_slice(slice)?;
|
||||
self.limit(core::mem::size_of::<T>())
|
||||
.ok_or(Error::new(EINVAL))?
|
||||
.copy_to_slice(slice)?;
|
||||
|
||||
Ok(t)
|
||||
}
|
||||
pub fn copy_common_bytes_to_slice(self, slice: &mut [u8]) -> Result<usize> {
|
||||
let min = core::cmp::min(self.len(), slice.len());
|
||||
self.limit(min).expect("min(len, x) is always <= len").copy_to_slice(&mut slice[..min])?;
|
||||
self.limit(min)
|
||||
.expect("min(len, x) is always <= len")
|
||||
.copy_to_slice(&mut slice[..min])?;
|
||||
Ok(min)
|
||||
}
|
||||
// TODO: Merge int IO functions?
|
||||
pub fn read_usize(self) -> Result<usize> {
|
||||
let mut ret = 0_usize.to_ne_bytes();
|
||||
self.limit(core::mem::size_of::<usize>()).ok_or(Error::new(EINVAL))?.copy_to_slice(&mut ret)?;
|
||||
self.limit(core::mem::size_of::<usize>())
|
||||
.ok_or(Error::new(EINVAL))?
|
||||
.copy_to_slice(&mut ret)?;
|
||||
Ok(usize::from_ne_bytes(ret))
|
||||
}
|
||||
pub fn read_u32(self) -> Result<u32> {
|
||||
let mut ret = 0_u32.to_ne_bytes();
|
||||
self.limit(4).ok_or(Error::new(EINVAL))?.copy_to_slice(&mut ret)?;
|
||||
self.limit(4)
|
||||
.ok_or(Error::new(EINVAL))?
|
||||
.copy_to_slice(&mut ret)?;
|
||||
Ok(u32::from_ne_bytes(ret))
|
||||
}
|
||||
pub fn read_u64(self) -> Result<u64> {
|
||||
let mut ret = 0_u64.to_ne_bytes();
|
||||
self.limit(8).ok_or(Error::new(EINVAL))?.copy_to_slice(&mut ret)?;
|
||||
self.limit(8)
|
||||
.ok_or(Error::new(EINVAL))?
|
||||
.copy_to_slice(&mut ret)?;
|
||||
Ok(u64::from_ne_bytes(ret))
|
||||
}
|
||||
pub fn usizes(self) -> impl Iterator<Item = Result<usize>> {
|
||||
self.in_exact_chunks(core::mem::size_of::<usize>()).map(Self::read_usize)
|
||||
self.in_exact_chunks(core::mem::size_of::<usize>())
|
||||
.map(Self::read_usize)
|
||||
}
|
||||
}
|
||||
impl<const READ: bool> UserSlice<READ, true> {
|
||||
@@ -135,23 +169,33 @@ impl<const READ: bool> UserSlice<READ, true> {
|
||||
}
|
||||
pub fn copy_common_bytes_from_slice(self, slice: &[u8]) -> Result<usize> {
|
||||
let min = core::cmp::min(self.len(), slice.len());
|
||||
self.limit(min).expect("min(len, x) is always <= len").copy_from_slice(&slice[..min])?;
|
||||
self.limit(min)
|
||||
.expect("min(len, x) is always <= len")
|
||||
.copy_from_slice(&slice[..min])?;
|
||||
Ok(min)
|
||||
}
|
||||
pub fn copy_exactly(self, slice: &[u8]) -> Result<()> {
|
||||
self.limit(slice.len()).ok_or(Error::new(EINVAL))?.copy_from_slice(slice)?;
|
||||
self.limit(slice.len())
|
||||
.ok_or(Error::new(EINVAL))?
|
||||
.copy_from_slice(slice)?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn write_usize(self, word: usize) -> Result<()> {
|
||||
self.limit(core::mem::size_of::<usize>()).ok_or(Error::new(EINVAL))?.copy_from_slice(&word.to_ne_bytes())?;
|
||||
self.limit(core::mem::size_of::<usize>())
|
||||
.ok_or(Error::new(EINVAL))?
|
||||
.copy_from_slice(&word.to_ne_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn write_u32(self, int: u32) -> Result<()> {
|
||||
self.limit(core::mem::size_of::<u32>()).ok_or(Error::new(EINVAL))?.copy_from_slice(&int.to_ne_bytes())?;
|
||||
self.limit(core::mem::size_of::<u32>())
|
||||
.ok_or(Error::new(EINVAL))?
|
||||
.copy_from_slice(&int.to_ne_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn write_u64(self, int: u64) -> Result<()> {
|
||||
self.limit(core::mem::size_of::<u64>()).ok_or(Error::new(EINVAL))?.copy_from_slice(&int.to_ne_bytes())?;
|
||||
self.limit(core::mem::size_of::<u64>())
|
||||
.ok_or(Error::new(EINVAL))?
|
||||
.copy_from_slice(&int.to_ne_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -173,7 +217,8 @@ impl UserSliceRw {
|
||||
}
|
||||
|
||||
fn is_kernel_mem(slice: &[u8]) -> bool {
|
||||
(slice.as_ptr() as usize) >= crate::USER_END_OFFSET && (slice.as_ptr() as usize).checked_add(slice.len()).is_some()
|
||||
(slice.as_ptr() as usize) >= crate::USER_END_OFFSET
|
||||
&& (slice.as_ptr() as usize).checked_add(slice.len()).is_some()
|
||||
}
|
||||
|
||||
/// Convert `[addr, addr+size)` into `(page, page_count)`.
|
||||
@@ -192,5 +237,8 @@ pub fn validate_region(address: usize, size: usize) -> Result<(Page, usize)> {
|
||||
if address.saturating_add(size) > crate::USER_END_OFFSET {
|
||||
return Err(Error::new(EFAULT));
|
||||
}
|
||||
Ok((Page::containing_address(VirtualAddress::new(address)), size / PAGE_SIZE))
|
||||
Ok((
|
||||
Page::containing_address(VirtualAddress::new(address)),
|
||||
size / PAGE_SIZE,
|
||||
))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user