WIP: continue the process transition

This commit is contained in:
4lDO2
2024-07-08 16:02:46 +02:00
parent 0da2fce64a
commit 8f452b0b0f
10 changed files with 268 additions and 254 deletions
+8 -8
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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(