From 01d2f4f036fc027b077e520d12e11caf1cca48fe Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 26 Jun 2023 20:02:01 +0200 Subject: [PATCH 1/8] WIP: Use fmap in program loader. --- src/platform/redox/redox-exec/src/lib.rs | 188 ++++++++++++++--------- 1 file changed, 113 insertions(+), 75 deletions(-) diff --git a/src/platform/redox/redox-exec/src/lib.rs b/src/platform/redox/redox-exec/src/lib.rs index f7527e4627..e5b24c3746 100644 --- a/src/platform/redox/redox-exec/src/lib.rs +++ b/src/platform/redox/redox-exec/src/lib.rs @@ -1,5 +1,6 @@ #![no_std] -#![feature(array_chunks)] +#![feature(array_chunks, int_roundings)] +#![forbid(unreachable_patterns)] extern crate alloc; @@ -22,7 +23,7 @@ use goblin::elf64::{ use syscall::{ error::*, flag::{MapFlags, SEEK_SET}, - PAGE_SIZE, + PAGE_SIZE, Map, }; pub use self::arch::*; @@ -82,7 +83,6 @@ where let current_addrspace_fd = FdGuard::new(syscall::dup(*open_via_dup, b"addrspace")?); FdGuard::new(syscall::dup(*current_addrspace_fd, b"empty")?) }; - let memory_fd = FdGuard::new(syscall::dup(*grants_fd, b"mem")?); // Never allow more than 1 MiB of program headers. const MAX_PH_SIZE: usize = 1024 * 1024; @@ -105,9 +105,6 @@ where |o| core::mem::take(&mut o.tree), ); - const BUFSZ: usize = 1024 * 256; - let mut buf = vec![0_u8; BUFSZ]; - read_all(*image_file as usize, Some(header.e_phoff as u64), phs) .map_err(|_| Error::new(EIO))?; @@ -124,14 +121,6 @@ where flags |= syscall::PROT_WRITE; } - let voff = segment.p_vaddr as usize % PAGE_SIZE; - let vaddr = segment.p_vaddr as usize - voff; - let size = (segment.p_memsz as usize + voff + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE; - - if segment.p_filesz > segment.p_memsz { - return Err(Error::new(ENOEXEC)); - } - #[forbid(unreachable_patterns)] match segment.p_type { // PT_INTERP must come before any PT_LOAD, so we don't have to iterate twice. PT_INTERP => { @@ -157,28 +146,70 @@ where }); } PT_LOAD => { + let voff = segment.p_vaddr as usize % PAGE_SIZE; + let vaddr = segment.p_vaddr as usize - voff; + + // TODO: Use CoW mmap from the underlying filesystem. + let _poff = segment.p_offset - voff as u64; + + let file_page_count = (segment.p_filesz as usize + voff).div_ceil(PAGE_SIZE); + let zero_page_count = ((segment.p_memsz as usize + voff) - file_page_count * PAGE_SIZE).div_ceil(PAGE_SIZE); + let total_page_count = file_page_count + zero_page_count; + + // The case where segments overlap so that they share one page, is not handled. + // TODO: Should it be? + + if segment.p_filesz > segment.p_memsz { + return Err(Error::new(ENOEXEC)); + } + allocate_remote( &grants_fd, memory_scheme_fd, vaddr, - size, - syscall::PROT_READ | syscall::PROT_WRITE, + total_page_count * PAGE_SIZE, + flags, )?; syscall::lseek(*image_file as usize, segment.p_offset as isize, SEEK_SET) .map_err(|_| Error::new(EIO))?; - syscall::lseek(*memory_fd, segment.p_vaddr as isize, SEEK_SET) - .map_err(|_| Error::new(EIO))?; - for size in core::iter::repeat(buf.len()) - .take((segment.p_filesz as usize) / buf.len()) - .chain(Some((segment.p_filesz as usize) % buf.len())) - { - read_all(*image_file as usize, None, &mut buf[..size]) - .map_err(|_| Error::new(EIO))?; - let _ = - syscall::write(*memory_fd, &buf[..size]).map_err(|_| Error::new(EIO))?; + // TODO: Unless the calling process if *very* memory-constrained, the max amount of + // pages per iteration has no limit other than the time it takes to setup page + // tables. + // + // TODO: Reserve PAGES_PER_ITER "scratch pages" of virtual memory for that type of + // situation? + const PAGES_PER_ITER: usize = 64; + + for page_idx in (0..file_page_count).step_by(PAGES_PER_ITER) { + let pages_in_this_group = core::cmp::min(PAGES_PER_ITER, file_page_count - page_idx); + + if pages_in_this_group == 0 { break } + + let dst_memory = unsafe { + let base = syscall::fmap(*grants_fd, &Map { + offset: vaddr + page_idx * PAGE_SIZE, + size: pages_in_this_group * PAGE_SIZE, + // TODO: MAP_FIXED (without MAP_FIXED_NOREPLACE) to a fixed offset, to + // avoid mapping/unmapping repeatedly? + flags: MapFlags::PROT_WRITE, + address: 0, // let the kernel choose + })? as *mut u8; + + core::slice::from_raw_parts_mut(base, pages_in_this_group * PAGE_SIZE) + }; + // TODO: Are &mut [u8] and &mut [[u8; PAGE_SIZE]] interchangeable (if the + // lengths are aligned, obviously)? + + let voff_here = if page_idx == 0 { voff } else { 0 }; + let size_here = if pages_in_this_group == PAGES_PER_ITER { PAGES_PER_ITER * PAGE_SIZE } else { (file_page_count) * PAGE_SIZE + (segment.p_filesz as usize % PAGE_SIZE) } - voff_here; + + read_all(*image_file, None, &mut dst_memory[voff_here..][..size_here])?; + + unsafe { syscall::funmap(dst_memory.as_ptr() as usize, dst_memory.len())?; } } - mprotect_remote(&grants_fd, vaddr, size, flags)?; + // file_page_count..file_page_count + zero_page_count are already zero-initialized + // by the kernel. if !tree .range(..=vaddr) @@ -186,7 +217,7 @@ where .filter(|(start, size)| **start + **size > vaddr) .is_some() { - tree.insert(vaddr, size); + tree.insert(vaddr, total_page_count * PAGE_SIZE); } } _ => continue, @@ -202,11 +233,33 @@ where )?; tree.insert(STACK_TOP - STACK_SIZE, STACK_SIZE); - let mut sp = STACK_TOP - 256; + let mut sp = STACK_TOP; + let mut stack_page = None; let mut push = |word: usize| { + let old_page_no = sp / PAGE_SIZE; sp -= size_of::(); - write_all(*memory_fd, Some(sp as u64), &usize::to_ne_bytes(word)) + let new_page_no = sp / PAGE_SIZE; + let new_page_off = sp % PAGE_SIZE; + + if old_page_no != new_page_no { + if let Some(old_page) = stack_page { + // TODO: fmap/funmap RAII guard + unsafe { syscall::funmap(old_page, PAGE_SIZE)?; } + } + let page = *stack_page.insert(unsafe { syscall::fmap(*grants_fd, &Map { + offset: new_page_no * PAGE_SIZE, + size: PAGE_SIZE, + flags: MapFlags::PROT_WRITE, + address: 0, // let kernel decide + })? }); + + unsafe { + (page as *mut u8).add(new_page_off).cast::().write(word); + } + } + + Ok(()) }; let pheaders_to_convey = if let Some(ref r#override) = interp_override { @@ -224,7 +277,20 @@ where pheaders_size_aligned, MapFlags::PROT_READ | MapFlags::PROT_WRITE, )?; - write_all(*memory_fd, Some(pheaders as u64), &pheaders_to_convey)?; + unsafe { + let base = syscall::fmap(*grants_fd, &Map { + offset: pheaders, + size: pheaders_size_aligned, + flags: MapFlags::PROT_WRITE, + address: 0, + })?; + + let dst = core::slice::from_raw_parts_mut(base as *mut u8, pheaders_size_aligned); + + dst[..pheaders_to_convey.len()].copy_from_slice(pheaders_to_convey); + + syscall::funmap(base, pheaders_size_aligned)?; + } mprotect_remote( &grants_fd, pheaders, @@ -275,9 +341,20 @@ where let mut argc = 0; { - let mut append = |source_slice: &[u8]| { + let mut append = |source_slice: &[u8]| unsafe { + // TODO let address = target_args_env_address + offset; - write_all(*memory_fd, Some(address as u64), source_slice)?; + + let containing_page = address.div_ceil(PAGE_SIZE) * PAGE_SIZE; + let displacement = address - containing_page; + let size = source_slice.len() + displacement; + let aligned_size = size.next_multiple_of(PAGE_SIZE); + + let base = syscall::fmap(*grants_fd, &Map { offset: containing_page, size: aligned_size, flags: MapFlags::PROT_WRITE, address: 0 })?; + let dst = core::slice::from_raw_parts_mut(base as *mut u8, aligned_size); + + dst[displacement..][..source_slice.len()].copy_from_slice(source_slice); + offset += source_slice.len() + 1; Ok(address) }; @@ -596,51 +673,12 @@ fn fork_inner(initial_rsp: *mut usize) -> Result { // CoW-duplicate address space. { - let cur_addr_space_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"addrspace")?); - - // FIXME: Find mappings which use external file descriptors - - let new_addr_space_fd = FdGuard::new(syscall::dup(*cur_addr_space_fd, b"exclusive")?); - - let mut buf = vec![0_u8; 4096]; - let mut bytes_read = 0; - - loop { - let new_bytes_read = syscall::read(*cur_addr_space_fd, &mut buf[bytes_read..])?; - - if new_bytes_read == 0 { - break; - } - - bytes_read += new_bytes_read; - } - let bytes = &buf[..bytes_read]; - - for struct_bytes in bytes.array_chunks::<{ size_of::() * 4 }>() { - let mut words = struct_bytes - .array_chunks::<{ size_of::() }>() - .copied() - .map(usize::from_ne_bytes); - - let addr = words.next().unwrap(); - let size = words.next().unwrap(); - let flags = words.next().unwrap(); - let offset = words.next().unwrap(); - - if flags & 0x8000_0000 == 0 { - continue; - } - let map_flags = MapFlags::from_bits_truncate(flags); - - let grant_fd = FdGuard::new(syscall::dup( - *cur_addr_space_fd, - alloc::format!("grant-{:x}", addr).as_bytes(), - )?); - mmap_remote(&new_addr_space_fd, &grant_fd, offset, addr, size, map_flags)?; - } let new_addr_space_sel_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"current-addrspace")?); + let cur_addr_space_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"addrspace")?); + let new_addr_space_fd = FdGuard::new(syscall::dup(*cur_addr_space_fd, b"exclusive")?); + let buf = create_set_addr_space_buf( *new_addr_space_fd, __relibc_internal_fork_ret as usize, From d164d84c7f7c52ca2efdaae2fbeca2073d18566b Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 26 Jun 2023 20:19:01 +0200 Subject: [PATCH 2/8] Fix address+size calculation in redox-exec. --- src/platform/redox/redox-exec/src/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/platform/redox/redox-exec/src/lib.rs b/src/platform/redox/redox-exec/src/lib.rs index e5b24c3746..b2fd00d477 100644 --- a/src/platform/redox/redox-exec/src/lib.rs +++ b/src/platform/redox/redox-exec/src/lib.rs @@ -182,7 +182,7 @@ where const PAGES_PER_ITER: usize = 64; for page_idx in (0..file_page_count).step_by(PAGES_PER_ITER) { - let pages_in_this_group = core::cmp::min(PAGES_PER_ITER, file_page_count - page_idx); + let pages_in_this_group = core::cmp::min(PAGES_PER_ITER, file_page_count - page_idx * PAGES_PER_ITER); if pages_in_this_group == 0 { break } @@ -202,7 +202,11 @@ where // lengths are aligned, obviously)? let voff_here = if page_idx == 0 { voff } else { 0 }; - let size_here = if pages_in_this_group == PAGES_PER_ITER { PAGES_PER_ITER * PAGE_SIZE } else { (file_page_count) * PAGE_SIZE + (segment.p_filesz as usize % PAGE_SIZE) } - voff_here; + let size_here = if pages_in_this_group == PAGES_PER_ITER { + PAGES_PER_ITER * PAGE_SIZE + } else { + file_page_count.div_floor(PAGES_PER_ITER) * PAGES_PER_ITER * PAGE_SIZE + (segment.p_filesz as usize % PAGE_SIZE) + } - voff_here; read_all(*image_file, None, &mut dst_memory[voff_here..][..size_here])?; From 29d265c11c497dc4241d0b3353c3699d45aefab9 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 26 Jun 2023 21:27:56 +0200 Subject: [PATCH 3/8] mmap RAII guard. --- src/platform/redox/redox-exec/src/lib.rs | 123 +++++++++++++++-------- 1 file changed, 79 insertions(+), 44 deletions(-) diff --git a/src/platform/redox/redox-exec/src/lib.rs b/src/platform/redox/redox-exec/src/lib.rs index b2fd00d477..6c7e896a98 100644 --- a/src/platform/redox/redox-exec/src/lib.rs +++ b/src/platform/redox/redox-exec/src/lib.rs @@ -1,5 +1,5 @@ #![no_std] -#![feature(array_chunks, int_roundings)] +#![feature(array_chunks, int_roundings, slice_ptr_get)] #![forbid(unreachable_patterns)] extern crate alloc; @@ -182,22 +182,23 @@ where const PAGES_PER_ITER: usize = 64; for page_idx in (0..file_page_count).step_by(PAGES_PER_ITER) { - let pages_in_this_group = core::cmp::min(PAGES_PER_ITER, file_page_count - page_idx * PAGES_PER_ITER); + // Use commented out lines to trigger kernel bug (FIXME). + + //let pages_in_this_group = core::cmp::min(PAGES_PER_ITER, file_page_count - page_idx * PAGES_PER_ITER); + let pages_in_this_group = core::cmp::min(PAGES_PER_ITER, file_page_count - page_idx); if pages_in_this_group == 0 { break } - let dst_memory = unsafe { - let base = syscall::fmap(*grants_fd, &Map { - offset: vaddr + page_idx * PAGE_SIZE, - size: pages_in_this_group * PAGE_SIZE, - // TODO: MAP_FIXED (without MAP_FIXED_NOREPLACE) to a fixed offset, to - // avoid mapping/unmapping repeatedly? - flags: MapFlags::PROT_WRITE, - address: 0, // let the kernel choose - })? as *mut u8; + let mut mmap_guard = MmapGuard::map(*grants_fd, &Map { + offset: vaddr + page_idx * PAGE_SIZE, + size: pages_in_this_group * PAGE_SIZE, + // TODO: MAP_FIXED (without MAP_FIXED_NOREPLACE) to a fixed offset, to + // avoid mapping/unmapping repeatedly? + flags: MapFlags::PROT_WRITE, + address: 0, // let the kernel choose + })?; - core::slice::from_raw_parts_mut(base, pages_in_this_group * PAGE_SIZE) - }; + let dst_memory = unsafe { &mut *mmap_guard.as_mut_ptr_slice() }; // TODO: Are &mut [u8] and &mut [[u8; PAGE_SIZE]] interchangeable (if the // lengths are aligned, obviously)? @@ -205,12 +206,11 @@ where let size_here = if pages_in_this_group == PAGES_PER_ITER { PAGES_PER_ITER * PAGE_SIZE } else { - file_page_count.div_floor(PAGES_PER_ITER) * PAGES_PER_ITER * PAGE_SIZE + (segment.p_filesz as usize % PAGE_SIZE) + (pages_in_this_group - 1) * PAGE_SIZE + (segment.p_filesz as usize % PAGE_SIZE) + //pages_in_this_group.div_floor(PAGES_PER_ITER) * PAGES_PER_ITER * PAGE_SIZE + (segment.p_filesz as usize % PAGE_SIZE) } - voff_here; read_all(*image_file, None, &mut dst_memory[voff_here..][..size_here])?; - - unsafe { syscall::funmap(dst_memory.as_ptr() as usize, dst_memory.len())?; } } // file_page_count..file_page_count + zero_page_count are already zero-initialized // by the kernel. @@ -238,7 +238,7 @@ where tree.insert(STACK_TOP - STACK_SIZE, STACK_SIZE); let mut sp = STACK_TOP; - let mut stack_page = None; + let mut stack_page = Option::::None; let mut push = |word: usize| { let old_page_no = sp / PAGE_SIZE; @@ -247,20 +247,24 @@ where let new_page_off = sp % PAGE_SIZE; if old_page_no != new_page_no { - if let Some(old_page) = stack_page { - // TODO: fmap/funmap RAII guard - unsafe { syscall::funmap(old_page, PAGE_SIZE)?; } - } - let page = *stack_page.insert(unsafe { syscall::fmap(*grants_fd, &Map { + stack_page = None; + } + + let page = if let Some(ref mut page) = stack_page { + page.as_mut_ptr_slice() + } else { + let new = MmapGuard::map(*grants_fd, &Map { offset: new_page_no * PAGE_SIZE, size: PAGE_SIZE, flags: MapFlags::PROT_WRITE, address: 0, // let kernel decide - })? }); + })?; - unsafe { - (page as *mut u8).add(new_page_off).cast::().write(word); - } + stack_page.insert(new).as_mut_ptr_slice() + }; + + unsafe { + page.as_mut_ptr().add(new_page_off).cast::().write(word); } Ok(()) @@ -271,7 +275,7 @@ where } else { &*phs_raw }; - let pheaders_size_aligned = (pheaders_to_convey.len() + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE; + let pheaders_size_aligned = pheaders_to_convey.len().next_multiple_of(PAGE_SIZE); let pheaders = find_free_target_addr(&tree, pheaders_size_aligned).ok_or(Error::new(ENOMEM))?; tree.insert(pheaders, pheaders_size_aligned); allocate_remote( @@ -282,18 +286,14 @@ where MapFlags::PROT_READ | MapFlags::PROT_WRITE, )?; unsafe { - let base = syscall::fmap(*grants_fd, &Map { + let mut base = MmapGuard::map(*grants_fd, &Map { offset: pheaders, size: pheaders_size_aligned, flags: MapFlags::PROT_WRITE, address: 0, })?; - let dst = core::slice::from_raw_parts_mut(base as *mut u8, pheaders_size_aligned); - - dst[..pheaders_to_convey.len()].copy_from_slice(pheaders_to_convey); - - syscall::funmap(base, pheaders_size_aligned)?; + (&mut *base.as_mut_ptr_slice())[..pheaders_to_convey.len()].copy_from_slice(pheaders_to_convey); } mprotect_remote( &grants_fd, @@ -327,8 +327,7 @@ where let total_args_envs_auxvpointee_size = total_args_envs_size + extrainfo.cwd.map_or(0, |s| s.len() + 1); - let args_envs_size_aligned = - (total_args_envs_auxvpointee_size + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE; + let args_envs_size_aligned = total_args_envs_auxvpointee_size.next_multiple_of(PAGE_SIZE); let target_args_env_address = find_free_target_addr(&tree, args_envs_size_aligned).ok_or(Error::new(ENOMEM))?; allocate_remote( @@ -349,15 +348,15 @@ where // TODO let address = target_args_env_address + offset; - let containing_page = address.div_ceil(PAGE_SIZE) * PAGE_SIZE; - let displacement = address - containing_page; - let size = source_slice.len() + displacement; - let aligned_size = size.next_multiple_of(PAGE_SIZE); + if !source_slice.is_empty() { + let containing_page = address.div_floor(PAGE_SIZE) * PAGE_SIZE; + let displacement = address - containing_page; + let size = source_slice.len() + displacement; + let aligned_size = size.next_multiple_of(PAGE_SIZE); - let base = syscall::fmap(*grants_fd, &Map { offset: containing_page, size: aligned_size, flags: MapFlags::PROT_WRITE, address: 0 })?; - let dst = core::slice::from_raw_parts_mut(base as *mut u8, aligned_size); - - dst[displacement..][..source_slice.len()].copy_from_slice(source_slice); + let mut base = MmapGuard::map(*grants_fd, &Map { offset: containing_page, size: aligned_size, flags: MapFlags::PROT_WRITE, address: 0 })?; + (unsafe { &mut *base.as_mut_ptr_slice() })[displacement..][..source_slice.len()].copy_from_slice(source_slice); + } offset += source_slice.len() + 1; Ok(address) @@ -409,11 +408,12 @@ where if interp_override.is_some() { let mmap_min_fd = FdGuard::new(syscall::dup(*grants_fd, b"mmap-min-addr")?); let last_addr = tree.iter().rev().nth(1).map_or(0, |(off, len)| *off + *len); - let aligned_last_addr = (last_addr + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE; + let aligned_last_addr = last_addr.next_multiple_of(PAGE_SIZE); let _ = syscall::write(*mmap_min_fd, &usize::to_ne_bytes(aligned_last_addr)); } let addrspace_selection_fd = FdGuard::new(syscall::dup(*open_via_dup, b"current-addrspace")?); + let _ = syscall::write(1, alloc::format!("ENTER {:p} {:p}\n", header.e_entry as *const u8, sp as *const u8).as_bytes()); let _ = syscall::write( *addrspace_selection_fd, @@ -574,6 +574,41 @@ fn find_free_target_addr(tree: &BTreeMap, size: usize) -> Option Result { + Ok(Self { + size: map.size, + taken: false, + + base: unsafe { syscall::fmap(fd, map)? }, + }) + } + pub fn addr(&self) -> usize { + self.base + } + pub fn len(&self) -> usize { + self.size + } + pub fn as_mut_ptr_slice(&mut self) -> *mut [u8] { + core::ptr::slice_from_raw_parts_mut(self.base as *mut u8, self.size) + } + pub fn take(&mut self) { + self.taken = true; + } +} +impl Drop for MmapGuard { + fn drop(&mut self) { + if !self.taken { + let _ = unsafe { syscall::funmap(self.base, self.size) }; + } + } +} + pub struct FdGuard { fd: usize, taken: bool, From 76c948b5627058a8c3026657ef7cc148ee0d1248 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Tue, 27 Jun 2023 15:28:33 +0200 Subject: [PATCH 4/8] Succeed at loading init! --- src/platform/redox/redox-exec/src/lib.rs | 139 ++++++++++++++--------- 1 file changed, 84 insertions(+), 55 deletions(-) diff --git a/src/platform/redox/redox-exec/src/lib.rs b/src/platform/redox/redox-exec/src/lib.rs index 6c7e896a98..2543c61e89 100644 --- a/src/platform/redox/redox-exec/src/lib.rs +++ b/src/platform/redox/redox-exec/src/lib.rs @@ -23,7 +23,7 @@ use goblin::elf64::{ use syscall::{ error::*, flag::{MapFlags, SEEK_SET}, - PAGE_SIZE, Map, + PAGE_SIZE, Map, PROT_WRITE, O_CLOEXEC, }; pub use self::arch::*; @@ -148,13 +148,9 @@ where PT_LOAD => { let voff = segment.p_vaddr as usize % PAGE_SIZE; let vaddr = segment.p_vaddr as usize - voff; + let filesz = segment.p_filesz as usize; - // TODO: Use CoW mmap from the underlying filesystem. - let _poff = segment.p_offset - voff as u64; - - let file_page_count = (segment.p_filesz as usize + voff).div_ceil(PAGE_SIZE); - let zero_page_count = ((segment.p_memsz as usize + voff) - file_page_count * PAGE_SIZE).div_ceil(PAGE_SIZE); - let total_page_count = file_page_count + zero_page_count; + let total_page_count = (segment.p_memsz as usize + voff).div_ceil(PAGE_SIZE); // The case where segments overlap so that they share one page, is not handled. // TODO: Should it be? @@ -170,9 +166,33 @@ where total_page_count * PAGE_SIZE, flags, )?; - syscall::lseek(*image_file as usize, segment.p_offset as isize, SEEK_SET) + syscall::lseek(*image_file, segment.p_offset as isize, SEEK_SET) .map_err(|_| Error::new(EIO))?; + // If unaligned, read the head page separately. + let (first_aligned_page, remaining_filesz) = if voff > 0 { + let bytes_to_next_page = PAGE_SIZE - voff; + + let (_guard, dst_page) = unsafe { + MmapGuard::map_mut_anywhere( + *grants_fd, + vaddr, + PAGE_SIZE, + )? + }; + + let length = core::cmp::min(bytes_to_next_page, filesz); + + read_all(*image_file, None, &mut dst_page[voff..][..length])?; + + (vaddr + PAGE_SIZE, filesz - length) + } else { + (vaddr, filesz) + }; + + let remaining_page_count = remaining_filesz.div_floor(PAGE_SIZE); + let tail_bytes = remaining_filesz % PAGE_SIZE; + // TODO: Unless the calling process if *very* memory-constrained, the max amount of // pages per iteration has no limit other than the time it takes to setup page // tables. @@ -181,37 +201,45 @@ where // situation? const PAGES_PER_ITER: usize = 64; - for page_idx in (0..file_page_count).step_by(PAGES_PER_ITER) { + // TODO: Before this loop, attempt to mmap with MAP_PRIVATE directly from the image + // file. + + for page_idx in (0..remaining_page_count).step_by(PAGES_PER_ITER) { // Use commented out lines to trigger kernel bug (FIXME). //let pages_in_this_group = core::cmp::min(PAGES_PER_ITER, file_page_count - page_idx * PAGES_PER_ITER); - let pages_in_this_group = core::cmp::min(PAGES_PER_ITER, file_page_count - page_idx); + let pages_in_this_group = core::cmp::min(PAGES_PER_ITER, remaining_page_count - page_idx); if pages_in_this_group == 0 { break } - let mut mmap_guard = MmapGuard::map(*grants_fd, &Map { - offset: vaddr + page_idx * PAGE_SIZE, - size: pages_in_this_group * PAGE_SIZE, - // TODO: MAP_FIXED (without MAP_FIXED_NOREPLACE) to a fixed offset, to - // avoid mapping/unmapping repeatedly? - flags: MapFlags::PROT_WRITE, - address: 0, // let the kernel choose - })?; + let _ = syscall::write(1, alloc::format!("idx {} reading (segment {:#?})\n", page_idx, segment).as_bytes()); + + // TODO: MAP_FIXED to optimize away funmap? + let (_guard, dst_memory) = unsafe { + MmapGuard::map_mut_anywhere( + *grants_fd, + first_aligned_page + page_idx * PAGE_SIZE, // offset + pages_in_this_group * PAGE_SIZE, // size + )? + }; - let dst_memory = unsafe { &mut *mmap_guard.as_mut_ptr_slice() }; // TODO: Are &mut [u8] and &mut [[u8; PAGE_SIZE]] interchangeable (if the // lengths are aligned, obviously)? - let voff_here = if page_idx == 0 { voff } else { 0 }; - let size_here = if pages_in_this_group == PAGES_PER_ITER { - PAGES_PER_ITER * PAGE_SIZE - } else { - (pages_in_this_group - 1) * PAGE_SIZE + (segment.p_filesz as usize % PAGE_SIZE) - //pages_in_this_group.div_floor(PAGES_PER_ITER) * PAGES_PER_ITER * PAGE_SIZE + (segment.p_filesz as usize % PAGE_SIZE) - } - voff_here; - - read_all(*image_file, None, &mut dst_memory[voff_here..][..size_here])?; + read_all(*image_file, None, dst_memory)?; } + + if tail_bytes > 0 { + let (_guard, dst_page) = unsafe { + MmapGuard::map_mut_anywhere( + *grants_fd, + first_aligned_page + remaining_page_count * PAGE_SIZE, + PAGE_SIZE, + )? + }; + read_all(*image_file, None, &mut dst_page[..tail_bytes])?; + } + // file_page_count..file_page_count + zero_page_count are already zero-initialized // by the kernel. @@ -286,14 +314,13 @@ where MapFlags::PROT_READ | MapFlags::PROT_WRITE, )?; unsafe { - let mut base = MmapGuard::map(*grants_fd, &Map { - offset: pheaders, - size: pheaders_size_aligned, - flags: MapFlags::PROT_WRITE, - address: 0, - })?; + let (_guard, memory) = MmapGuard::map_mut_anywhere( + *grants_fd, + pheaders, + pheaders_size_aligned, + )?; - (&mut *base.as_mut_ptr_slice())[..pheaders_to_convey.len()].copy_from_slice(pheaders_to_convey); + memory[..pheaders_to_convey.len()].copy_from_slice(pheaders_to_convey); } mprotect_remote( &grants_fd, @@ -344,7 +371,7 @@ where let mut argc = 0; { - let mut append = |source_slice: &[u8]| unsafe { + let mut append = |source_slice: &[u8]| { // TODO let address = target_args_env_address + offset; @@ -354,8 +381,14 @@ where let size = source_slice.len() + displacement; let aligned_size = size.next_multiple_of(PAGE_SIZE); - let mut base = MmapGuard::map(*grants_fd, &Map { offset: containing_page, size: aligned_size, flags: MapFlags::PROT_WRITE, address: 0 })?; - (unsafe { &mut *base.as_mut_ptr_slice() })[displacement..][..source_slice.len()].copy_from_slice(source_slice); + let (_guard, memory) = unsafe { + MmapGuard::map_mut_anywhere( + *grants_fd, + containing_page, + aligned_size, + )? + }; + memory[displacement..][..source_slice.len()].copy_from_slice(source_slice); } offset += source_slice.len() + 1; @@ -537,21 +570,6 @@ fn read_all(fd: usize, offset: Option, buf: &mut [u8]) -> Result<()> { } Ok(()) } -fn write_all(fd: usize, offset: Option, buf: &[u8]) -> Result<()> { - if let Some(offset) = offset { - syscall::lseek(fd, offset as isize, SEEK_SET)?; - } - - let mut total_bytes_written = 0; - - while total_bytes_written < buf.len() { - total_bytes_written += match syscall::write(fd, &buf[total_bytes_written..])? { - 0 => return Err(Error::new(EIO)), - bytes_written => bytes_written, - } - } - Ok(()) -} // TODO: With the introduction of remote mmaps, remove this and let the kernel handle address // allocation. @@ -588,6 +606,17 @@ impl MmapGuard { base: unsafe { syscall::fmap(fd, map)? }, }) } + pub unsafe fn map_mut_anywhere<'a>(fd: usize, offset: usize, size: usize) -> Result<(Self, &'a mut [u8])> { + let mut this = Self::map(fd, &Map { + size, + offset, + address: 0, + flags: PROT_WRITE, + })?; + let slice = &mut *this.as_mut_ptr_slice(); + + Ok((this, slice)) + } pub fn addr(&self) -> usize { self.base } @@ -668,7 +697,7 @@ fn fork_inner(initial_rsp: *mut usize) -> Result { { let cur_pid_fd = FdGuard::new(syscall::open( "thisproc:current/open_via_dup", - syscall::O_CLOEXEC, + O_CLOEXEC, )?); (new_pid_fd, new_pid) = new_context()?; @@ -757,7 +786,7 @@ pub fn new_context() -> Result<(FdGuard, usize)> { // Create a new context (fields such as uid/gid will be inherited from the current context). let fd = FdGuard::new(syscall::open( "thisproc:new/open_via_dup", - syscall::O_CLOEXEC, + O_CLOEXEC, )?); // Extract pid. From 67a0d7aebb3007cd26a81842ee04984d798fbf44 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 3 Jul 2023 16:57:50 +0200 Subject: [PATCH 5/8] Remove redox-exec debug log. --- src/platform/redox/redox-exec/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/platform/redox/redox-exec/src/lib.rs b/src/platform/redox/redox-exec/src/lib.rs index 2543c61e89..3689844a2a 100644 --- a/src/platform/redox/redox-exec/src/lib.rs +++ b/src/platform/redox/redox-exec/src/lib.rs @@ -212,8 +212,6 @@ where if pages_in_this_group == 0 { break } - let _ = syscall::write(1, alloc::format!("idx {} reading (segment {:#?})\n", page_idx, segment).as_bytes()); - // TODO: MAP_FIXED to optimize away funmap? let (_guard, dst_memory) = unsafe { MmapGuard::map_mut_anywhere( @@ -446,7 +444,6 @@ where } let addrspace_selection_fd = FdGuard::new(syscall::dup(*open_via_dup, b"current-addrspace")?); - let _ = syscall::write(1, alloc::format!("ENTER {:p} {:p}\n", header.e_entry as *const u8, sp as *const u8).as_bytes()); let _ = syscall::write( *addrspace_selection_fd, From 5aa3ae25b4410a88a5795b05a4a34ed4da4c33a1 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Wed, 5 Jul 2023 11:16:38 +0200 Subject: [PATCH 6/8] Reimplement "clone grant using fmap". --- Cargo.lock | 95 +++++++++++------------- src/platform/redox/extra.rs | 5 +- src/platform/redox/redox-exec/src/lib.rs | 54 ++++++++++++++ 3 files changed, 101 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6521070ac3..e73d9b5fd3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,16 +27,16 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "cbindgen" -version = "0.24.3" +version = "0.24.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6358dedf60f4d9b8db43ad187391afe959746101346fe51bb978126bec61dfb" +checksum = "4b922faaf31122819ec80c4047cc684c6979a087366c069611e33649bf98e18d" dependencies = [ "clap", "heck", "indexmap", "log", - "proc-macro2 1.0.56", - "quote 1.0.26", + "proc-macro2 1.0.63", + "quote 1.0.29", "serde", "serde_json", "syn 1.0.109", @@ -67,9 +67,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.2.23" +version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "atty", "bitflags", @@ -197,9 +197,9 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi 0.3.1", "libc", @@ -208,9 +208,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" [[package]] name = "lazy_static" @@ -232,15 +232,15 @@ source = "git+https://gitlab.redox-os.org/redox-os/liblibc.git?branch=redox_0.2. [[package]] name = "linux-raw-sys" -version = "0.3.1" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -248,12 +248,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "memchr" @@ -281,9 +278,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.5.0" +version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" +checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" [[package]] name = "plain" @@ -306,9 +303,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" dependencies = [ "unicode-ident", ] @@ -324,11 +321,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.26" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ - "proc-macro2 1.0.56", + "proc-macro2 1.0.63", ] [[package]] @@ -389,8 +386,6 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags", ] @@ -454,9 +449,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" [[package]] name = "sc" @@ -514,29 +509,29 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.160" +version = "1.0.166" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "d01b7404f9d441d3ad40e6a636a7782c377d2abdbe4fa2440e2edcc2f4f10db8" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.160" +version = "1.0.166" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +checksum = "5dd83d6dde2b6b2d466e14d9d1acce8816dedee94f735eac6395808b3483c6d6" dependencies = [ - "proc-macro2 1.0.56", - "quote 1.0.26", - "syn 2.0.15", + "proc-macro2 1.0.63", + "quote 1.0.29", + "syn 2.0.23", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" dependencies = [ "itoa", "ryu", @@ -581,19 +576,19 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.56", - "quote 1.0.26", + "proc-macro2 1.0.63", + "quote 1.0.29", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.15" +version = "2.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737" dependencies = [ - "proc-macro2 1.0.56", - "quote 1.0.26", + "proc-macro2 1.0.63", + "quote 1.0.29", "unicode-ident", ] @@ -642,9 +637,9 @@ checksum = "e92e959f029e4f8ee25d70d15ab58d2b46f98a17bc238b9265ff0c26f6f3d67f" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" [[package]] name = "unicode-width" @@ -704,7 +699,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.1", ] [[package]] @@ -724,9 +719,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ "windows_aarch64_gnullvm 0.48.0", "windows_aarch64_msvc 0.48.0", diff --git a/src/platform/redox/extra.rs b/src/platform/redox/extra.rs index f43330b408..0c151efdcd 100644 --- a/src/platform/redox/extra.rs +++ b/src/platform/redox/extra.rs @@ -1,9 +1,10 @@ use core::{ptr, slice}; use crate::platform::{sys::e, types::*}; - use syscall::{error::*, F_SETFD, F_SETFL}; +pub use redox_exec::*; + #[no_mangle] pub unsafe extern "C" fn redox_fpath(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t { e(syscall::fpath( @@ -46,5 +47,3 @@ pub fn pipe2(fds: &mut [c_int], flags: usize) -> syscall::error::Result<()> { Ok(()) } - -pub use redox_exec::{create_set_addr_space_buf, FdGuard}; diff --git a/src/platform/redox/redox-exec/src/lib.rs b/src/platform/redox/redox-exec/src/lib.rs index 3689844a2a..5b983651c0 100644 --- a/src/platform/redox/redox-exec/src/lib.rs +++ b/src/platform/redox/redox-exec/src/lib.rs @@ -24,6 +24,7 @@ use syscall::{ error::*, flag::{MapFlags, SEEK_SET}, PAGE_SIZE, Map, PROT_WRITE, O_CLOEXEC, + GrantDesc, GrantFlags, PROT_READ, PROT_EXEC, MAP_SHARED, MAP_FIXED_NOREPLACE, }; pub use self::arch::*; @@ -744,6 +745,59 @@ fn fork_inner(initial_rsp: *mut usize) -> Result { let cur_addr_space_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"addrspace")?); let new_addr_space_fd = FdGuard::new(syscall::dup(*cur_addr_space_fd, b"exclusive")?); + let mut grant_desc_buf = [GrantDesc::default(); 16]; + loop { + let bytes_read = { + let buf = unsafe { core::slice::from_raw_parts_mut(grant_desc_buf.as_mut_ptr().cast(), grant_desc_buf.len() * size_of::()) }; + syscall::read(*cur_addr_space_fd, buf)? + }; + if bytes_read == 0 { + break; + } + + let grants = &grant_desc_buf[..bytes_read / size_of::()]; + + for grant in grants { + if !grant.flags.contains(GrantFlags::GRANT_SCHEME) || !grant.flags.contains(GrantFlags::GRANT_SHARED) { + continue; + } + + let mut buf; + + // TODO: write! using some #![no_std] Cursor type (tracking the length)? + #[cfg(target_pointer_width = "64")] + { + //buf = *b"grant-fd-AAAABBBBCCCCDDDD"; + //write!(&mut buf, "grant-fd-{:>016x}", grant.base).unwrap(); + buf = alloc::format!("grant-fd-{:>016x}", grant.base).into_bytes(); + } + + #[cfg(target_pointer_width = "32")] + { + //buf = *b"grant-fd-AAAABBBB"; + //write!(&mut buf[..], "grant-fd-{:>08x}", grant.base).unwrap(); + buf = alloc::format!("grant-fd-{:>08x}", grant.base).into_bytes(); + } + + let grant_fd = FdGuard::new(syscall::dup(*cur_addr_space_fd, &buf)?); + + let mut flags = MAP_SHARED | MAP_FIXED_NOREPLACE; + + flags.set(PROT_READ, grant.flags.contains(GrantFlags::GRANT_READ)); + flags.set(PROT_WRITE, grant.flags.contains(GrantFlags::GRANT_WRITE)); + flags.set(PROT_EXEC, grant.flags.contains(GrantFlags::GRANT_EXEC)); + + mmap_remote( + &new_addr_space_fd, + &grant_fd, + grant.offset as usize, + grant.base, + grant.size, + flags, + )?; + } + } + let buf = create_set_addr_space_buf( *new_addr_space_fd, __relibc_internal_fork_ret as usize, From 084d6b03446886274f6505588864646c147b9a26 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Wed, 12 Jul 2023 15:44:36 +0200 Subject: [PATCH 7/8] Some MAP_FIXED optimizations. --- src/platform/redox/redox-exec/src/lib.rs | 43 +++++++++++++++--------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/platform/redox/redox-exec/src/lib.rs b/src/platform/redox/redox-exec/src/lib.rs index 5b983651c0..7420c22b5f 100644 --- a/src/platform/redox/redox-exec/src/lib.rs +++ b/src/platform/redox/redox-exec/src/lib.rs @@ -1,5 +1,5 @@ #![no_std] -#![feature(array_chunks, int_roundings, slice_ptr_get)] +#![feature(array_chunks, int_roundings, let_chains, slice_ptr_get)] #![forbid(unreachable_patterns)] extern crate alloc; @@ -273,25 +273,24 @@ where let new_page_no = sp / PAGE_SIZE; let new_page_off = sp % PAGE_SIZE; - if old_page_no != new_page_no { - stack_page = None; - } - - let page = if let Some(ref mut page) = stack_page { - page.as_mut_ptr_slice() + let page = if let Some(ref mut page) = stack_page && old_page_no == new_page_no { + page + } else if let Some(ref mut stack_page) = stack_page { + stack_page.remap(new_page_no * PAGE_SIZE, PROT_WRITE)?; + stack_page } else { let new = MmapGuard::map(*grants_fd, &Map { offset: new_page_no * PAGE_SIZE, size: PAGE_SIZE, - flags: MapFlags::PROT_WRITE, + flags: PROT_WRITE, address: 0, // let kernel decide })?; - stack_page.insert(new).as_mut_ptr_slice() + stack_page.insert(new) }; unsafe { - page.as_mut_ptr().add(new_page_off).cast::().write(word); + page.as_mut_ptr_slice().as_mut_ptr().add(new_page_off).cast::().write(word); } Ok(()) @@ -591,19 +590,31 @@ fn find_free_target_addr(tree: &BTreeMap, size: usize) -> Option Result { Ok(Self { + fd, size: map.size, - taken: false, - base: unsafe { syscall::fmap(fd, map)? }, }) } + pub fn remap(&mut self, offset: usize, mut flags: MapFlags) -> Result<()> { + flags.remove(MapFlags::MAP_FIXED_NOREPLACE); + flags.insert(MapFlags::MAP_FIXED); + + let _new_base = unsafe { syscall::fmap(self.fd, &Map { + offset, + size: self.size, + flags, + address: self.base, + })? }; + + Ok(()) + } pub unsafe fn map_mut_anywhere<'a>(fd: usize, offset: usize, size: usize) -> Result<(Self, &'a mut [u8])> { let mut this = Self::map(fd, &Map { size, @@ -624,13 +635,13 @@ impl MmapGuard { pub fn as_mut_ptr_slice(&mut self) -> *mut [u8] { core::ptr::slice_from_raw_parts_mut(self.base as *mut u8, self.size) } - pub fn take(&mut self) { - self.taken = true; + pub fn take(mut self) { + self.size = 0; } } impl Drop for MmapGuard { fn drop(&mut self) { - if !self.taken { + if self.size != 0 { let _ = unsafe { syscall::funmap(self.base, self.size) }; } } From 068ce3df7cb5d9e5d82c79d9b49fa341c93567ca Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Wed, 2 Aug 2023 15:14:05 +0200 Subject: [PATCH 8/8] Use redox_syscall git dependency. --- Cargo.lock | 82 ++++++++++++++++++++++++++++-------------------------- Cargo.toml | 1 + 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e73d9b5fd3..92eb0d3704 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,8 +35,8 @@ dependencies = [ "heck", "indexmap", "log", - "proc-macro2 1.0.63", - "quote 1.0.29", + "proc-macro2 1.0.66", + "quote 1.0.32", "serde", "serde_json", "syn 1.0.109", @@ -55,9 +55,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "51f1226cd9da55587234753d1245dd5b132343ea240f26b6a9003d68706141ba" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -110,9 +113,9 @@ version = "0.1.0" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" dependencies = [ "errno-dragonfly", "libc", @@ -172,9 +175,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "indexmap" @@ -201,16 +204,16 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi 0.3.2", "libc", "windows-sys 0.48.0", ] [[package]] name = "itoa" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "lazy_static" @@ -269,9 +272,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] @@ -303,9 +306,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] @@ -321,11 +324,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.29" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.66", ] [[package]] @@ -386,6 +389,7 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" version = "0.3.5" +source = "git+https://gitlab.redox-os.org/redox-os/syscall#a525620c818a801bb7038e111b71033eff56a3ee" dependencies = [ "bitflags", ] @@ -449,9 +453,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "sc" @@ -461,9 +465,9 @@ checksum = "010e18bd3bfd1d45a7e666b236c78720df0d9a7698ebaa9c1c559961eb60a38b" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "scroll" @@ -509,29 +513,29 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.166" +version = "1.0.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d01b7404f9d441d3ad40e6a636a7782c377d2abdbe4fa2440e2edcc2f4f10db8" +checksum = "0ea67f183f058fe88a4e3ec6e2788e003840893b91bac4559cabedd00863b3ed" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.166" +version = "1.0.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd83d6dde2b6b2d466e14d9d1acce8816dedee94f735eac6395808b3483c6d6" +checksum = "24e744d7782b686ab3b73267ef05697159cc0e5abbed3f47f9933165e5219036" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.29", - "syn 2.0.23", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.28", ] [[package]] name = "serde_json" -version = "1.0.99" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" dependencies = [ "itoa", "ryu", @@ -576,19 +580,19 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.29", + "proc-macro2 1.0.66", + "quote 1.0.32", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.23" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.29", + "proc-macro2 1.0.66", + "quote 1.0.32", "unicode-ident", ] @@ -637,9 +641,9 @@ checksum = "e92e959f029e4f8ee25d70d15ab58d2b46f98a17bc238b9265ff0c26f6f3d67f" [[package]] name = "unicode-ident" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-width" diff --git a/Cargo.toml b/Cargo.toml index 982fb40c31..61f84fbbf1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,3 +61,4 @@ panic = "abort" [patch.crates-io] libc = { git = "https://gitlab.redox-os.org/redox-os/liblibc.git", branch = "redox_0.2.138" } +redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall" }