bootstrap: restore upstream exec.rs from commit 372b200f
Our Red Bear patches had reverted the userspace fd allocation refactor
(commit 372b200f) in exec.rs. This caused FD tracking mismatches
between the userspace FILETABLE and the kernel fd table, resulting in
EEXIST errors and fork failures.
Restored the upstream version which correctly uses redox_rt::sys::*
functions (openat, dup, sys_call_ro) that go through the FILETABLE,
and openat_into_upper for pre-init FD allocation. Also includes the
filetable_binary_fd setup and same_process flag in ExtraInfo.
This commit is contained in:
+48
-45
@@ -6,10 +6,11 @@ use core::str::FromStr;
|
||||
use hashbrown::HashMap;
|
||||
use redox_scheme::Socket;
|
||||
|
||||
use syscall::CallFlags;
|
||||
use libredox::protocol::O_CLOEXEC;
|
||||
use syscall::data::{GlobalSchemes, KernelSchemeInfo};
|
||||
use syscall::flag::{O_CLOEXEC, O_RDONLY, O_STAT};
|
||||
use syscall::{EINTR, Error};
|
||||
use syscall::flag::{O_DIRECTORY, O_RDONLY, O_STAT};
|
||||
use syscall::CallFlags;
|
||||
use syscall::{Error, EINTR};
|
||||
|
||||
use redox_rt::proc::*;
|
||||
|
||||
@@ -26,7 +27,7 @@ impl log::Log for Logger {
|
||||
let line = record.line().unwrap_or(0);
|
||||
let level = record.level();
|
||||
let msg = record.args();
|
||||
let _ = libredox::call::write(
|
||||
let _ = syscall::write(
|
||||
1,
|
||||
alloc::format!("[{file}:{line} {level}] {msg}\n").as_bytes(),
|
||||
);
|
||||
@@ -72,13 +73,13 @@ pub fn main() -> ! {
|
||||
let mut env_bytes = [0_u8; 4096];
|
||||
let mut envs = {
|
||||
let fd = FdGuard::new(
|
||||
libredox::call::openat(
|
||||
redox_rt::sys::openat(
|
||||
kernel_schemes
|
||||
.get(GlobalSchemes::Sys)
|
||||
.expect("failed to get sys fd")
|
||||
.as_raw_fd(),
|
||||
"env",
|
||||
(O_RDONLY | O_CLOEXEC) as i32,
|
||||
O_RDONLY | O_CLOEXEC,
|
||||
0,
|
||||
)
|
||||
.expect("bootstrap: failed to open env"),
|
||||
@@ -207,12 +208,16 @@ pub fn main() -> ! {
|
||||
// from this point, this_thr_fd is no longer valid
|
||||
|
||||
const CWD: &[u8] = b"/scheme/initfs";
|
||||
let cwd_fd = FdGuard::new(
|
||||
libredox::call::openat(initns_fd.as_raw_fd(), "/scheme/initfs", O_STAT as i32, 0)
|
||||
.expect("failed to open cwd fd"),
|
||||
)
|
||||
.to_upper()
|
||||
.unwrap();
|
||||
|
||||
let initfs_root_fd = initns_fd
|
||||
.openat_into_upper("/scheme/initfs", O_DIRECTORY, 0)
|
||||
.expect("failed to open initfs root fd");
|
||||
let cwd_fd = initfs_root_fd
|
||||
.openat_into_upper("", O_STAT, 0)
|
||||
.expect("failed to open cwd fd");
|
||||
let filetable_binary_fd = init_thr_fd
|
||||
.dup_into_upper(b"filetable-binary")
|
||||
.expect("faild to create filetable-binary fd");
|
||||
let extrainfo = ExtraInfo {
|
||||
cwd: Some(CWD),
|
||||
sigprocmask: 0,
|
||||
@@ -222,25 +227,23 @@ pub fn main() -> ! {
|
||||
proc_fd: init_proc_fd.as_raw_fd(),
|
||||
ns_fd: Some(initns_fd.take()),
|
||||
cwd_fd: Some(cwd_fd.as_raw_fd()),
|
||||
filetable_fd: None,
|
||||
same_process: false,
|
||||
filetable_fd: Some(filetable_binary_fd.as_raw_fd()),
|
||||
same_process: true,
|
||||
};
|
||||
|
||||
let path = "/scheme/initfs/bin/init";
|
||||
let exe_path = "/scheme/initfs/bin/init";
|
||||
let exe_reference = "bin/init";
|
||||
|
||||
let image_file = FdGuard::new(
|
||||
libredox::call::openat(extrainfo.ns_fd.unwrap(), path, (O_RDONLY | O_CLOEXEC) as i32, 0)
|
||||
.expect("failed to open init"),
|
||||
)
|
||||
.to_upper()
|
||||
.unwrap();
|
||||
let image_file = initfs_root_fd
|
||||
.openat_into_upper(exe_reference, O_RDONLY | O_CLOEXEC, 0)
|
||||
.expect("failed to open init");
|
||||
|
||||
let exe_path = alloc::format!("/scheme/initfs{}", path);
|
||||
drop(initfs_root_fd);
|
||||
|
||||
let Some(FexecResult::Interp {
|
||||
let FexecResult::Interp {
|
||||
path: interp_path,
|
||||
interp_override,
|
||||
}) = fexec_impl(
|
||||
} = fexec_impl(
|
||||
image_file,
|
||||
init_thr_fd,
|
||||
init_proc_fd,
|
||||
@@ -250,29 +253,33 @@ pub fn main() -> ! {
|
||||
&extrainfo,
|
||||
None,
|
||||
)
|
||||
.map_err(|e| {
|
||||
let _ = libredox::call::write(1, alloc::format!("fexec_impl failed: {}\n", e).as_bytes());
|
||||
e
|
||||
})
|
||||
.expect("failed to execute init")
|
||||
else {
|
||||
panic!("fexec_impl returned None for init");
|
||||
};
|
||||
.ok()
|
||||
.flatten()
|
||||
.expect("failed to execute init");
|
||||
|
||||
// According to elf(5), PT_INTERP requires that the interpreter path be
|
||||
// null-terminated. Violating this should therefore give the "format error" ENOEXEC.
|
||||
let interp_cstr = CStr::from_bytes_with_nul(&interp_path).expect("interpreter not valid C str");
|
||||
let interp_file = FdGuard::new(
|
||||
libredox::call::openat(
|
||||
let interp_path = interp_cstr.to_str().expect("interpreter not UTF-8");
|
||||
let root_fd = FdGuard::new(
|
||||
redox_rt::sys::openat_into_upper(
|
||||
extrainfo.ns_fd.unwrap(), // initns, not initfs!
|
||||
interp_cstr.to_str().expect("interpreter not UTF-8"),
|
||||
(O_RDONLY | O_CLOEXEC) as i32,
|
||||
interp_path,
|
||||
O_RDONLY | O_CLOEXEC,
|
||||
0,
|
||||
)
|
||||
.expect("failed to open dynamic linker"),
|
||||
.expect("failed to open root fd"),
|
||||
)
|
||||
.to_upper()
|
||||
.unwrap();
|
||||
let redox_path = redox_path::RedoxPath::from_absolute(interp_path)
|
||||
.expect("interpreter path is not a Scheme-rooted path");
|
||||
let (_, reference) = redox_path
|
||||
.as_parts()
|
||||
.expect("redox_path is not scheme root path");
|
||||
let interp_file = root_fd
|
||||
.openat_into_upper(reference.as_ref(), O_RDONLY | O_CLOEXEC, 0)
|
||||
.expect("failed to open dynamic linker");
|
||||
|
||||
fexec_impl(
|
||||
interp_file,
|
||||
@@ -299,13 +306,13 @@ pub(crate) fn spawn(
|
||||
inner: impl FnOnce(FdGuard, Socket, FdGuard, KernelSchemeMap) -> !,
|
||||
) -> (FdGuard, FdGuard, KernelSchemeMap, FdGuard) {
|
||||
let read = FdGuard::new(
|
||||
libredox::call::openat(
|
||||
redox_rt::sys::openat(
|
||||
kernel_schemes
|
||||
.get(GlobalSchemes::Pipe)
|
||||
.expect("failed to get pipe fd")
|
||||
.as_raw_fd(),
|
||||
"",
|
||||
O_CLOEXEC as i32,
|
||||
O_CLOEXEC,
|
||||
0,
|
||||
)
|
||||
.expect("failed to open sync read pipe"),
|
||||
@@ -313,7 +320,7 @@ pub(crate) fn spawn(
|
||||
|
||||
// The write pipe will not inherit O_CLOEXEC, but is closed by the daemon later.
|
||||
let write = FdGuard::new(
|
||||
libredox::call::dup(read.as_raw_fd(), b"write").expect("failed to open sync write pipe"),
|
||||
redox_rt::sys::dup(read.as_raw_fd(), b"write").expect("failed to open sync write pipe"),
|
||||
);
|
||||
|
||||
match fork_impl(&ForkArgs::Init {
|
||||
@@ -325,15 +332,11 @@ pub(crate) fn spawn(
|
||||
}
|
||||
// Continue serving the scheme as the child.
|
||||
Ok(0) => {
|
||||
let _ = libredox::call::write(1, b"SP:0\n");
|
||||
drop(read);
|
||||
let _ = libredox::call::write(1, b"SP:1\n");
|
||||
|
||||
let socket = Socket::create_inner(scheme_creation_cap.as_raw_fd(), nonblock)
|
||||
.expect("failed to open proc scheme socket");
|
||||
let _ = libredox::call::write(1, b"SP:2\n");
|
||||
drop(scheme_creation_cap);
|
||||
let _ = libredox::call::write(1, b"SP:3\n");
|
||||
|
||||
inner(write, socket, auth, kernel_schemes)
|
||||
}
|
||||
@@ -349,7 +352,7 @@ pub(crate) fn spawn(
|
||||
)
|
||||
};
|
||||
loop {
|
||||
match syscall::call_ro(
|
||||
match redox_rt::sys::sys_call_ro(
|
||||
read.as_raw_fd(),
|
||||
fd_bytes,
|
||||
CallFlags::FD | CallFlags::FD_UPPER,
|
||||
|
||||
Reference in New Issue
Block a user