WIP: continue the process transition
This commit is contained in:
+8
-45
@@ -27,7 +27,7 @@ use ::core::sync::atomic::AtomicUsize;
|
||||
|
||||
use super::{
|
||||
empty_cr3,
|
||||
memory::{AddrSpaceWrapper, GrantFileRef},
|
||||
memory::{AddrSpaceWrapper, GrantFileRef}, process::{Process, ProcessId},
|
||||
};
|
||||
int_like!(ContextId, AtomicContextId, usize, AtomicUsize);
|
||||
|
||||
@@ -71,8 +71,8 @@ pub enum HardBlockedReason {
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct WaitpidKey {
|
||||
pub pid: Option<ContextId>,
|
||||
pub pgid: Option<ContextId>,
|
||||
pub pid: Option<ProcessId>,
|
||||
pub pgid: Option<ProcessId>,
|
||||
}
|
||||
|
||||
impl Ord for WaitpidKey {
|
||||
@@ -134,31 +134,11 @@ pub struct Context {
|
||||
/// The internal context ID of this context
|
||||
pub cid: ContextId,
|
||||
/// The process ID of this context
|
||||
pub pid: ContextId,
|
||||
/// The group ID of this context
|
||||
pub pgid: ContextId,
|
||||
/// The ID of the parent context
|
||||
pub ppid: ContextId,
|
||||
/// The ID of the session
|
||||
pub session_id: ContextId,
|
||||
/// The real user id
|
||||
pub ruid: u32,
|
||||
/// The real group id
|
||||
pub rgid: u32,
|
||||
/// The real namespace id
|
||||
pub rns: SchemeNamespace,
|
||||
/// The effective user id
|
||||
pub euid: u32,
|
||||
/// The effective group id
|
||||
pub egid: u32,
|
||||
/// The effective namespace id
|
||||
pub ens: SchemeNamespace,
|
||||
|
||||
pub pid: ProcessId,
|
||||
/// Process state shared with other threads
|
||||
pub process: Arc<RwLock<Process>>,
|
||||
/// Signal handler
|
||||
pub sig: Option<SignalState>,
|
||||
|
||||
/// Process umask
|
||||
pub umask: usize,
|
||||
/// Status of context
|
||||
pub status: Status,
|
||||
pub status_reason: &'static str,
|
||||
@@ -186,8 +166,6 @@ pub struct Context {
|
||||
/// Tail buffer to use when system call buffers are not page aligned
|
||||
// TODO: Store in user memory?
|
||||
pub syscall_tail: Option<RaiiFrame>,
|
||||
/// Context is being waited on
|
||||
pub waitpid: Arc<WaitMap<WaitpidKey, (ContextId, usize)>>,
|
||||
/// Context should wake up at specified time
|
||||
pub wake: Option<u128>,
|
||||
/// The architecture specific context
|
||||
@@ -209,10 +187,6 @@ pub struct Context {
|
||||
/// All contexts except kmain will primarily live in userspace, and enter the kernel only when
|
||||
/// interrupts or syscalls occur. This flag is set for all contexts but kmain.
|
||||
pub userspace: bool,
|
||||
/// A somewhat hacky way to initially stop a context when creating
|
||||
/// a new instance of the proc: scheme, entirely separate from
|
||||
/// signals or any other way to restart a process.
|
||||
pub ptrace_stop: bool,
|
||||
pub being_sigkilled: bool,
|
||||
pub fmap_ret: Option<Frame>,
|
||||
}
|
||||
@@ -233,21 +207,12 @@ pub struct SignalState {
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn new(cid: ContextId, pid: ContextId) -> Result<Context> {
|
||||
pub fn new(cid: ContextId, pid: ContextId, process: Arc<RwLock<Process>>) -> Result<Context> {
|
||||
let this = Context {
|
||||
cid,
|
||||
pid,
|
||||
pgid: pid,
|
||||
ppid: ContextId::from(0),
|
||||
session_id: ContextId::from(0),
|
||||
ruid: 0,
|
||||
rgid: 0,
|
||||
rns: SchemeNamespace::from(0),
|
||||
euid: 0,
|
||||
egid: 0,
|
||||
ens: SchemeNamespace::from(0),
|
||||
process,
|
||||
sig: None,
|
||||
umask: 0o022,
|
||||
status: Status::HardBlocked {
|
||||
reason: HardBlockedReason::NotYetStarted,
|
||||
},
|
||||
@@ -260,7 +225,6 @@ impl Context {
|
||||
inside_syscall: false,
|
||||
syscall_head: Some(RaiiFrame::allocate()?),
|
||||
syscall_tail: Some(RaiiFrame::allocate()?),
|
||||
waitpid: Arc::new(WaitMap::new()),
|
||||
wake: None,
|
||||
arch: arch::Context::new(),
|
||||
kfx: AlignedBox::<[u8], { arch::KFX_ALIGN }>::try_zeroed_slice(crate::arch::kfx_size())?,
|
||||
@@ -269,7 +233,6 @@ impl Context {
|
||||
name: Cow::Borrowed(""),
|
||||
files: Arc::new(RwLock::new(Vec::new())),
|
||||
userspace: false,
|
||||
ptrace_stop: false,
|
||||
fmap_ret: None,
|
||||
being_sigkilled: false,
|
||||
|
||||
|
||||
@@ -33,21 +33,6 @@ impl ContextList {
|
||||
self.map.get(&id)
|
||||
}
|
||||
|
||||
/// Get an iterator of all parents
|
||||
pub fn ancestors(
|
||||
&'_ self,
|
||||
id: ContextId,
|
||||
) -> impl Iterator<Item = (ContextId, &Arc<RwSpinlock<Context>>)> + '_ {
|
||||
iter::successors(
|
||||
self.get(id).map(|context| (id, context)),
|
||||
move |(_id, context)| {
|
||||
let context = context.read();
|
||||
let id = context.ppid;
|
||||
self.get(id).map(|context| (id, context))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Get the current context.
|
||||
pub fn current(&self) -> Option<&Arc<RwSpinlock<Context>>> {
|
||||
self.map.get(&super::current_cid())
|
||||
|
||||
@@ -14,6 +14,7 @@ use crate::{
|
||||
syscall::error::{Error, Result, ESRCH},
|
||||
};
|
||||
|
||||
use self::process::ProcessId;
|
||||
pub use self::{
|
||||
context::{BorrowedHtBuf, Context, ContextId, Status, WaitpidKey},
|
||||
list::ContextList,
|
||||
@@ -47,6 +48,9 @@ pub mod file;
|
||||
/// Memory struct - contains a set of pages for a context
|
||||
pub mod memory;
|
||||
|
||||
/// Process handling - TODO move to userspace
|
||||
pub mod process;
|
||||
|
||||
/// Signal handling
|
||||
pub mod signal;
|
||||
|
||||
@@ -103,6 +107,9 @@ pub fn contexts_mut() -> RwLockWriteGuard<'static, ContextList> {
|
||||
pub fn current_cid() -> ContextId {
|
||||
PercpuBlock::current().switch_internals.current_cid()
|
||||
}
|
||||
pub fn current_pid() -> Result<ProcessId> {
|
||||
Ok(current()?.read().pid)
|
||||
}
|
||||
|
||||
pub fn current() -> Result<Arc<RwSpinlock<Context>>> {
|
||||
contexts()
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
// TODO: move all this code to userspace
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::sync::{Arc, Weak};
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use spin::RwLock;
|
||||
use spinning_top::RwSpinlock;
|
||||
|
||||
use syscall::{Error, Result, ESRCH};
|
||||
|
||||
use crate::scheme::SchemeNamespace;
|
||||
use crate::sync::WaitMap;
|
||||
|
||||
use crate::context::{self, Context, WaitpidKey};
|
||||
|
||||
int_like!(ProcessId, usize);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Process {
|
||||
/// The process ID of this process
|
||||
pub pid: ProcessId,
|
||||
/// The group ID of this process
|
||||
pub pgid: ProcessId,
|
||||
/// The ID of the parent process
|
||||
pub ppid: ProcessId,
|
||||
/// The ID of the session
|
||||
pub session_id: ProcessId,
|
||||
/// The real user id
|
||||
pub ruid: u32,
|
||||
/// The real group id
|
||||
pub rgid: u32,
|
||||
/// The real namespace id
|
||||
pub rns: SchemeNamespace,
|
||||
/// The effective user id
|
||||
pub euid: u32,
|
||||
/// The effective group id
|
||||
pub egid: u32,
|
||||
/// The effective namespace id
|
||||
pub ens: SchemeNamespace,
|
||||
/// Process umask
|
||||
pub umask: usize,
|
||||
/// Context is being waited on
|
||||
pub waitpid: WaitMap<WaitpidKey, (ProcessId, usize)>,
|
||||
pub threads: Vec<Weak<RwSpinlock<Context>>>,
|
||||
}
|
||||
|
||||
pub static PROCESSES: RwLock<BTreeMap<ProcessId, Arc<RwLock<Process>>>> = RwLock::new(BTreeMap::new());
|
||||
|
||||
/// Get an iterator of all parents
|
||||
pub fn ancestors(
|
||||
list: &BTreeSet<Process>,
|
||||
id: ProcessId,
|
||||
) -> impl Iterator<Item = (ProcessId, &Arc<RwSpinlock<Context>>)> + '_ {
|
||||
core::iter::successors(
|
||||
list.get(&id).map(|process| (id, process)),
|
||||
move |(_id, process)| {
|
||||
let context = process.read();
|
||||
let id = process.ppid;
|
||||
list.get(&id).map(|context| (id, context))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
impl Ord for Process {
|
||||
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
|
||||
Ord::cmp(&self.pid, &other.pid)
|
||||
}
|
||||
}
|
||||
impl PartialOrd for Process {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
|
||||
Some(Ord::cmp(&self.pid, &other.pid))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current() -> Result<Arc<RwLock<Process>>> {
|
||||
let pid = context::current()?.read().pid;
|
||||
PROCESSES.read().get(&pid).ok_or(Error::new(ESRCH))
|
||||
}
|
||||
impl PartialEq for Process {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
Ord::cmp(self, other) == core::cmp::Ordering::Equal
|
||||
}
|
||||
}
|
||||
impl Eq for Process {}
|
||||
@@ -131,7 +131,7 @@ pub fn switch() -> SwitchResult {
|
||||
let mut skip_idle = true;
|
||||
|
||||
// Locate next context
|
||||
for (pid, next_context_lock) in contexts
|
||||
for (cid, next_context_lock) in contexts
|
||||
// Include all contexts with IDs greater than the current...
|
||||
.range((Bound::Excluded(prev_context_guard.cid), Bound::Unbounded))
|
||||
.chain(
|
||||
@@ -146,7 +146,7 @@ pub fn switch() -> SwitchResult {
|
||||
)
|
||||
// ... but not the current context, which is already locked
|
||||
{
|
||||
if pid == &idle_id && skip_idle {
|
||||
if cid == &idle_id && skip_idle {
|
||||
// Skip idle process the first time it shows up
|
||||
skip_idle = false;
|
||||
continue;
|
||||
@@ -201,7 +201,7 @@ pub fn switch() -> SwitchResult {
|
||||
}));
|
||||
|
||||
let (ptrace_session, ptrace_flags) = if let Some((session, bp)) = ptrace::sessions()
|
||||
.get(&next_context.pid)
|
||||
.get(&next_context.cid)
|
||||
.map(|s| (Arc::downgrade(s), s.data.lock().breakpoint))
|
||||
{
|
||||
(Some(session), bp.map_or(PtraceFlags::empty(), |f| f.flags))
|
||||
|
||||
+4
-2
@@ -200,10 +200,12 @@ fn kmain(cpu_count: u32, bootstrap: Bootstrap) -> ! {
|
||||
match context::contexts_mut().spawn(true, userspace_init) {
|
||||
Ok(context_lock) => {
|
||||
let mut context = context_lock.write();
|
||||
context.rns = SchemeNamespace::from(1);
|
||||
context.ens = SchemeNamespace::from(1);
|
||||
context.status = context::Status::Runnable;
|
||||
context.name = "bootstrap".into();
|
||||
|
||||
let mut process = context.process.write();
|
||||
process.rns = SchemeNamespace::from(1);
|
||||
process.ens = SchemeNamespace::from(1);
|
||||
}
|
||||
Err(err) => {
|
||||
panic!("failed to spawn userspace_init: {:?}", err);
|
||||
|
||||
+8
-8
@@ -7,7 +7,7 @@ use crate::{
|
||||
context::{
|
||||
self,
|
||||
file::{FileDescription, FileDescriptor, InternalFlags},
|
||||
memory::{AddrSpace, PageSpan},
|
||||
memory::{AddrSpace, PageSpan}, process,
|
||||
},
|
||||
paging::{Page, VirtualAddress, PAGE_SIZE},
|
||||
scheme::{self, CallerCtx, FileHandle, KernelScheme, OpenResult},
|
||||
@@ -54,13 +54,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.pid.into(),
|
||||
context.euid,
|
||||
context.egid,
|
||||
context.ens,
|
||||
context.umask,
|
||||
let (pid, uid, gid, scheme_ns, umask) = match process::current()?.read() {
|
||||
ref process => (
|
||||
process.pid.into(),
|
||||
process.euid,
|
||||
process.egid,
|
||||
process.ens,
|
||||
process.umask,
|
||||
),
|
||||
};
|
||||
|
||||
|
||||
+11
-11
@@ -25,7 +25,7 @@ use self::{
|
||||
use crate::{interrupt::InterruptStack, percpu::PercpuBlock};
|
||||
|
||||
use crate::{
|
||||
context::{memory::AddrSpace, ContextId},
|
||||
context::{memory::AddrSpace, process::ProcessId},
|
||||
scheme::{memory::MemoryScheme, FileHandle, SchemeNamespace},
|
||||
};
|
||||
|
||||
@@ -205,14 +205,14 @@ pub fn syscall(
|
||||
.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),
|
||||
SYS_GETPPID => getppid().map(ContextId::into),
|
||||
SYS_GETPID => getpid().map(ProcessId::into),
|
||||
SYS_GETPGID => getpgid(ProcessId::from(b)).map(ProcessId::into),
|
||||
SYS_GETPPID => getppid().map(ProcessId::into),
|
||||
|
||||
SYS_EXIT => exit(b),
|
||||
SYS_KILL => kill(ContextId::from(b), c, false),
|
||||
SYS_KILL => kill(ProcessId::from(b), c, false),
|
||||
SYS_WAITPID => waitpid(
|
||||
ContextId::from(b),
|
||||
ProcessId::from(b),
|
||||
if c == 0 {
|
||||
None
|
||||
} else {
|
||||
@@ -220,7 +220,7 @@ pub fn syscall(
|
||||
},
|
||||
WaitFlags::from_bits_truncate(d),
|
||||
)
|
||||
.map(ContextId::into),
|
||||
.map(ProcessId::into),
|
||||
SYS_IOPL => iopl(b),
|
||||
SYS_GETEGID => getegid(),
|
||||
SYS_GETENS => getens(),
|
||||
@@ -234,10 +234,10 @@ pub fn syscall(
|
||||
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)),
|
||||
SYS_SETREGID => setregid(b as u32, c as u32),
|
||||
SYS_SETPGID => setpgid(ProcessId::from(b), ProcessId::from(c)).map(|()| 0),
|
||||
SYS_SETREUID => setreuid(b as u32, c as u32).map(|()| 0),
|
||||
SYS_SETRENS => setrens(SchemeNamespace::from(b), SchemeNamespace::from(c)).map(|()| 0),
|
||||
SYS_SETREGID => setregid(b as u32, c as u32).map(|()| 0),
|
||||
SYS_UMASK => umask(b),
|
||||
SYS_VIRTTOPHYS => virttophys(b),
|
||||
|
||||
|
||||
+47
-68
@@ -1,7 +1,7 @@
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::{
|
||||
context,
|
||||
context::{self, process},
|
||||
scheme::{self, SchemeNamespace},
|
||||
syscall::error::*,
|
||||
};
|
||||
@@ -12,50 +12,32 @@ use super::{
|
||||
};
|
||||
|
||||
pub fn getegid() -> Result<usize> {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
Ok(context.egid as usize)
|
||||
Ok(process::current()?.read().egid as usize)
|
||||
}
|
||||
|
||||
pub fn getens() -> Result<usize> {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
Ok(context.ens.into())
|
||||
Ok(process::current()?.read().ens.into())
|
||||
}
|
||||
|
||||
pub fn geteuid() -> Result<usize> {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
Ok(context.euid as usize)
|
||||
Ok(process::current()?.read().euid as usize)
|
||||
}
|
||||
|
||||
pub fn getgid() -> Result<usize> {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
Ok(context.rgid as usize)
|
||||
Ok(process::current()?.read().rgid as usize)
|
||||
}
|
||||
|
||||
pub fn getns() -> Result<usize> {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
Ok(context.rns.into())
|
||||
Ok(process::current()?.read().rns.into())
|
||||
}
|
||||
|
||||
pub fn getuid() -> Result<usize> {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
Ok(context.ruid as usize)
|
||||
Ok(process::current()?.read().ruid as usize)
|
||||
}
|
||||
|
||||
pub fn mkns(mut user_buf: UserSliceRo) -> Result<usize> {
|
||||
let (uid, from) = match context::current()?.read() {
|
||||
ref context => (context.euid, context.ens),
|
||||
let (uid, from) = match process::current()?.read() {
|
||||
ref process => (process.euid, process.ens),
|
||||
};
|
||||
|
||||
// TODO: Lift this restriction later?
|
||||
@@ -86,18 +68,17 @@ pub fn mkns(mut user_buf: UserSliceRo) -> Result<usize> {
|
||||
Ok(to.into())
|
||||
}
|
||||
|
||||
pub fn setregid(rgid: u32, egid: u32) -> Result<usize> {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let mut context = context_lock.write();
|
||||
pub fn setregid(rgid: u32, egid: u32) -> Result<()> {
|
||||
let process_lock = process::current()?;
|
||||
let mut process = process_lock.write();
|
||||
|
||||
let setrgid = if context.euid == 0 {
|
||||
let setrgid = if process.euid == 0 {
|
||||
// Allow changing RGID if root
|
||||
true
|
||||
} else if rgid == context.egid {
|
||||
} else if rgid == process.egid {
|
||||
// Allow changing RGID if used for EGID
|
||||
true
|
||||
} else if rgid == context.rgid {
|
||||
} else if rgid == process.rgid {
|
||||
// Allow changing RGID if used for RGID
|
||||
true
|
||||
} else if rgid as i32 == -1 {
|
||||
@@ -108,13 +89,13 @@ pub fn setregid(rgid: u32, egid: u32) -> Result<usize> {
|
||||
return Err(Error::new(EPERM));
|
||||
};
|
||||
|
||||
let setegid = if context.euid == 0 {
|
||||
let setegid = if process.euid == 0 {
|
||||
// Allow changing EGID if root
|
||||
true
|
||||
} else if egid == context.egid {
|
||||
} else if egid == process.egid {
|
||||
// Allow changing EGID if used for EGID
|
||||
true
|
||||
} else if egid == context.rgid {
|
||||
} else if egid == process.rgid {
|
||||
// Allow changing EGID if used for RGID
|
||||
true
|
||||
} else if egid as i32 == -1 {
|
||||
@@ -126,20 +107,19 @@ pub fn setregid(rgid: u32, egid: u32) -> Result<usize> {
|
||||
};
|
||||
|
||||
if setrgid {
|
||||
context.rgid = rgid;
|
||||
process.rgid = rgid;
|
||||
}
|
||||
|
||||
if setegid {
|
||||
context.egid = egid;
|
||||
process.egid = egid;
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result<usize> {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let mut context = context_lock.write();
|
||||
pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result<()> {
|
||||
let process_lock = process::current()?;
|
||||
let mut process = process_lock.write();
|
||||
|
||||
let setrns = if rns.get() as isize == -1 {
|
||||
// Ignore RNS if -1 is passed
|
||||
@@ -147,16 +127,16 @@ pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result<usize> {
|
||||
} else if rns.get() == 0 {
|
||||
// Allow entering capability mode
|
||||
true
|
||||
} else if context.rns.get() == 0 {
|
||||
} else if process.rns.get() == 0 {
|
||||
// Do not allow leaving capability mode
|
||||
return Err(Error::new(EPERM));
|
||||
} else if context.euid == 0 {
|
||||
} else if process.euid == 0 {
|
||||
// Allow setting RNS if root
|
||||
true
|
||||
} else if rns == context.ens {
|
||||
} else if rns == process.ens {
|
||||
// Allow setting RNS if used for ENS
|
||||
true
|
||||
} else if rns == context.rns {
|
||||
} else if rns == process.rns {
|
||||
// Allow setting RNS if used for RNS
|
||||
true
|
||||
} else {
|
||||
@@ -170,16 +150,16 @@ pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result<usize> {
|
||||
} else if ens.get() == 0 {
|
||||
// Allow entering capability mode
|
||||
true
|
||||
} else if context.ens.get() == 0 {
|
||||
} else if process.ens.get() == 0 {
|
||||
// Do not allow leaving capability mode
|
||||
return Err(Error::new(EPERM));
|
||||
} else if context.euid == 0 {
|
||||
} else if process.euid == 0 {
|
||||
// Allow setting ENS if root
|
||||
true
|
||||
} else if ens == context.ens {
|
||||
} else if ens == process.ens {
|
||||
// Allow setting ENS if used for ENS
|
||||
true
|
||||
} else if ens == context.rns {
|
||||
} else if ens == process.rns {
|
||||
// Allow setting ENS if used for RNS
|
||||
true
|
||||
} else {
|
||||
@@ -189,29 +169,28 @@ pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result<usize> {
|
||||
|
||||
if setrns {
|
||||
assert_ne!(rns.get() as isize, -1);
|
||||
context.rns = rns;
|
||||
process.rns = rns;
|
||||
}
|
||||
|
||||
if setens {
|
||||
assert_ne!(ens.get() as isize, -1);
|
||||
context.ens = ens;
|
||||
process.ens = ens;
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn setreuid(ruid: u32, euid: u32) -> Result<usize> {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let mut context = context_lock.write();
|
||||
pub fn setreuid(ruid: u32, euid: u32) -> Result<()> {
|
||||
let process_lock = process::current()?;
|
||||
let mut process = process_lock.write();
|
||||
|
||||
let setruid = if context.euid == 0 {
|
||||
let setruid = if process.euid == 0 {
|
||||
// Allow setting RUID if root
|
||||
true
|
||||
} else if ruid == context.euid {
|
||||
} else if ruid == process.euid {
|
||||
// Allow setting RUID if used for EUID
|
||||
true
|
||||
} else if ruid == context.ruid {
|
||||
} else if ruid == process.ruid {
|
||||
// Allow setting RUID if used for RUID
|
||||
true
|
||||
} else if ruid as i32 == -1 {
|
||||
@@ -222,13 +201,13 @@ pub fn setreuid(ruid: u32, euid: u32) -> Result<usize> {
|
||||
return Err(Error::new(EPERM));
|
||||
};
|
||||
|
||||
let seteuid = if context.euid == 0 {
|
||||
let seteuid = if process.euid == 0 {
|
||||
// Allow setting EUID if root
|
||||
true
|
||||
} else if euid == context.euid {
|
||||
} else if euid == process.euid {
|
||||
// Allow setting EUID if used for EUID
|
||||
true
|
||||
} else if euid == context.ruid {
|
||||
} else if euid == process.ruid {
|
||||
// Allow setting EUID if used for RUID
|
||||
true
|
||||
} else if euid as i32 == -1 {
|
||||
@@ -240,12 +219,12 @@ pub fn setreuid(ruid: u32, euid: u32) -> Result<usize> {
|
||||
};
|
||||
|
||||
if setruid {
|
||||
context.ruid = ruid;
|
||||
process.ruid = ruid;
|
||||
}
|
||||
|
||||
if seteuid {
|
||||
context.euid = euid;
|
||||
process.euid = euid;
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+96
-102
@@ -6,8 +6,7 @@ use rmm::Arch;
|
||||
use spin::RwLock;
|
||||
|
||||
use crate::context::{
|
||||
memory::{AddrSpace, Grant, PageSpan},
|
||||
ContextId, WaitpidKey,
|
||||
memory::{AddrSpace, Grant, PageSpan}, process::{self, ProcessId}, WaitpidKey
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -62,17 +61,18 @@ pub fn exit(status: usize) -> ! {
|
||||
// PGID and PPID must be grabbed after close, as context switches could change PGID or PPID if parent exits
|
||||
let (pgid, ppid) = {
|
||||
let context = context_lock.read();
|
||||
(context.pgid, context.ppid)
|
||||
let process = context.process.read();
|
||||
(process.pgid, process.ppid)
|
||||
};
|
||||
let _ = kill(ppid, SIGCHLD, true);
|
||||
|
||||
// Transfer child processes to parent
|
||||
// Transfer child processes to parent (TODO: init)
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
for (_id, context_lock) in contexts.iter() {
|
||||
let mut context = context_lock.write();
|
||||
if context.ppid == pid {
|
||||
context.ppid = ppid;
|
||||
let processes = context::process::PROCESSES.read();
|
||||
for (pid, process_lock) in processes.iter() {
|
||||
let mut process = process_lock.write();
|
||||
if process.ppid == pid {
|
||||
process.ppid = ppid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,37 +113,32 @@ pub fn exit(status: usize) -> ! {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
pub fn getpid() -> Result<ContextId> {
|
||||
Ok(context::current()?.read().pid)
|
||||
pub fn getpid() -> Result<ProcessId> {
|
||||
context::current_pid()
|
||||
}
|
||||
|
||||
pub fn getpgid(pid: ContextId) -> Result<ContextId> {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = if pid.get() == 0 {
|
||||
contexts.current().ok_or(Error::new(ESRCH))?
|
||||
pub fn getpgid(pid: ProcessId) -> Result<ProcessId> {
|
||||
let process_lock = if pid.get() == 0 {
|
||||
process::current()?
|
||||
} else {
|
||||
contexts.get(pid).ok_or(Error::new(ESRCH))?
|
||||
Arc::clone(process::PROCESSES.get(&pid).ok_or(Error::new(ESRCH))?)
|
||||
};
|
||||
let context = context_lock.read();
|
||||
Ok(context.pgid)
|
||||
let process = process_lock.read();
|
||||
Ok(process.pgid)
|
||||
}
|
||||
|
||||
pub fn getppid() -> Result<ContextId> {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
Ok(context.ppid)
|
||||
pub fn getppid() -> Result<ProcessId> {
|
||||
Ok(process::current()?.read().ppid)
|
||||
}
|
||||
|
||||
pub fn kill(pid: ContextId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
let (ruid, euid, current_pgid) = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
(context.ruid, context.euid, context.pgid)
|
||||
let process_lock = process::current?;
|
||||
let process = process_lock.read();
|
||||
(process.ruid, process.euid, process.pgid)
|
||||
};
|
||||
|
||||
if euid == 0 && pid == ContextId::new(1) {
|
||||
if euid == 0 && pid.get() == 1 {
|
||||
match sig {
|
||||
SIGTERM => unsafe { crate::stop::kreset() },
|
||||
SIGKILL => unsafe { crate::stop::kstop() },
|
||||
@@ -161,19 +156,19 @@ pub fn kill(pid: ContextId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
let mut killed_self = false;
|
||||
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
let processes = process::PROCESSES.read();
|
||||
|
||||
enum SendResult {
|
||||
Forbidden,
|
||||
Succeeded,
|
||||
SucceededSigchld {
|
||||
ppid: ContextId,
|
||||
pgid: ContextId,
|
||||
ppid: ProcessId,
|
||||
pgid: ProcessId,
|
||||
orig_signal: usize,
|
||||
},
|
||||
SucceededSigcont {
|
||||
ppid: ContextId,
|
||||
pgid: ContextId,
|
||||
ppid: ProcessId,
|
||||
pgid: ProcessId,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -264,8 +259,8 @@ pub fn kill(pid: ContextId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
} => {
|
||||
sent += 1;
|
||||
let waitpid = Arc::clone(
|
||||
&context::contexts()
|
||||
.get(ppid)
|
||||
&process::PROCESSES.read()
|
||||
.get(&ppid)
|
||||
.ok_or(Error::new(ESRCH))?
|
||||
.read()
|
||||
.waitpid,
|
||||
@@ -282,8 +277,8 @@ pub fn kill(pid: ContextId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
SendResult::SucceededSigcont { ppid, pgid } => {
|
||||
sent += 1;
|
||||
let waitpid = Arc::clone(
|
||||
&context::contexts()
|
||||
.get(ppid)
|
||||
&process::PROCESSES.read()
|
||||
.get(&ppid)
|
||||
.ok_or(Error::new(ESRCH))?
|
||||
.read()
|
||||
.waitpid,
|
||||
@@ -302,20 +297,22 @@ pub fn kill(pid: ContextId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
|
||||
if pid.get() as isize > 0 {
|
||||
// Send to a single process
|
||||
if let Some(context_lock) = contexts.get(pid) {
|
||||
if let Some(process_lock) = processes.get(&pid) {
|
||||
found += 1;
|
||||
let result = send(&mut *context_lock.write());
|
||||
let result = send(&mut *process_lock.write());
|
||||
handle_send(pid, result)?;
|
||||
}
|
||||
} else if pid.get() == 1_usize.wrapping_neg() {
|
||||
// Send to every process with permission, except for init
|
||||
for (pid, context_lock) in contexts.iter() {
|
||||
let mut context = context_lock.write();
|
||||
for (pid, process_lock) in processes.iter() {
|
||||
let mut process = process_lock.write();
|
||||
|
||||
if context.pid.get() <= 2 {
|
||||
if process.pid.get() <= 2 {
|
||||
continue;
|
||||
}
|
||||
found += 1;
|
||||
let context_lock = process.threads.first().ok_or(Error::new(ESRCH))?.upgrade().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.write();
|
||||
|
||||
let result = send(&mut *context);
|
||||
drop(context);
|
||||
@@ -325,12 +322,12 @@ pub fn kill(pid: ContextId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
let pgid = if pid.get() == 0 {
|
||||
current_pgid
|
||||
} else {
|
||||
ContextId::from(pid.get().wrapping_neg())
|
||||
ProcessId::from(pid.get().wrapping_neg())
|
||||
};
|
||||
|
||||
// Send to every process in the process group whose ID
|
||||
for (pid, context_lock) in contexts.iter() {
|
||||
let mut context = context_lock.write();
|
||||
for (pid, process_lock) in processes.iter() {
|
||||
let mut context = process_lock.write();
|
||||
|
||||
if context.pgid != pgid {
|
||||
continue;
|
||||
@@ -367,29 +364,25 @@ pub fn mprotect(address: usize, size: usize, flags: MapFlags) -> Result<()> {
|
||||
AddrSpace::current()?.mprotect(span, flags)
|
||||
}
|
||||
|
||||
pub fn setpgid(pid: ContextId, pgid: ContextId) -> Result<usize> {
|
||||
let contexts = context::contexts();
|
||||
pub fn setpgid(pid: ProcessId, pgid: ProcessId) -> Result<()> {
|
||||
let current_pid = context::current_pid()?;
|
||||
|
||||
let current_pid = {
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
context.pid
|
||||
};
|
||||
let processes = process::PROCESSES.read();
|
||||
|
||||
let context_lock = if pid.get() == 0 {
|
||||
contexts.current().ok_or(Error::new(ESRCH))?
|
||||
let process_lock = if pid.get() == 0 {
|
||||
process::current()?
|
||||
} else {
|
||||
contexts.get(pid).ok_or(Error::new(ESRCH))?
|
||||
Arc::clone(processes.get(&pid).ok_or(Error::new(ESRCH))?)
|
||||
};
|
||||
|
||||
let mut context = context_lock.write();
|
||||
if context.pid == current_pid || context.ppid == current_pid {
|
||||
let mut process = process_lock.write();
|
||||
if process.pid == current_pid || process.ppid == current_pid {
|
||||
if pgid.get() == 0 {
|
||||
context.pgid = context.pid;
|
||||
process.pgid = process.pid;
|
||||
} else {
|
||||
context.pgid = pgid;
|
||||
process.pgid = pgid;
|
||||
}
|
||||
Ok(0)
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::new(ESRCH))
|
||||
}
|
||||
@@ -398,48 +391,48 @@ pub fn setpgid(pid: ContextId, pgid: ContextId) -> Result<usize> {
|
||||
pub fn umask(mask: usize) -> Result<usize> {
|
||||
let previous;
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let mut context = context_lock.write();
|
||||
previous = context.umask;
|
||||
context.umask = mask;
|
||||
let process_lock = process::current()?;
|
||||
let mut process = process_lock.write();
|
||||
previous = process.umask;
|
||||
process.umask = mask;
|
||||
}
|
||||
|
||||
Ok(previous)
|
||||
}
|
||||
|
||||
fn reap(pid: ContextId) -> Result<ContextId> {
|
||||
fn reap(pid: ProcessId) -> Result<ProcessId> {
|
||||
let process_lock = Arc::clone(process::PROCESSES.read().get(&pid).ok_or(Error::new(ESRCH))?);
|
||||
|
||||
// Spin until not running
|
||||
let mut running = true;
|
||||
while running {
|
||||
loop {
|
||||
// TODO: exit WaitCondition?
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.get(pid).ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
running = context.running;
|
||||
let mut process = process_lock.read();
|
||||
if process.threads.iter().all(|t| t.upgrade().map_or(true, |t| !t.read().running)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: context switch?
|
||||
interrupt::pause();
|
||||
}
|
||||
|
||||
let _ = context::contexts_mut()
|
||||
.remove(pid)
|
||||
let _ = process::PROCESSES.write()
|
||||
.remove(&pid)
|
||||
.ok_or(Error::new(ESRCH))?;
|
||||
|
||||
Ok(pid)
|
||||
}
|
||||
|
||||
pub fn waitpid(
|
||||
pid: ContextId,
|
||||
pid: ProcessId,
|
||||
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.pid, Arc::clone(&context.waitpid))
|
||||
) -> Result<ProcessId> {
|
||||
let (ppid, process_lock) = {
|
||||
let process_lock = process::current()?;
|
||||
let process = process_lock.read();
|
||||
(process.pid, process_lock)
|
||||
};
|
||||
let write_status = |value| {
|
||||
status_ptr
|
||||
@@ -447,7 +440,7 @@ pub fn waitpid(
|
||||
.unwrap_or(Ok(()))
|
||||
};
|
||||
|
||||
let grim_reaper = |w_pid: ContextId, status: usize| -> Option<Result<ContextId>> {
|
||||
let grim_reaper = |w_pid: ProcessId, status: usize| -> Option<Result<ProcessId>> {
|
||||
if wifcontinued(status) {
|
||||
if flags & WCONTINUED == WCONTINUED {
|
||||
Some(write_status(status).map(|()| w_pid))
|
||||
@@ -471,10 +464,10 @@ pub fn waitpid(
|
||||
{
|
||||
let mut found = false;
|
||||
|
||||
let contexts = context::contexts();
|
||||
for (_id, context_lock) in contexts.iter() {
|
||||
let context = context_lock.read();
|
||||
if context.ppid == ppid {
|
||||
let contexts = process::PROCESSES.read();
|
||||
for (_id, process_lock) in processs.iter() {
|
||||
let process = process_lock.read();
|
||||
if process.ppid == ppid {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -489,23 +482,23 @@ pub fn waitpid(
|
||||
if let Some((_wid, (w_pid, status))) = waitpid.receive_any_nonblock() {
|
||||
grim_reaper(w_pid, status)
|
||||
} else {
|
||||
Some(Ok(ContextId::from(0)))
|
||||
Some(Ok(ProcessId::from(0)))
|
||||
}
|
||||
} else {
|
||||
let (_wid, (w_pid, status)) = waitpid.receive_any("waitpid any");
|
||||
grim_reaper(w_pid, status)
|
||||
}
|
||||
} else if (pid.get() as isize) < 0 {
|
||||
let pgid = ContextId::from(-(pid.get() as isize) as usize);
|
||||
let pgid = ProcessId::from(-(pid.get() as isize) as usize);
|
||||
|
||||
// Check for existence of child in process group PGID
|
||||
{
|
||||
let mut found = false;
|
||||
|
||||
let contexts = context::contexts();
|
||||
for (_id, context_lock) in contexts.iter() {
|
||||
let context = context_lock.read();
|
||||
if context.pgid == pgid {
|
||||
let processes = process::PROCESSES.read();
|
||||
for (_pid, process_lock) in processes.iter() {
|
||||
let process = process_lock.read();
|
||||
if process.pgid == pgid {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -523,7 +516,7 @@ pub fn waitpid(
|
||||
}) {
|
||||
grim_reaper(w_pid, status)
|
||||
} else {
|
||||
Some(Ok(ContextId::from(0)))
|
||||
Some(Ok(ProcessId::from(0)))
|
||||
}
|
||||
} else {
|
||||
let (w_pid, status) = waitpid.receive(
|
||||
@@ -537,17 +530,18 @@ pub fn waitpid(
|
||||
}
|
||||
} else {
|
||||
let hack_status = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.get(pid).ok_or(Error::new(ECHILD))?;
|
||||
let mut context = context_lock.write();
|
||||
if context.ppid != ppid {
|
||||
let processes = process::PROCESSES.read();
|
||||
let process_lock = processes.get(&pid).ok_or(Error::new(ECHILD))?;
|
||||
let process = process_lock.read();
|
||||
|
||||
if process.ppid != ppid {
|
||||
println!(
|
||||
"TODO: Hack for rustc - changing ppid of {} from {} to {}",
|
||||
context.pid.get(),
|
||||
context.ppid.get(),
|
||||
process.pid.get(),
|
||||
process.ppid.get(),
|
||||
ppid.get()
|
||||
);
|
||||
context.ppid = ppid;
|
||||
process.ppid = ppid;
|
||||
//return Err(Error::new(ECHILD));
|
||||
Some(context.status.clone())
|
||||
} else {
|
||||
@@ -568,7 +562,7 @@ pub fn waitpid(
|
||||
}) {
|
||||
grim_reaper(w_pid, status)
|
||||
} else {
|
||||
Some(Ok(ContextId::from(0)))
|
||||
Some(Ok(ProcessId::from(0)))
|
||||
}
|
||||
} else {
|
||||
let (w_pid, status) = waitpid.receive(
|
||||
|
||||
Reference in New Issue
Block a user