aedc416f0c
The bootstrap's start.rs used libredox::call::openat which resolved to the bootstrap's own redox_openat_v1 in initfs.rs, calling syscall::openat (SYS_OPENAT). This let the kernel allocate POSIX FDs 0,1,2 for stdin/stdout/stderr, but the userspace FILETABLE was never updated. Later, exec.rs called auth.dup(b'cur-context') via redox_rt::sys::dup, which asked the empty FILETABLE for a free slot (returning 0), then passed it to SYS_DUP_INTO. The kernel rejected it with EEXIST because posix_fdtbl[0] was already occupied by stdin. Fix: use syscall::openat_into to directly specify FD slots 0,1,2 in start.rs, and use syscall::dup_into with a computed FD index for cur-context in exec.rs. Both bypass the FILETABLE, which is only populated later by redox_rt::initialize_freestanding.
84 lines
2.5 KiB
Rust
84 lines
2.5 KiB
Rust
use syscall::flag::MapFlags;
|
|
|
|
mod offsets {
|
|
unsafe extern "C" {
|
|
static __text_start: u8;
|
|
static __text_end: u8;
|
|
static __rodata_start: u8;
|
|
static __rodata_end: u8;
|
|
static __data_start: u8;
|
|
static __bss_end: u8;
|
|
}
|
|
pub fn text() -> (usize, usize) {
|
|
unsafe {
|
|
(
|
|
&__text_start as *const u8 as usize,
|
|
&__text_end as *const u8 as usize,
|
|
)
|
|
}
|
|
}
|
|
pub fn rodata() -> (usize, usize) {
|
|
unsafe {
|
|
(
|
|
&__rodata_start as *const u8 as usize,
|
|
&__rodata_end as *const u8 as usize,
|
|
)
|
|
}
|
|
}
|
|
pub fn data_and_bss() -> (usize, usize) {
|
|
unsafe {
|
|
(
|
|
&__data_start as *const u8 as usize,
|
|
&__bss_end as *const u8 as usize,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn start() -> ! {
|
|
let (text_start, text_end) = offsets::text();
|
|
let (rodata_start, rodata_end) = offsets::rodata();
|
|
let (data_start, data_end) = offsets::data_and_bss();
|
|
|
|
let debug_fd = syscall::UPPER_FDTBL_TAG + syscall::data::GlobalSchemes::Debug as usize;
|
|
let _ = syscall::openat_into(debug_fd, 0, "", syscall::O_RDONLY, 0);
|
|
let _ = syscall::openat_into(debug_fd, 1, "", syscall::O_WRONLY, 0);
|
|
let _ = syscall::openat_into(debug_fd, 2, "", syscall::O_WRONLY, 0);
|
|
|
|
unsafe {
|
|
let _ = syscall::mprotect(4096, 4096, MapFlags::PROT_READ | MapFlags::MAP_PRIVATE)
|
|
.expect("mprotect failed for initfs header page");
|
|
|
|
let _ = syscall::mprotect(
|
|
text_start,
|
|
text_end - text_start,
|
|
MapFlags::PROT_READ | MapFlags::PROT_EXEC | MapFlags::MAP_PRIVATE,
|
|
)
|
|
.expect("mprotect failed for .text");
|
|
|
|
let _ = syscall::mprotect(
|
|
rodata_start,
|
|
rodata_end - rodata_start,
|
|
MapFlags::PROT_READ | MapFlags::MAP_PRIVATE,
|
|
)
|
|
.expect("mprotect failed for .rodata");
|
|
|
|
let _ = syscall::mprotect(
|
|
data_start,
|
|
data_end - data_start,
|
|
MapFlags::PROT_READ | MapFlags::PROT_WRITE | MapFlags::MAP_PRIVATE,
|
|
)
|
|
.expect("mprotect failed for .data/.bss");
|
|
|
|
let _ = syscall::mprotect(
|
|
data_end,
|
|
crate::arch::STACK_START - data_end,
|
|
MapFlags::PROT_READ | MapFlags::MAP_PRIVATE,
|
|
)
|
|
.expect("mprotect failed for rest of memory");
|
|
}
|
|
|
|
crate::exec::main();
|
|
}
|