Fix most code except proc scheme.
This commit is contained in:
+2
-10
@@ -16,8 +16,7 @@ use crate::{
|
||||
memory::{allocate_p2frame, deallocate_p2frame, Enomem, Frame, RaiiFrame},
|
||||
paging::{RmmA, RmmArch},
|
||||
percpu::PercpuBlock,
|
||||
scheme::{CallerCtx, FileHandle, SchemeNamespace},
|
||||
sync::WaitMap,
|
||||
scheme::FileHandle,
|
||||
};
|
||||
|
||||
use crate::syscall::error::{Error, Result, EAGAIN, ESRCH};
|
||||
@@ -207,7 +206,7 @@ pub struct SignalState {
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn new(cid: ContextId, pid: ContextId, process: Arc<RwLock<Process>>) -> Result<Context> {
|
||||
pub fn new(cid: ContextId, pid: ProcessId, process: Arc<RwLock<Process>>) -> Result<Context> {
|
||||
let this = Context {
|
||||
cid,
|
||||
pid,
|
||||
@@ -413,13 +412,6 @@ impl Context {
|
||||
|
||||
core::mem::replace(&mut self.addr_space, addr_space)
|
||||
}
|
||||
pub fn caller_ctx(&self) -> CallerCtx {
|
||||
CallerCtx {
|
||||
pid: self.pid.into(),
|
||||
uid: self.euid,
|
||||
gid: self.egid,
|
||||
}
|
||||
}
|
||||
|
||||
fn can_access_regs(&self) -> bool {
|
||||
self.userspace
|
||||
|
||||
+11
-7
@@ -1,11 +1,11 @@
|
||||
use alloc::{collections::BTreeMap, sync::Arc};
|
||||
use core::iter;
|
||||
use spin::RwLock;
|
||||
|
||||
use spinning_top::RwSpinlock;
|
||||
|
||||
use super::{
|
||||
context::{Context, ContextId, Kstack},
|
||||
memory::AddrSpaceWrapper,
|
||||
memory::AddrSpaceWrapper, process::{Process, ProcessId},
|
||||
};
|
||||
use crate::{
|
||||
interrupt::InterruptStack,
|
||||
@@ -53,22 +53,26 @@ impl ContextList {
|
||||
|
||||
pub(crate) fn insert_context_raw(
|
||||
&mut self,
|
||||
id: ContextId,
|
||||
cid: ContextId,
|
||||
pid: ProcessId,
|
||||
process: Arc<RwLock<Process>>,
|
||||
) -> Result<&Arc<RwSpinlock<Context>>> {
|
||||
assert!(self
|
||||
.map
|
||||
// TODO
|
||||
.insert(id, Arc::new(RwSpinlock::new(Context::new(id, id)?)))
|
||||
.insert(cid, Arc::new(RwSpinlock::new(Context::new(cid, pid, process)?)))
|
||||
.is_none());
|
||||
|
||||
Ok(self
|
||||
.map
|
||||
.get(&id)
|
||||
.get(&cid)
|
||||
.expect("Failed to insert new context. ID is out of bounds."))
|
||||
}
|
||||
|
||||
/// Create a new context.
|
||||
pub fn new_context(&mut self) -> Result<&Arc<RwSpinlock<Context>>> {
|
||||
pub fn new_context(&mut self, process: Arc<RwLock<Process>>) -> Result<&Arc<RwSpinlock<Context>>> {
|
||||
let pid = process.read().pid;
|
||||
|
||||
// Zero is not a valid context ID, therefore add 1.
|
||||
//
|
||||
// FIXME: Ensure the number of CPUs can't switch between new_context calls.
|
||||
@@ -91,7 +95,7 @@ impl ContextList {
|
||||
let id = ContextId::from(self.next_id);
|
||||
self.next_id += 1;
|
||||
|
||||
self.insert_context_raw(id)
|
||||
self.insert_context_raw(id, pid, process)
|
||||
}
|
||||
|
||||
/// Spawn a context from a function.
|
||||
|
||||
+35
-24
@@ -1,3 +1,5 @@
|
||||
use core::ops::{Deref, DerefMut};
|
||||
|
||||
// TODO: move all this code to userspace
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::sync::{Arc, Weak};
|
||||
@@ -8,7 +10,7 @@ use spinning_top::RwSpinlock;
|
||||
|
||||
use syscall::{Error, Result, ESRCH};
|
||||
|
||||
use crate::scheme::SchemeNamespace;
|
||||
use crate::scheme::{CallerCtx, SchemeNamespace};
|
||||
use crate::sync::WaitMap;
|
||||
|
||||
use crate::context::{self, Context, WaitpidKey};
|
||||
@@ -17,6 +19,14 @@ int_like!(ProcessId, usize);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Process {
|
||||
pub info: ProcessInfo,
|
||||
/// Context is being waited on
|
||||
pub waitpid: Arc<WaitMap<WaitpidKey, (ProcessId, usize)>>,
|
||||
/// Threads of process
|
||||
pub threads: Vec<Weak<RwSpinlock<Context>>>,
|
||||
}
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct ProcessInfo {
|
||||
/// The process ID of this process
|
||||
pub pid: ProcessId,
|
||||
/// The group ID of this process
|
||||
@@ -39,46 +49,47 @@ pub struct Process {
|
||||
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>>>,
|
||||
}
|
||||
impl Deref for Process {
|
||||
type Target = ProcessInfo;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.info
|
||||
}
|
||||
}
|
||||
impl DerefMut for Process {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.info
|
||||
}
|
||||
}
|
||||
|
||||
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>,
|
||||
list: &BTreeMap<ProcessId, Arc<RwLock<Process>>>,
|
||||
id: ProcessId,
|
||||
) -> impl Iterator<Item = (ProcessId, &Arc<RwSpinlock<Context>>)> + '_ {
|
||||
) -> impl Iterator<Item = (ProcessId, &Arc<RwLock<Process>>)> + '_ {
|
||||
core::iter::successors(
|
||||
list.get(&id).map(|process| (id, process)),
|
||||
move |(_id, process)| {
|
||||
let context = process.read();
|
||||
let process = process.read();
|
||||
let id = process.ppid;
|
||||
list.get(&id).map(|context| (id, context))
|
||||
list.get(&id).map(|process| (id, process))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
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))
|
||||
Ok(Arc::clone(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 Process {
|
||||
pub fn caller_ctx(&self) -> CallerCtx {
|
||||
CallerCtx {
|
||||
pid: self.pid.into(),
|
||||
uid: self.euid,
|
||||
gid: self.egid,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Eq for Process {}
|
||||
|
||||
@@ -25,12 +25,6 @@ unsafe fn update_runnable(context: &mut Context, cpu_id: LogicalCpuId) -> Update
|
||||
return UpdateResult::Skip;
|
||||
}
|
||||
|
||||
// Ignore contexts stopped by ptrace
|
||||
// TODO: ContextStatus::HardBlocked?
|
||||
if context.ptrace_stop {
|
||||
return UpdateResult::Skip;
|
||||
}
|
||||
|
||||
// Ignore contexts assigned to other CPUs
|
||||
if !context.sched_affinity.contains(cpu_id) {
|
||||
return UpdateResult::Skip;
|
||||
@@ -201,7 +195,7 @@ pub fn switch() -> SwitchResult {
|
||||
}));
|
||||
|
||||
let (ptrace_session, ptrace_flags) = if let Some((session, bp)) = ptrace::sessions()
|
||||
.get(&next_context.cid)
|
||||
.get(&next_context.pid)
|
||||
.map(|s| (Arc::downgrade(s), s.data.lock().breakpoint))
|
||||
{
|
||||
(Some(session), bp.map_or(PtraceFlags::empty(), |f| f.flags))
|
||||
|
||||
+8
-8
@@ -3,7 +3,7 @@
|
||||
//! of the scheme.
|
||||
|
||||
use crate::{
|
||||
context::{self, ContextId},
|
||||
context::{self, process::ProcessId},
|
||||
event,
|
||||
percpu::PercpuBlock,
|
||||
scheme::GlobalSchemes,
|
||||
@@ -82,7 +82,7 @@ pub struct Session {
|
||||
pub tracer: WaitCondition,
|
||||
}
|
||||
impl Session {
|
||||
pub fn with_session<F, T>(pid: ContextId, callback: F) -> Result<T>
|
||||
pub fn with_session<F, T>(pid: ProcessId, callback: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(&Session) -> Result<T>,
|
||||
{
|
||||
@@ -97,7 +97,7 @@ impl Session {
|
||||
}
|
||||
}
|
||||
|
||||
type SessionMap = HashMap<ContextId, Arc<Session>>;
|
||||
type SessionMap = HashMap<ProcessId, Arc<Session>>;
|
||||
|
||||
static SESSIONS: Once<RwLock<SessionMap>> = Once::new();
|
||||
|
||||
@@ -113,7 +113,7 @@ fn sessions_mut() -> RwLockWriteGuard<'static, SessionMap> {
|
||||
|
||||
/// Try to create a new session, but fail if one already exists for this
|
||||
/// process
|
||||
pub fn try_new_session(pid: ContextId, file_id: usize) -> bool {
|
||||
pub fn try_new_session(pid: ProcessId, file_id: usize) -> bool {
|
||||
let mut sessions = sessions_mut();
|
||||
|
||||
match sessions.entry(pid) {
|
||||
@@ -135,7 +135,7 @@ pub fn try_new_session(pid: ContextId, file_id: usize) -> bool {
|
||||
|
||||
/// Remove the session from the list of open sessions and notify any
|
||||
/// waiting processes
|
||||
pub fn close_session(pid: ContextId) {
|
||||
pub fn close_session(pid: ProcessId) {
|
||||
if let Some(session) = sessions_mut().remove(&pid) {
|
||||
session.tracer.notify();
|
||||
session.tracee.notify();
|
||||
@@ -148,7 +148,7 @@ pub fn close_session(pid: ContextId) {
|
||||
/// session will *actually* be closed. This is partly to ensure ENOSRCH is
|
||||
/// returned rather than ENODEV (which occurs when there's no session - should
|
||||
/// never really happen).
|
||||
pub fn close_tracee(pid: ContextId) {
|
||||
pub fn close_tracee(pid: ProcessId) {
|
||||
if let Some(session) = sessions().get(&pid) {
|
||||
session.tracer.notify();
|
||||
|
||||
@@ -158,7 +158,7 @@ pub fn close_tracee(pid: ContextId) {
|
||||
}
|
||||
|
||||
/// Returns true if a session is attached to this process
|
||||
pub fn is_traced(pid: ContextId) -> bool {
|
||||
pub fn is_traced(pid: ProcessId) -> bool {
|
||||
sessions().contains_key(&pid)
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ pub(crate) struct Breakpoint {
|
||||
///
|
||||
/// Note: Don't call while holding any locks or allocated data, this will
|
||||
/// switch contexts and may in fact just never terminate.
|
||||
pub fn wait(pid: ContextId) -> Result<()> {
|
||||
pub fn wait(pid: ProcessId) -> Result<()> {
|
||||
loop {
|
||||
let session = {
|
||||
let sessions = sessions();
|
||||
|
||||
+2
-7
@@ -8,7 +8,7 @@ use spin::RwLock;
|
||||
use syscall::O_FSYNC;
|
||||
|
||||
use crate::{
|
||||
context::{self, file::InternalFlags},
|
||||
context::{self, file::InternalFlags, process},
|
||||
scheme::{
|
||||
self,
|
||||
user::{UserInner, UserScheme},
|
||||
@@ -115,12 +115,7 @@ impl KernelScheme for RootScheme {
|
||||
|
||||
Ok(OpenResult::SchemeLocal(id, InternalFlags::empty()))
|
||||
} else if path.is_empty() {
|
||||
let scheme_ns = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
context.ens
|
||||
};
|
||||
let scheme_ns = process::current()?.read().ens;
|
||||
|
||||
let mut data = Vec::new();
|
||||
{
|
||||
|
||||
+11
-10
@@ -103,25 +103,26 @@ pub fn resource() -> Result<Vec<u8>> {
|
||||
} else {
|
||||
format!("{} B", memory)
|
||||
};
|
||||
let process = context.process.read();
|
||||
|
||||
string.push_str(&format!(
|
||||
"{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<11}{:<12}{:<8}{}\n",
|
||||
context.pid.get(),
|
||||
context.pgid.get(),
|
||||
context.ppid.get(),
|
||||
context.session_id.get(),
|
||||
context.ruid,
|
||||
context.rgid,
|
||||
context.rns.get(),
|
||||
context.euid,
|
||||
context.egid,
|
||||
context.ens.get(),
|
||||
process.pgid.get(),
|
||||
process.ppid.get(),
|
||||
process.session_id.get(),
|
||||
process.ruid,
|
||||
process.rgid,
|
||||
process.rns.get(),
|
||||
process.euid,
|
||||
process.egid,
|
||||
process.ens.get(),
|
||||
stat_string,
|
||||
cpu_string,
|
||||
affinity,
|
||||
cpu_time_string,
|
||||
memory_string,
|
||||
context.name
|
||||
context.name,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::{
|
||||
context, scheme,
|
||||
syscall::error::{Error, Result, ESRCH},
|
||||
context::process, scheme,
|
||||
syscall::error::{Error, Result},
|
||||
};
|
||||
|
||||
pub fn resource() -> Result<Vec<u8>> {
|
||||
let scheme_ns = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
context.ens
|
||||
};
|
||||
let scheme_ns = process::current()?.read().ens;
|
||||
|
||||
let mut data = Vec::new();
|
||||
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::{
|
||||
context, scheme,
|
||||
context::process, scheme,
|
||||
syscall::error::{Error, Result, ESRCH},
|
||||
};
|
||||
|
||||
pub fn resource() -> Result<Vec<u8>> {
|
||||
let scheme_ns = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
context.ens
|
||||
};
|
||||
let scheme_ns = process::current()?.read().ens;
|
||||
|
||||
let mut data = Vec::new();
|
||||
|
||||
|
||||
+11
-15
@@ -21,14 +21,10 @@ use syscall::{
|
||||
|
||||
use crate::{
|
||||
context::{
|
||||
self,
|
||||
context::HardBlockedReason,
|
||||
file::{FileDescription, FileDescriptor, InternalFlags},
|
||||
memory::{
|
||||
self, context::HardBlockedReason, file::{FileDescription, FileDescriptor, InternalFlags}, memory::{
|
||||
AddrSpace, AddrSpaceWrapper, BorrowedFmapSource, Grant, GrantFileRef, MmapMode,
|
||||
PageSpan, DANGLING,
|
||||
},
|
||||
BorrowedHtBuf, Context, Status,
|
||||
}, process, BorrowedHtBuf, Context, Status
|
||||
},
|
||||
event,
|
||||
memory::Frame,
|
||||
@@ -236,7 +232,7 @@ impl UserInner {
|
||||
}
|
||||
|
||||
pub fn call(&self, opcode: Opcode, args: impl Args) -> Result<usize> {
|
||||
let ctx = context::current()?.read().caller_ctx();
|
||||
let ctx = process::current()?.read().caller_ctx();
|
||||
match self.call_extended(ctx, None, opcode, args)? {
|
||||
Response::Regular(code, _) => Error::demux(code),
|
||||
Response::Fd(_) => Err(Error::new(EIO)),
|
||||
@@ -1355,10 +1351,10 @@ impl KernelScheme for UserScheme {
|
||||
|
||||
fn fchown(&self, file: usize, uid: u32, gid: u32) -> Result<()> {
|
||||
{
|
||||
let context_lock = context::current()?;
|
||||
let context = context_lock.read();
|
||||
if context.euid != 0 {
|
||||
if uid != context.euid || gid != context.egid {
|
||||
let process_lock = process::current()?;
|
||||
let process = process_lock.read();
|
||||
if process.euid != 0 {
|
||||
if uid != process.euid || gid != process.egid {
|
||||
return Err(Error::new(EPERM));
|
||||
}
|
||||
}
|
||||
@@ -1543,7 +1539,7 @@ impl KernelScheme for UserScheme {
|
||||
fn kfunmap(&self, number: usize, offset: usize, size: usize, flags: MunmapFlags) -> Result<()> {
|
||||
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
|
||||
|
||||
let ctx = context::current()?.read().caller_ctx();
|
||||
let ctx = process::current()?.read().caller_ctx();
|
||||
let res = inner.call_extended(
|
||||
ctx,
|
||||
None,
|
||||
@@ -1565,7 +1561,7 @@ impl KernelScheme for UserScheme {
|
||||
) -> Result<usize> {
|
||||
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
|
||||
|
||||
let ctx = context::current()?.read().caller_ctx();
|
||||
let ctx = process::current()?.read().caller_ctx();
|
||||
let res = inner.call_extended(ctx, Some(desc), Opcode::Sendfd, [number, flags.bits()])?;
|
||||
|
||||
match res {
|
||||
@@ -1603,7 +1599,7 @@ fn uid_gid_hack_merge([uid, gid]: [u32; 2]) -> u64 {
|
||||
u64::from(uid) | (u64::from(gid) << 32)
|
||||
}
|
||||
fn current_uid_gid() -> Result<[u32; 2]> {
|
||||
Ok(match context::current()?.read() {
|
||||
ref ctx => [ctx.euid, ctx.egid],
|
||||
Ok(match process::current()?.read() {
|
||||
ref p => [p.euid, p.egid],
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
context,
|
||||
context::{self, process},
|
||||
paging::VirtualAddress,
|
||||
syscall::error::{Error, Result, EFAULT, EPERM, ESRCH},
|
||||
};
|
||||
fn enforce_root() -> Result<()> {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
if context.euid == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::new(EPERM))
|
||||
if process::current()?.read().euid != 0 {
|
||||
return Err(Error::new(EPERM));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
|
||||
+14
-19
@@ -111,8 +111,8 @@ pub fn open(raw_path: UserSliceRo, flags: usize) -> Result<FileHandle> {
|
||||
|
||||
/// rmdir syscall
|
||||
pub fn rmdir(raw_path: UserSliceRo) -> Result<()> {
|
||||
let (scheme_ns, caller_ctx) = match context::current()?.read() {
|
||||
ref context => (context.ens, context.caller_ctx()),
|
||||
let (scheme_ns, caller_ctx) = match process::current()?.read() {
|
||||
ref process => (process.ens, process.caller_ctx()),
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -135,8 +135,8 @@ pub fn rmdir(raw_path: UserSliceRo) -> Result<()> {
|
||||
|
||||
/// Unlink syscall
|
||||
pub fn unlink(raw_path: UserSliceRo) -> Result<()> {
|
||||
let (scheme_ns, caller_ctx) = match context::current()?.read() {
|
||||
ref context => (context.ens, context.caller_ctx()),
|
||||
let (scheme_ns, caller_ctx) = match process::current()?.read() {
|
||||
ref process => (process.ens, process.caller_ctx()),
|
||||
};
|
||||
/*
|
||||
let mut path_buf = BorrowedHtBuf::head()?;
|
||||
@@ -159,8 +159,7 @@ pub fn unlink(raw_path: UserSliceRo) -> Result<()> {
|
||||
/// Close syscall
|
||||
pub fn close(fd: FileHandle) -> Result<()> {
|
||||
let file = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context_lock = context::current()?;
|
||||
let context = context_lock.read();
|
||||
context.remove_file(fd).ok_or(Error::new(EBADF))?
|
||||
};
|
||||
@@ -169,12 +168,8 @@ 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(),
|
||||
),
|
||||
};
|
||||
let caller_ctx = process::current()?.read().caller_ctx();
|
||||
let file = context::current()?.read().get_file(fd).ok_or(Error::new(EBADF))?;
|
||||
|
||||
if user_buf.is_empty() {
|
||||
Ok(FileDescriptor {
|
||||
@@ -355,17 +350,17 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
|
||||
}
|
||||
|
||||
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))?,
|
||||
let (caller_ctx, scheme_ns) = match process::current()?.read() {
|
||||
ref process => (
|
||||
CallerCtx {
|
||||
uid: context.euid,
|
||||
gid: context.egid,
|
||||
pid: context.pid.get(),
|
||||
uid: process.euid,
|
||||
gid: process.egid,
|
||||
pid: process.pid.get(),
|
||||
},
|
||||
context.ens,
|
||||
process.ens,
|
||||
),
|
||||
};
|
||||
let file = context::current()?.read().get_file(fd).ok_or(Error::new(EBADF))?;
|
||||
|
||||
/*
|
||||
let mut path_buf = BorrowedHtBuf::head()?;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::{
|
||||
context::{self, process},
|
||||
context::process,
|
||||
scheme::{self, SchemeNamespace},
|
||||
syscall::error::*,
|
||||
};
|
||||
|
||||
+56
-48
@@ -6,7 +6,7 @@ use rmm::Arch;
|
||||
use spin::RwLock;
|
||||
|
||||
use crate::context::{
|
||||
memory::{AddrSpace, Grant, PageSpan}, process::{self, ProcessId}, WaitpidKey
|
||||
memory::{AddrSpace, Grant, PageSpan}, process::{self, ProcessId, ProcessInfo}, WaitpidKey
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -38,7 +38,7 @@ pub fn exit(status: usize) -> ! {
|
||||
let close_files;
|
||||
let addrspace_opt;
|
||||
|
||||
let pid = {
|
||||
let (pid, process_lock) = {
|
||||
let mut context = context_lock.write();
|
||||
close_files = Arc::try_unwrap(mem::take(&mut context.files))
|
||||
.map_or_else(|_| Vec::new(), RwLock::into_inner);
|
||||
@@ -47,7 +47,7 @@ pub fn exit(status: usize) -> ! {
|
||||
.and_then(|a| Arc::try_unwrap(a).ok());
|
||||
drop(context.syscall_head.take());
|
||||
drop(context.syscall_tail.take());
|
||||
context.pid
|
||||
(context.pid, Arc::clone(&context.process))
|
||||
};
|
||||
|
||||
// Files must be closed while context is valid so that messages can be passed
|
||||
@@ -60,34 +60,29 @@ 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();
|
||||
let process = context.process.read();
|
||||
let process = process_lock.read();
|
||||
(process.pgid, process.ppid)
|
||||
};
|
||||
let _ = kill(ppid, SIGCHLD, true);
|
||||
|
||||
// Transfer child processes to parent (TODO: init)
|
||||
// Transfer child processes to parent (TODO: to init)
|
||||
{
|
||||
let processes = context::process::PROCESSES.read();
|
||||
for (pid, process_lock) in processes.iter() {
|
||||
let mut process = process_lock.write();
|
||||
for (_child_pid, child_process_lock) in processes.iter() {
|
||||
let mut process = child_process_lock.write();
|
||||
if process.ppid == pid {
|
||||
process.ppid = ppid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let children = {
|
||||
let mut context = context_lock.write();
|
||||
context_lock.write().status = context::Status::Exited(status);
|
||||
|
||||
context.status = context::Status::Exited(status);
|
||||
|
||||
context.waitpid.receive_all()
|
||||
};
|
||||
let children = process_lock.write().waitpid.receive_all();
|
||||
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
if let Some(parent_lock) = contexts.get(ppid) {
|
||||
let processes = process::PROCESSES.read();
|
||||
if let Some(parent_lock) = processes.get(&ppid) {
|
||||
let waitpid = Arc::clone(&parent_lock.write().waitpid);
|
||||
|
||||
for (c_pid, c_status) in children {
|
||||
@@ -121,7 +116,7 @@ pub fn getpgid(pid: ProcessId) -> Result<ProcessId> {
|
||||
let process_lock = if pid.get() == 0 {
|
||||
process::current()?
|
||||
} else {
|
||||
Arc::clone(process::PROCESSES.get(&pid).ok_or(Error::new(ESRCH))?)
|
||||
Arc::clone(process::PROCESSES.read().get(&pid).ok_or(Error::new(ESRCH))?)
|
||||
};
|
||||
let process = process_lock.read();
|
||||
Ok(process.pgid)
|
||||
@@ -133,7 +128,7 @@ pub fn getppid() -> Result<ProcessId> {
|
||||
|
||||
pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
let (ruid, euid, current_pgid) = {
|
||||
let process_lock = process::current?;
|
||||
let process_lock = process::current()?;
|
||||
let process = process_lock.read();
|
||||
(process.ruid, process.euid, process.pgid)
|
||||
};
|
||||
@@ -172,11 +167,11 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
},
|
||||
}
|
||||
|
||||
let mut send = |context: &mut context::Context| -> SendResult {
|
||||
let mut send = |context: &mut context::Context, proc: &ProcessInfo| -> SendResult {
|
||||
let is_self = context.cid == context::current_cid();
|
||||
|
||||
// Non-root users cannot kill arbitrarily.
|
||||
if euid != 0 && euid != context.ruid && ruid != context.ruid {
|
||||
if euid != 0 && euid != proc.ruid && ruid != proc.ruid {
|
||||
return SendResult::Forbidden;
|
||||
}
|
||||
// If sig = 0, test that process exists and can be signalled, but don't send any
|
||||
@@ -204,8 +199,8 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
}
|
||||
// POSIX XSI allows but does not reqiure SIGCHLD to be sent when SIGCONT occurs.
|
||||
SendResult::SucceededSigcont {
|
||||
ppid: context.ppid,
|
||||
pgid: context.pgid,
|
||||
ppid: proc.ppid,
|
||||
pgid: proc.pgid,
|
||||
}
|
||||
} else if sig == SIGSTOP
|
||||
|| (matches!(sig, SIGTTIN | SIGTTOU | SIGTSTP)
|
||||
@@ -219,8 +214,8 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
ctl.word[0].fetch_and(!sig_bit(SIGCONT), Ordering::Relaxed);
|
||||
}
|
||||
SendResult::SucceededSigchld {
|
||||
ppid: context.ppid,
|
||||
pgid: context.pgid,
|
||||
ppid: proc.ppid,
|
||||
pgid: proc.pgid,
|
||||
orig_signal: sig,
|
||||
}
|
||||
} else if sig == SIGKILL {
|
||||
@@ -276,14 +271,11 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
}
|
||||
SendResult::SucceededSigcont { ppid, pgid } => {
|
||||
sent += 1;
|
||||
let waitpid = Arc::clone(
|
||||
&process::PROCESSES.read()
|
||||
.get(&ppid)
|
||||
.ok_or(Error::new(ESRCH))?
|
||||
.read()
|
||||
.waitpid,
|
||||
);
|
||||
waitpid.send(
|
||||
.waitpid.send(
|
||||
WaitpidKey {
|
||||
pid: Some(pid),
|
||||
pgid: Some(pgid),
|
||||
@@ -299,22 +291,29 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
// Send to a single process
|
||||
if let Some(process_lock) = processes.get(&pid) {
|
||||
found += 1;
|
||||
let result = send(&mut *process_lock.write());
|
||||
let (context_lock, info) = {
|
||||
let process = process_lock.read();
|
||||
(process.threads.first().ok_or(Error::new(ESRCH))?.upgrade().ok_or(Error::new(ESRCH))?, process.info)
|
||||
};
|
||||
let mut context = context_lock.write();
|
||||
let result = send(&mut *context, &info);
|
||||
handle_send(pid, result)?;
|
||||
}
|
||||
} else if pid.get() == 1_usize.wrapping_neg() {
|
||||
// Send to every process with permission, except for init
|
||||
for (pid, process_lock) in processes.iter() {
|
||||
let mut process = process_lock.write();
|
||||
let (context_lock, info) = {
|
||||
let process = process_lock.read();
|
||||
(process.threads.first().ok_or(Error::new(ESRCH))?.upgrade().ok_or(Error::new(ESRCH))?, process.info)
|
||||
};
|
||||
|
||||
if process.pid.get() <= 2 {
|
||||
if info.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 mut context = context_lock.write();
|
||||
|
||||
let result = send(&mut *context);
|
||||
let result = send(&mut *context, &info);
|
||||
drop(context);
|
||||
handle_send(*pid, result)?;
|
||||
}
|
||||
@@ -327,14 +326,18 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
|
||||
// Send to every process in the process group whose ID
|
||||
for (pid, process_lock) in processes.iter() {
|
||||
let mut context = process_lock.write();
|
||||
let (context_lock, info) = {
|
||||
let process = process_lock.read();
|
||||
(process.threads.first().ok_or(Error::new(ESRCH))?.upgrade().ok_or(Error::new(ESRCH))?, process.info)
|
||||
};
|
||||
|
||||
if context.pgid != pgid {
|
||||
if info.pgid != pgid {
|
||||
continue;
|
||||
}
|
||||
found += 1;
|
||||
|
||||
let result = send(&mut *context);
|
||||
let mut context = context_lock.write();
|
||||
let result = send(&mut *context, &info);
|
||||
drop(context);
|
||||
|
||||
handle_send(*pid, result)?;
|
||||
@@ -429,11 +432,12 @@ pub fn waitpid(
|
||||
status_ptr: Option<UserSliceWo>,
|
||||
flags: WaitFlags,
|
||||
) -> Result<ProcessId> {
|
||||
let (ppid, process_lock) = {
|
||||
let process_lock = process::current()?;
|
||||
let process_lock = process::current()?;
|
||||
let (ppid, waitpid) = {
|
||||
let process = process_lock.read();
|
||||
(process.pid, process_lock)
|
||||
(process.ppid, Arc::clone(&process.waitpid))
|
||||
};
|
||||
|
||||
let write_status = |value| {
|
||||
status_ptr
|
||||
.map(|ptr| ptr.write_usize(value))
|
||||
@@ -464,8 +468,8 @@ pub fn waitpid(
|
||||
{
|
||||
let mut found = false;
|
||||
|
||||
let contexts = process::PROCESSES.read();
|
||||
for (_id, process_lock) in processs.iter() {
|
||||
let processes = process::PROCESSES.read();
|
||||
for (_id, process_lock) in processes.iter() {
|
||||
let process = process_lock.read();
|
||||
if process.ppid == ppid {
|
||||
found = true;
|
||||
@@ -477,7 +481,6 @@ pub fn waitpid(
|
||||
return Err(Error::new(ECHILD));
|
||||
}
|
||||
}
|
||||
|
||||
if flags & WNOHANG == WNOHANG {
|
||||
if let Some((_wid, (w_pid, status))) = waitpid.receive_any_nonblock() {
|
||||
grim_reaper(w_pid, status)
|
||||
@@ -535,6 +538,9 @@ pub fn waitpid(
|
||||
let process = process_lock.read();
|
||||
|
||||
if process.ppid != ppid {
|
||||
return Err(Error::new(ECHILD));
|
||||
// TODO
|
||||
/*
|
||||
println!(
|
||||
"TODO: Hack for rustc - changing ppid of {} from {} to {}",
|
||||
process.pid.get(),
|
||||
@@ -542,24 +548,26 @@ pub fn waitpid(
|
||||
ppid.get()
|
||||
);
|
||||
process.ppid = ppid;
|
||||
//return Err(Error::new(ECHILD));
|
||||
Some(context.status.clone())
|
||||
*/
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(context::Status::Exited(status)) = hack_status {
|
||||
let _ = waitpid.receive_nonblock(&WaitpidKey {
|
||||
/*let _ = waitpid.receive_nonblock(&WaitpidKey {
|
||||
pid: Some(pid),
|
||||
pgid: None,
|
||||
});
|
||||
grim_reaper(pid, status)
|
||||
grim_reaper(pid, status)*/
|
||||
unreachable!()
|
||||
} else if flags & WNOHANG == WNOHANG {
|
||||
if let Some((w_pid, status)) = waitpid.receive_nonblock(&WaitpidKey {
|
||||
let res = waitpid.receive_nonblock(&WaitpidKey {
|
||||
pid: Some(pid),
|
||||
pgid: None,
|
||||
}) {
|
||||
});
|
||||
if let Some((w_pid, status)) = res {
|
||||
grim_reaper(w_pid, status)
|
||||
} else {
|
||||
Some(Ok(ProcessId::from(0)))
|
||||
|
||||
Reference in New Issue
Block a user