Merge branch 'bootstrap_refactors2' into 'main'
Use FdGuard in bootstrap where possible See merge request redox-os/base!142
This commit is contained in:
+102
-58
@@ -4,11 +4,12 @@ use alloc::vec::Vec;
|
||||
use core::ffi::CStr;
|
||||
use core::str::FromStr;
|
||||
use hashbrown::HashMap;
|
||||
use redox_scheme::Socket;
|
||||
|
||||
use syscall::CallFlags;
|
||||
use syscall::data::{GlobalSchemes, KernelSchemeInfo};
|
||||
use syscall::flag::{O_CLOEXEC, O_RDONLY, O_STAT};
|
||||
use syscall::CallFlags;
|
||||
use syscall::{Error, EINTR};
|
||||
use syscall::{EINTR, Error};
|
||||
|
||||
use redox_rt::proc::*;
|
||||
|
||||
@@ -49,20 +50,15 @@ pub fn main() -> ! {
|
||||
};
|
||||
let scheme_creation_cap = unsafe {
|
||||
let base_ptr = cursor as *const u8;
|
||||
let cap = *(base_ptr as *const usize);
|
||||
cap
|
||||
FdGuard::new(*(base_ptr as *const usize))
|
||||
};
|
||||
|
||||
let kernel_schemes = KernelSchemeMap::new(kernel_scheme_infos);
|
||||
let mut kernel_schemes = KernelSchemeMap::new(kernel_scheme_infos);
|
||||
|
||||
let auth = FdGuard::new(
|
||||
*kernel_schemes
|
||||
.get(GlobalSchemes::Proc)
|
||||
.expect("failed to get proc fd"),
|
||||
);
|
||||
let pipe_fd = *kernel_schemes
|
||||
.get(GlobalSchemes::Pipe)
|
||||
.expect("failed to get pipe fd");
|
||||
let auth = kernel_schemes
|
||||
.0
|
||||
.remove(&GlobalSchemes::Proc)
|
||||
.expect("failed to get proc fd");
|
||||
|
||||
let this_thr_fd = auth
|
||||
.dup(b"cur-context")
|
||||
@@ -75,9 +71,10 @@ pub fn main() -> ! {
|
||||
let mut envs = {
|
||||
let fd = FdGuard::new(
|
||||
syscall::openat(
|
||||
*kernel_schemes
|
||||
kernel_schemes
|
||||
.get(GlobalSchemes::Sys)
|
||||
.expect("failed to get sys fd"),
|
||||
.expect("failed to get sys fd")
|
||||
.as_raw_fd(),
|
||||
"env",
|
||||
O_RDONLY | O_CLOEXEC,
|
||||
0,
|
||||
@@ -126,12 +123,14 @@ pub fn main() -> ! {
|
||||
(*(core::ptr::addr_of!(__initfs_header) as *const redox_initfs::types::Header)).initfs_size
|
||||
};
|
||||
|
||||
let initfs_fd = spawn(
|
||||
let (scheme_creation_cap, auth, kernel_schemes, initfs_fd) = spawn(
|
||||
"initfs daemon",
|
||||
&auth,
|
||||
auth,
|
||||
&this_thr_fd,
|
||||
pipe_fd,
|
||||
|write_fd| unsafe {
|
||||
scheme_creation_cap,
|
||||
kernel_schemes,
|
||||
false,
|
||||
|write_fd, socket, _, _| unsafe {
|
||||
// Creating a reference to NULL is UB. Mask the UB for now using black_box.
|
||||
// FIXME use a raw pointer and inline asm for reading instead for the initfs header.
|
||||
let initfs_start = core::ptr::addr_of!(__initfs_header);
|
||||
@@ -140,45 +139,65 @@ pub fn main() -> ! {
|
||||
crate::initfs::run(
|
||||
core::slice::from_raw_parts(initfs_start, initfs_length),
|
||||
write_fd,
|
||||
&kernel_schemes,
|
||||
scheme_creation_cap,
|
||||
socket,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
let proc_fd = spawn(
|
||||
let (scheme_creation_cap, auth, kernel_schemes, proc_fd) = spawn(
|
||||
"process manager",
|
||||
&auth,
|
||||
auth,
|
||||
&this_thr_fd,
|
||||
pipe_fd,
|
||||
|write_fd| crate::procmgr::run(write_fd, &auth, &kernel_schemes, scheme_creation_cap),
|
||||
);
|
||||
|
||||
let initns_fd = spawn(
|
||||
"init namespace manager",
|
||||
&auth,
|
||||
&this_thr_fd,
|
||||
pipe_fd,
|
||||
move |write_fd| {
|
||||
let mut schemes = HashMap::default();
|
||||
for (scheme, fd) in kernel_schemes.0.into_iter() {
|
||||
schemes.insert(scheme.as_str().to_string(), Arc::new(FdGuard::new(fd)));
|
||||
}
|
||||
schemes.insert("proc".to_string(), Arc::new(FdGuard::new(proc_fd)));
|
||||
schemes.insert("initfs".to_string(), Arc::new(FdGuard::new(initfs_fd)));
|
||||
|
||||
crate::initnsmgr::run(write_fd, schemes, scheme_creation_cap)
|
||||
scheme_creation_cap,
|
||||
kernel_schemes,
|
||||
true,
|
||||
|write_fd, socket, auth, mut kernel_schemes| {
|
||||
let event = kernel_schemes
|
||||
.0
|
||||
.remove(&GlobalSchemes::Event)
|
||||
.expect("failed to get event fd");
|
||||
drop(kernel_schemes);
|
||||
crate::procmgr::run(write_fd, socket, auth, event)
|
||||
},
|
||||
);
|
||||
|
||||
let (init_proc_fd, init_thr_fd) = unsafe { make_init(proc_fd) };
|
||||
let scheme_creation_cap_dup = scheme_creation_cap
|
||||
.dup(b"")
|
||||
.expect("failed to dup scheme creation cap");
|
||||
let (_, _, _, initns_fd) = spawn(
|
||||
"init namespace manager",
|
||||
auth,
|
||||
&this_thr_fd,
|
||||
scheme_creation_cap,
|
||||
kernel_schemes,
|
||||
false,
|
||||
|write_fd, socket, _, kernel_schemes| {
|
||||
let mut schemes = HashMap::default();
|
||||
for (scheme, fd) in kernel_schemes.0.into_iter() {
|
||||
schemes.insert(scheme.as_str().to_string(), Arc::new(fd));
|
||||
}
|
||||
schemes.insert(
|
||||
"proc".to_string(),
|
||||
// A bit dirty, but necessary as the parent process still needs access to it. Rust
|
||||
// doesn't know that the fd got cloned by fork.
|
||||
Arc::new(FdGuard::new(proc_fd.as_raw_fd())),
|
||||
);
|
||||
schemes.insert("initfs".to_string(), Arc::new(initfs_fd));
|
||||
|
||||
crate::initnsmgr::run(write_fd, socket, schemes, scheme_creation_cap_dup)
|
||||
},
|
||||
);
|
||||
|
||||
let (init_proc_fd, init_thr_fd) = unsafe { make_init(proc_fd.take()) };
|
||||
// from this point, this_thr_fd is no longer valid
|
||||
|
||||
const CWD: &[u8] = b"/scheme/initfs";
|
||||
let cwd_fd =
|
||||
FdGuard::new(syscall::openat(initfs_fd, "", O_STAT, 0).expect("failed to open cwd fd"))
|
||||
.to_upper()
|
||||
.unwrap();
|
||||
let cwd_fd = FdGuard::new(
|
||||
syscall::openat(initns_fd.as_raw_fd(), "/scheme/initfs", O_STAT, 0)
|
||||
.expect("failed to open cwd fd"),
|
||||
)
|
||||
.to_upper()
|
||||
.unwrap();
|
||||
let extrainfo = ExtraInfo {
|
||||
cwd: Some(CWD),
|
||||
sigprocmask: 0,
|
||||
@@ -186,14 +205,15 @@ pub fn main() -> ! {
|
||||
umask: redox_rt::sys::get_umask(),
|
||||
thr_fd: init_thr_fd.as_raw_fd(),
|
||||
proc_fd: init_proc_fd.as_raw_fd(),
|
||||
ns_fd: Some(initns_fd),
|
||||
ns_fd: Some(initns_fd.take()),
|
||||
cwd_fd: Some(cwd_fd.as_raw_fd()),
|
||||
};
|
||||
|
||||
let path = "/bin/init";
|
||||
let path = "/scheme/initfs/bin/init";
|
||||
|
||||
let image_file = FdGuard::new(
|
||||
syscall::openat(initfs_fd, path, O_RDONLY | O_CLOEXEC, 0).expect("failed to open init"),
|
||||
syscall::openat(extrainfo.ns_fd.unwrap(), path, O_RDONLY | O_CLOEXEC, 0)
|
||||
.expect("failed to open init"),
|
||||
)
|
||||
.to_upper()
|
||||
.unwrap();
|
||||
@@ -220,7 +240,7 @@ pub fn main() -> ! {
|
||||
let interp_cstr = CStr::from_bytes_with_nul(&interp_path).expect("interpreter not valid C str");
|
||||
let interp_file = FdGuard::new(
|
||||
syscall::openat(
|
||||
initns_fd, // initns, not initfs!
|
||||
extrainfo.ns_fd.unwrap(), // initns, not initfs!
|
||||
interp_cstr.to_str().expect("interpreter not UTF-8"),
|
||||
O_RDONLY | O_CLOEXEC,
|
||||
0,
|
||||
@@ -247,13 +267,24 @@ pub fn main() -> ! {
|
||||
|
||||
pub(crate) fn spawn(
|
||||
name: &str,
|
||||
auth: &FdGuard,
|
||||
auth: FdGuard,
|
||||
this_thr_fd: &FdGuardUpper,
|
||||
pipe_fd: usize,
|
||||
inner: impl FnOnce(FdGuard) -> !,
|
||||
) -> usize {
|
||||
scheme_creation_cap: FdGuard,
|
||||
kernel_schemes: KernelSchemeMap,
|
||||
nonblock: bool,
|
||||
inner: impl FnOnce(FdGuard, Socket, FdGuard, KernelSchemeMap) -> !,
|
||||
) -> (FdGuard, FdGuard, KernelSchemeMap, FdGuard) {
|
||||
let read = FdGuard::new(
|
||||
syscall::openat(pipe_fd, "", O_CLOEXEC, 0).expect("failed to open sync read pipe"),
|
||||
syscall::openat(
|
||||
kernel_schemes
|
||||
.get(GlobalSchemes::Pipe)
|
||||
.expect("failed to get pipe fd")
|
||||
.as_raw_fd(),
|
||||
"",
|
||||
O_CLOEXEC,
|
||||
0,
|
||||
)
|
||||
.expect("failed to open sync read pipe"),
|
||||
);
|
||||
|
||||
// The write pipe will not inherit O_CLOEXEC, but is closed by the daemon later.
|
||||
@@ -261,13 +292,22 @@ pub(crate) fn spawn(
|
||||
syscall::dup(read.as_raw_fd(), b"write").expect("failed to open sync write pipe"),
|
||||
);
|
||||
|
||||
match fork_impl(&ForkArgs::Init { this_thr_fd, auth }) {
|
||||
match fork_impl(&ForkArgs::Init {
|
||||
this_thr_fd,
|
||||
auth: &auth,
|
||||
}) {
|
||||
Err(err) => {
|
||||
panic!("Failed to fork in order to start {name}: {err}");
|
||||
}
|
||||
// Continue serving the scheme as the child.
|
||||
Ok(0) => {
|
||||
drop(read);
|
||||
|
||||
let socket = Socket::create_inner(scheme_creation_cap.as_raw_fd(), nonblock)
|
||||
.expect("failed to open proc scheme socket");
|
||||
drop(scheme_creation_cap);
|
||||
|
||||
inner(write, socket, auth, kernel_schemes)
|
||||
}
|
||||
// Return in order to execute init, as the parent.
|
||||
Ok(_) => {
|
||||
@@ -292,8 +332,12 @@ pub(crate) fn spawn(
|
||||
}
|
||||
}
|
||||
|
||||
return new_fd;
|
||||
(
|
||||
scheme_creation_cap,
|
||||
auth,
|
||||
kernel_schemes,
|
||||
FdGuard::new(new_fd),
|
||||
)
|
||||
}
|
||||
}
|
||||
inner(write)
|
||||
}
|
||||
|
||||
+1
-16
@@ -24,8 +24,6 @@ use syscall::error::*;
|
||||
use syscall::flag::*;
|
||||
use syscall::schemev2::NewFdFlags;
|
||||
|
||||
use crate::KernelSchemeMap;
|
||||
|
||||
enum Handle {
|
||||
Node(Node),
|
||||
SchemeRoot,
|
||||
@@ -384,24 +382,11 @@ impl SchemeSync for InitFsScheme {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(
|
||||
bytes: &'static [u8],
|
||||
sync_pipe: FdGuard,
|
||||
kernel_schemes: &KernelSchemeMap,
|
||||
scheme_creation_cap: usize,
|
||||
) -> ! {
|
||||
pub fn run(bytes: &'static [u8], sync_pipe: FdGuard, socket: Socket) -> ! {
|
||||
log::info!("bootstrap: starting initfs scheme");
|
||||
let mut state = SchemeState::new();
|
||||
let mut scheme = InitFsScheme::new(bytes);
|
||||
|
||||
let socket = Socket::create_inner(scheme_creation_cap, false)
|
||||
.expect("failed to open initfs scheme socket");
|
||||
let _ = syscall::close(scheme_creation_cap);
|
||||
|
||||
for fd in kernel_schemes.0.values() {
|
||||
let _ = syscall::close(*fd);
|
||||
}
|
||||
|
||||
// send open-capability to bootstrap
|
||||
let new_id = scheme.next_id();
|
||||
scheme.handles.insert(new_id, Handle::SchemeRoot);
|
||||
|
||||
@@ -489,14 +489,12 @@ where
|
||||
|
||||
pub fn run(
|
||||
sync_pipe: FdGuard,
|
||||
socket: Socket,
|
||||
schemes: HashMap<String, Arc<FdGuard>>,
|
||||
scheme_creation_cap: usize,
|
||||
scheme_creation_cap: FdGuard,
|
||||
) -> ! {
|
||||
let socket = Socket::create_inner(scheme_creation_cap, false)
|
||||
.expect("failed to open init namespace scheme socket");
|
||||
|
||||
let mut state = SchemeState::new();
|
||||
let mut scheme = NamespaceScheme::new(&socket, schemes, FdGuard::new(scheme_creation_cap));
|
||||
let mut scheme = NamespaceScheme::new(&socket, schemes, scheme_creation_cap);
|
||||
|
||||
// send namespace fd to bootstrap
|
||||
let new_id = scheme.next_id;
|
||||
|
||||
@@ -29,6 +29,7 @@ extern crate alloc;
|
||||
use core::cell::UnsafeCell;
|
||||
|
||||
use alloc::collections::btree_map::BTreeMap;
|
||||
use redox_rt::proc::FdGuard;
|
||||
use syscall::data::Map;
|
||||
use syscall::data::{GlobalSchemes, KernelSchemeInfo};
|
||||
use syscall::flag::MapFlags;
|
||||
@@ -135,18 +136,18 @@ unsafe impl alloc::alloc::GlobalAlloc for Allocator {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct KernelSchemeMap(BTreeMap<GlobalSchemes, usize>);
|
||||
pub struct KernelSchemeMap(BTreeMap<GlobalSchemes, FdGuard>);
|
||||
impl KernelSchemeMap {
|
||||
fn new(kernel_scheme_infos: &[KernelSchemeInfo]) -> Self {
|
||||
let mut map = BTreeMap::new();
|
||||
for info in kernel_scheme_infos {
|
||||
if let Some(scheme_id) = GlobalSchemes::try_from_raw(info.scheme_id) {
|
||||
map.insert(scheme_id, info.fd);
|
||||
map.insert(scheme_id, FdGuard::new(info.fd));
|
||||
}
|
||||
}
|
||||
Self(map)
|
||||
}
|
||||
fn get(&self, scheme: GlobalSchemes) -> Option<&usize> {
|
||||
fn get(&self, scheme: GlobalSchemes) -> Option<&FdGuard> {
|
||||
self.0.get(&scheme)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ use redox_scheme::{
|
||||
Socket, Tag,
|
||||
};
|
||||
use slab::Slab;
|
||||
use syscall::data::GlobalSchemes;
|
||||
use syscall::schemev2::NewFdFlags;
|
||||
use syscall::{
|
||||
CallFlags, ContextStatus, ContextVerb, CtxtStsBuf, EACCES, EAGAIN, EBADF, EBADFD, ECANCELED,
|
||||
@@ -39,8 +38,6 @@ use syscall::{
|
||||
sig_bit,
|
||||
};
|
||||
|
||||
use crate::KernelSchemeMap;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
enum VirtualId {
|
||||
KernelId(Id),
|
||||
@@ -48,31 +45,12 @@ enum VirtualId {
|
||||
InternalId(u64),
|
||||
}
|
||||
|
||||
pub fn run(
|
||||
write_fd: FdGuard,
|
||||
auth: &FdGuard,
|
||||
kernel_schemes: &KernelSchemeMap,
|
||||
scheme_creation_cap: usize,
|
||||
) -> ! {
|
||||
let socket =
|
||||
Socket::create_inner(scheme_creation_cap, true).expect("failed to open proc scheme socket");
|
||||
let _ = syscall::close(scheme_creation_cap);
|
||||
|
||||
pub fn run(write_fd: FdGuard, socket: Socket, auth: FdGuard, event: FdGuard) -> ! {
|
||||
// TODO?
|
||||
let socket_ident = socket.inner().raw();
|
||||
|
||||
let queue = RawEventQueue::new(
|
||||
*kernel_schemes
|
||||
.get(GlobalSchemes::Event)
|
||||
.expect("failed to get event fd"),
|
||||
)
|
||||
.expect("failed to create event queue");
|
||||
for (scheme, fd) in kernel_schemes.0.iter() {
|
||||
if *scheme == GlobalSchemes::Proc {
|
||||
continue;
|
||||
}
|
||||
let _ = syscall::close(*fd);
|
||||
}
|
||||
let queue = RawEventQueue::new(event.as_raw_fd()).expect("failed to create event queue");
|
||||
drop(event);
|
||||
|
||||
queue
|
||||
.subscribe(socket.inner().raw(), socket_ident, EventFlags::EVENT_READ)
|
||||
@@ -520,7 +498,7 @@ struct ProcScheme<'a> {
|
||||
next_id: ProcessId,
|
||||
|
||||
queue: &'a RawEventQueue,
|
||||
auth: &'a FdGuard,
|
||||
auth: FdGuard,
|
||||
}
|
||||
#[derive(Debug, Default)]
|
||||
struct Pgrp {
|
||||
@@ -598,7 +576,7 @@ impl RawEventQueue {
|
||||
}
|
||||
|
||||
impl<'a> ProcScheme<'a> {
|
||||
pub fn new(auth: &'a FdGuard, queue: &'a RawEventQueue) -> ProcScheme<'a> {
|
||||
pub fn new(auth: FdGuard, queue: &'a RawEventQueue) -> ProcScheme<'a> {
|
||||
ProcScheme {
|
||||
processes: HashMap::new(),
|
||||
groups: HashMap::new(),
|
||||
@@ -745,7 +723,7 @@ impl<'a> ProcScheme<'a> {
|
||||
}));
|
||||
if let Err(err) = new_process
|
||||
.borrow_mut()
|
||||
.sync_kernel_attrs(child_pid, self.auth)
|
||||
.sync_kernel_attrs(child_pid, &self.auth)
|
||||
{
|
||||
log::warn!("Failed to set kernel attrs when forking: {err}");
|
||||
}
|
||||
@@ -1611,7 +1589,7 @@ impl<'a> ProcScheme<'a> {
|
||||
if let Some(new_sgid) = new_sgid {
|
||||
proc.sgid = new_sgid;
|
||||
}
|
||||
if let Err(err) = proc.sync_kernel_attrs(pid, self.auth) {
|
||||
if let Err(err) = proc.sync_kernel_attrs(pid, &self.auth) {
|
||||
log::warn!("Failed to sync proc attrs in setresugid: {err}");
|
||||
}
|
||||
Ok(())
|
||||
@@ -2393,7 +2371,7 @@ impl<'a> ProcScheme<'a> {
|
||||
.borrow_mut();
|
||||
|
||||
proc.name = ArrayString::from_str(&new_name[..new_name.len().min(NAME_CAPAC)]).unwrap();
|
||||
if let Err(err) = proc.sync_kernel_attrs(pid, self.auth) {
|
||||
if let Err(err) = proc.sync_kernel_attrs(pid, &self.auth) {
|
||||
log::warn!("Failed to set kernel attrs when renaming proc: {err}");
|
||||
}
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user