diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index cff17004..362f91aa 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -11,14 +11,14 @@ jobs: name: Format check ${{ matrix.arch }} runs-on: ubuntu-latest continue-on-error: true - container: dragonos/dragonos-dev:v1.11 + container: dragonos/dragonos-dev:v1.12 strategy: matrix: arch: [x86_64, riscv64, loongarch64] steps: - - run: echo "Running in dragonos/dragonos-dev:v1.11" + - run: echo "Running in dragonos/dragonos-dev:v1.12" - uses: actions/checkout@v3 - name: Format check @@ -35,14 +35,14 @@ jobs: name: Kernel static test ${{ matrix.arch }} runs-on: ubuntu-latest continue-on-error: true - container: dragonos/dragonos-dev:v1.11 + container: dragonos/dragonos-dev:v1.12 strategy: matrix: arch: [x86_64, riscv64, loongarch64] steps: - - run: echo "Running in dragonos/dragonos-dev:v1.11" + - run: echo "Running in dragonos/dragonos-dev:v1.12" - uses: actions/checkout@v3 @@ -56,7 +56,7 @@ jobs: build: name: Build ${{ matrix.arch }} runs-on: ubuntu-latest - container: dragonos/dragonos-dev:v1.11 + container: dragonos/dragonos-dev:v1.12 continue-on-error: true strategy: matrix: @@ -73,7 +73,7 @@ jobs: checkout_params: {} steps: - - run: echo "Running in dragonos/dragonos-dev:v1.11" + - run: echo "Running in dragonos/dragonos-dev:v1.12" - uses: actions/checkout@v3 with: ${{ matrix.checkout_params }} diff --git a/kernel/src/arch/x86_64/mm/fault.rs b/kernel/src/arch/x86_64/mm/fault.rs index b41409e6..e21535d8 100644 --- a/kernel/src/arch/x86_64/mm/fault.rs +++ b/kernel/src/arch/x86_64/mm/fault.rs @@ -177,6 +177,10 @@ impl X86_64MMArch { error_code: X86PfErrorCode, address: VirtAddr, ) { + // log::debug!("fault at {:?}:{:?}", + // address, + // error_code, + // ); let rflags = RFlags::from_bits_truncate(regs.rflags); let mut flags: FaultFlags = FaultFlags::FAULT_FLAG_ALLOW_RETRY | FaultFlags::FAULT_FLAG_KILLABLE diff --git a/kernel/src/arch/x86_64/process/syscall.rs b/kernel/src/arch/x86_64/process/syscall.rs index a10bd57d..698cf21d 100644 --- a/kernel/src/arch/x86_64/process/syscall.rs +++ b/kernel/src/arch/x86_64/process/syscall.rs @@ -53,6 +53,7 @@ impl Syscall { } /// ## 用于控制和查询与体系结构相关的进程特定选项 + /// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/kernel/process_64.c#913 pub fn arch_prctl(option: usize, arg2: usize) -> Result { let pcb = ProcessManager::current_pcb(); if let Err(SystemError::EINVAL) = Self::do_arch_prctl_64(&pcb, option, arg2, true) { @@ -109,8 +110,17 @@ impl Syscall { } #[allow(dead_code)] - pub fn do_arch_prctl_common(_option: usize, _arg2: usize) -> Result { - todo!("do_arch_prctl_common not unimplemented"); + pub fn do_arch_prctl_common(option: usize, arg2: usize) -> Result { + // Don't use 0x3001-0x3004 because of old glibcs + if (0x3001..=0x3004).contains(&option) { + return Err(SystemError::EINVAL); + } + + todo!( + "do_arch_prctl_common not unimplemented, option: {}, arg2: {}", + option, + arg2 + ); } } diff --git a/kernel/src/arch/x86_64/syscall/mod.rs b/kernel/src/arch/x86_64/syscall/mod.rs index 30b4c118..92817d4e 100644 --- a/kernel/src/arch/x86_64/syscall/mod.rs +++ b/kernel/src/arch/x86_64/syscall/mod.rs @@ -90,7 +90,7 @@ pub extern "sysv64" fn syscall_handler(frame: &mut TrapFrame) { mfence(); let pid = ProcessManager::current_pcb().pid(); let show = false; - // let show = if syscall_num != SYS_SCHED && pid.data() >= 7 { + // let show = if syscall_num != SYS_SCHED && pid.data() >= 9{ // true // } else { // false diff --git a/kernel/src/debug/panic/mod.rs b/kernel/src/debug/panic/mod.rs index 8a6425b8..14a2d0f7 100644 --- a/kernel/src/debug/panic/mod.rs +++ b/kernel/src/debug/panic/mod.rs @@ -1,4 +1,4 @@ -mod hook; +pub mod hook; use alloc::boxed::Box; use cfg_if::cfg_if; diff --git a/kernel/src/driver/base/device/dd.rs b/kernel/src/driver/base/device/dd.rs index 358c5195..81adaa18 100644 --- a/kernel/src/driver/base/device/dd.rs +++ b/kernel/src/driver/base/device/dd.rs @@ -144,6 +144,7 @@ impl DeviceManager { /// - Err(SystemError): 匹配过程中出现意外错误,没有匹配成功 /// /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#899 + #[inline(never)] fn do_device_attach_driver( &self, driver: &Arc, diff --git a/kernel/src/filesystem/fat/fs.rs b/kernel/src/filesystem/fat/fs.rs index 5256949a..a0d5acc4 100644 --- a/kernel/src/filesystem/fat/fs.rs +++ b/kernel/src/filesystem/fat/fs.rs @@ -1452,7 +1452,6 @@ impl IndexNode for LockedFATInode { let page_cache = self.0.lock().page_cache.clone(); if let Some(page_cache) = page_cache { let r = page_cache.lock_irqsave().read(offset, &mut buf[0..len]); - // self.0.lock_irqsave().update_metadata(); return r; } else { return self.read_direct(offset, len, buf, data); diff --git a/kernel/src/filesystem/page_cache.rs b/kernel/src/filesystem/page_cache.rs index d7ed808b..c5902a02 100644 --- a/kernel/src/filesystem/page_cache.rs +++ b/kernel/src/filesystem/page_cache.rs @@ -113,13 +113,14 @@ impl InnerPageCache { /// - `Ok(usize)` 成功读取的长度 /// - `Err(SystemError)` 失败返回错误码 pub fn read(&mut self, offset: usize, buf: &mut [u8]) -> Result { - let inode = self + let inode: Arc = self .page_cache_ref .upgrade() .unwrap() .inode .upgrade() .unwrap(); + let file_size = inode.metadata().unwrap().size; let len = if offset < file_size as usize { @@ -182,6 +183,7 @@ impl InnerPageCache { for (page_index, count) in not_exist { // TODO 这里使用buffer避免多次读取磁盘,将来引入异步IO直接写入页面,减少内存开销和拷贝 let mut page_buf = vec![0u8; MMArch::PAGE_SIZE * count]; + inode.read_sync(page_index * MMArch::PAGE_SIZE, page_buf.as_mut())?; self.create_pages(page_index, page_buf.as_mut())?; @@ -314,7 +316,7 @@ impl InnerPageCache { impl Drop for InnerPageCache { fn drop(&mut self) { - log::debug!("page cache drop"); + // log::debug!("page cache drop"); let mut page_manager = page_manager_lock_irqsave(); for page in self.pages.values() { page_manager.remove_page(&page.phys_address()); @@ -358,6 +360,13 @@ impl PageCache { } pub fn lock_irqsave(&self) -> SpinLockGuard { + if self.inner.is_locked() { + log::error!("page cache already locked"); + } self.inner.lock_irqsave() } + + pub fn is_locked(&self) -> bool { + self.inner.is_locked() + } } diff --git a/kernel/src/filesystem/vfs/open.rs b/kernel/src/filesystem/vfs/open.rs index 108a114a..5b906934 100644 --- a/kernel/src/filesystem/vfs/open.rs +++ b/kernel/src/filesystem/vfs/open.rs @@ -42,6 +42,7 @@ pub(super) fn do_faccessat( let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; let path = path.to_str().map_err(|_| SystemError::EINVAL)?; + // log::debug!("do_faccessat path: {:?}", path); let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?; @@ -166,7 +167,7 @@ fn do_sys_openat2( how: OpenHow, follow_symlink: bool, ) -> Result { - // debug!("open path: {}, how: {:?}", path, how); + // log::debug!("openat2: dirfd: {}, path: {}, how: {:?}",dirfd, path, how); let path = path.trim(); let (inode_begin, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?; diff --git a/kernel/src/filesystem/vfs/stat.rs b/kernel/src/filesystem/vfs/stat.rs index 65df11a5..87167170 100644 --- a/kernel/src/filesystem/vfs/stat.rs +++ b/kernel/src/filesystem/vfs/stat.rs @@ -273,6 +273,7 @@ pub fn vfs_getattr( /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#274 #[inline(never)] pub fn vfs_fstatat(dfd: i32, filename: &str, flags: AtFlags) -> Result { + // log::debug!("vfs_fstatat: dfd={}, filename={}", dfd, filename); let statx_flags = flags | AtFlags::AT_NO_AUTOMOUNT; if dfd >= 0 && flags == AtFlags::AT_EMPTY_PATH { return vfs_fstat(dfd); @@ -322,7 +323,7 @@ pub(super) fn do_newfstatat( /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#393 #[inline(never)] -fn cp_new_stat(kstat: KStat, user_buf_ptr: usize) -> Result<(), SystemError> { +pub(super) fn cp_new_stat(kstat: KStat, user_buf_ptr: usize) -> Result<(), SystemError> { let posix_stat = PosixStat::try_from(kstat)?; let mut ubuf_writer = UserBufferWriter::new(user_buf_ptr as *mut PosixStat, size_of::(), true)?; @@ -397,70 +398,6 @@ fn cp_statx(kstat: KStat, user_buf_ptr: usize) -> Result<(), SystemError> { Ok(()) } -// 注意!这个结构体定义的貌似不太对,需要修改! -#[repr(C)] -#[derive(Clone, Copy)] -/// # 文件信息结构体 -pub struct PosixKstat { - /// 硬件设备ID - pub dev_id: u64, - /// inode号 - pub inode: u64, - /// 硬链接数 - pub nlink: u64, - /// 文件权限 - pub mode: ModeType, - /// 所有者用户ID - pub uid: i32, - /// 所有者组ID - pub gid: i32, - /// 设备ID - pub rdev: i64, - /// 文件大小 - pub size: i64, - /// 文件系统块大小 - pub blcok_size: i64, - /// 分配的512B块数 - pub blocks: u64, - /// 最后访问时间 - pub atime: PosixTimeSpec, - /// 最后修改时间 - pub mtime: PosixTimeSpec, - /// 最后状态变化时间 - pub ctime: PosixTimeSpec, - /// 用于填充结构体大小的空白数据 - pub _pad: [i8; 24], -} -impl PosixKstat { - pub(super) fn new() -> Self { - Self { - inode: 0, - dev_id: 0, - mode: ModeType::empty(), - nlink: 0, - uid: 0, - gid: 0, - rdev: 0, - size: 0, - atime: PosixTimeSpec { - tv_sec: 0, - tv_nsec: 0, - }, - mtime: PosixTimeSpec { - tv_sec: 0, - tv_nsec: 0, - }, - ctime: PosixTimeSpec { - tv_sec: 0, - tv_nsec: 0, - }, - blcok_size: 0, - blocks: 0, - _pad: Default::default(), - } - } -} - /// 通用的PosixStat #[allow(unused)] #[repr(C)] diff --git a/kernel/src/filesystem/vfs/syscall/mod.rs b/kernel/src/filesystem/vfs/syscall/mod.rs index b5c7c717..09dc4e10 100644 --- a/kernel/src/filesystem/vfs/syscall/mod.rs +++ b/kernel/src/filesystem/vfs/syscall/mod.rs @@ -21,7 +21,7 @@ use crate::{ time::{syscall::PosixTimeval, PosixTimeSpec}, }; -use super::stat::{do_newfstatat, do_statx, PosixKstat}; +use super::stat::{do_newfstatat, do_statx, vfs_fstat}; use super::vcore::do_symlinkat; use super::{ fcntl::{AtFlags, FcntlCommand, FD_CLOEXEC}, @@ -1211,79 +1211,31 @@ impl Syscall { return Err(SystemError::EBADF); } - fn do_fstat(fd: i32) -> Result { - let binding = ProcessManager::current_pcb().fd_table(); - let fd_table_guard = binding.read(); - let file = fd_table_guard - .get_file_by_fd(fd) - .ok_or(SystemError::EBADF)?; - // drop guard 以避免无法调度的问题 - drop(fd_table_guard); - - let mut kstat = PosixKstat::new(); - // 获取文件信息 - let metadata = file.metadata()?; - kstat.size = metadata.size; - kstat.dev_id = metadata.dev_id as u64; - kstat.inode = metadata.inode_id.into() as u64; - kstat.blcok_size = metadata.blk_size as i64; - kstat.blocks = metadata.blocks as u64; - - kstat.atime.tv_sec = metadata.atime.tv_sec; - kstat.atime.tv_nsec = metadata.atime.tv_nsec; - kstat.mtime.tv_sec = metadata.mtime.tv_sec; - kstat.mtime.tv_nsec = metadata.mtime.tv_nsec; - kstat.ctime.tv_sec = metadata.ctime.tv_sec; - kstat.ctime.tv_nsec = metadata.ctime.tv_nsec; - - kstat.nlink = metadata.nlinks as u64; - kstat.uid = metadata.uid as i32; - kstat.gid = metadata.gid as i32; - kstat.rdev = metadata.raw_dev.data() as i64; - kstat.mode = metadata.mode; - match file.file_type() { - FileType::File => kstat.mode.insert(ModeType::S_IFREG), - FileType::Dir => kstat.mode.insert(ModeType::S_IFDIR), - FileType::BlockDevice => kstat.mode.insert(ModeType::S_IFBLK), - FileType::CharDevice => kstat.mode.insert(ModeType::S_IFCHR), - FileType::SymLink => kstat.mode.insert(ModeType::S_IFLNK), - FileType::Socket => kstat.mode.insert(ModeType::S_IFSOCK), - FileType::Pipe => kstat.mode.insert(ModeType::S_IFIFO), - FileType::KvmDevice => kstat.mode.insert(ModeType::S_IFCHR), - FileType::FramebufferDevice => kstat.mode.insert(ModeType::S_IFCHR), - } - - return Ok(kstat); + #[inline(never)] + pub fn fstat(fd: i32, user_stat_ptr: usize) -> Result { + Self::newfstat(fd, user_stat_ptr) } - pub fn fstat(fd: i32, usr_kstat: *mut PosixKstat) -> Result { - let mut writer = UserBufferWriter::new(usr_kstat, size_of::(), true)?; - let kstat = Self::do_fstat(fd)?; - - writer.copy_one_to_user(&kstat, 0)?; - return Ok(0); - } - - pub fn stat(path: *const u8, user_kstat: *mut PosixKstat) -> Result { + pub fn stat(path: *const u8, user_stat_ptr: usize) -> Result { let fd = Self::open( path, FileMode::O_RDONLY.bits(), ModeType::empty().bits(), true, )?; - let r = Self::fstat(fd as i32, user_kstat); + let r = Self::fstat(fd as i32, user_stat_ptr); Self::close(fd).ok(); return r; } - pub fn lstat(path: *const u8, user_kstat: *mut PosixKstat) -> Result { + pub fn lstat(path: *const u8, user_stat_ptr: usize) -> Result { let fd = Self::open( path, FileMode::O_RDONLY.bits(), ModeType::empty().bits(), false, )?; - let r = Self::fstat(fd as i32, user_kstat); + let r = Self::fstat(fd as i32, user_stat_ptr); Self::close(fd).ok(); return r; } @@ -1356,6 +1308,16 @@ impl Syscall { do_newfstatat(dfd, filename_str, user_stat_buf_ptr, flags).map(|_| 0) } + #[inline(never)] + pub fn newfstat(fd: i32, user_stat_buf_ptr: usize) -> Result { + if user_stat_buf_ptr == 0 { + return Err(SystemError::EFAULT); + } + let stat = vfs_fstat(fd)?; + // log::debug!("newfstat fd: {}, stat.size: {:?}",fd,stat.size); + super::stat::cp_new_stat(stat, user_stat_buf_ptr).map(|_| 0) + } + pub fn mknod( path: *const u8, mode: ModeType, diff --git a/kernel/src/libs/elf.rs b/kernel/src/libs/elf.rs index fc531125..7ccbe6a5 100644 --- a/kernel/src/libs/elf.rs +++ b/kernel/src/libs/elf.rs @@ -7,10 +7,10 @@ use core::{ use alloc::vec::Vec; use elf::{ - abi::{PT_GNU_PROPERTY, PT_INTERP}, + abi::{ET_DYN, ET_EXEC, PT_GNU_PROPERTY, PT_INTERP, PT_LOAD}, endian::AnyEndian, file::FileHeader, - segment::ProgramHeader, + segment::{ProgramHeader, SegmentTable}, }; use log::error; use system_error::SystemError; @@ -18,7 +18,6 @@ use system_error::SystemError; use crate::{ arch::{CurrentElfArch, MMArch}, driver::base::block::SeekFrom, - filesystem::vfs::file::File, libs::align::page_align_up, mm::{ allocator::page_frame::{PageFrameCount, VirtPageFrame}, @@ -28,7 +27,9 @@ use crate::{ }, process::{ abi::AtType, - exec::{BinaryLoader, BinaryLoaderResult, ExecError, ExecLoadMode, ExecParam}, + exec::{ + BinaryLoader, BinaryLoaderResult, ExecError, ExecLoadMode, ExecParam, ExecParamFlags, + }, ProcessFlags, ProcessManager, }, syscall::user_access::{clear_user, copy_to_user}, @@ -134,8 +135,8 @@ impl ElfLoader { end: VirtAddr, prot_flags: ProtFlags, ) -> Result<(), ExecError> { - let start = self.elf_page_start(start); - let end = self.elf_page_align_up(end); + let start = Self::elf_page_start(start); + let end = Self::elf_page_align_up(end); // debug!("set_elf_brk: start={:?}, end={:?}", start, end); if end > start { let r = user_vm_guard.map_anonymous( @@ -158,15 +159,15 @@ impl ElfLoader { } /// 计算addr在ELF PAGE内的偏移 - fn elf_page_offset(&self, addr: VirtAddr) -> usize { + fn elf_page_offset(addr: VirtAddr) -> usize { addr.data() & (CurrentElfArch::ELF_PAGE_SIZE - 1) } - fn elf_page_start(&self, addr: VirtAddr) -> VirtAddr { + fn elf_page_start(addr: VirtAddr) -> VirtAddr { VirtAddr::new(addr.data() & (!(CurrentElfArch::ELF_PAGE_SIZE - 1))) } - fn elf_page_align_up(&self, addr: VirtAddr) -> VirtAddr { + fn elf_page_align_up(addr: VirtAddr) -> VirtAddr { VirtAddr::new( (addr.data() + CurrentElfArch::ELF_PAGE_SIZE - 1) & (!(CurrentElfArch::ELF_PAGE_SIZE - 1)), @@ -174,7 +175,7 @@ impl ElfLoader { } /// 根据ELF的p_flags生成对应的ProtFlags - fn make_prot(&self, p_flags: u32, _has_interpreter: bool, _is_interpreter: bool) -> ProtFlags { + fn make_prot(p_flags: u32, _has_interpreter: bool, _is_interpreter: bool) -> ProtFlags { let mut prot = ProtFlags::empty(); if p_flags & elf::abi::PF_R != 0 { prot |= ProtFlags::PROT_READ; @@ -211,7 +212,6 @@ impl ElfLoader { /// - `Ok((VirtAddr, bool))`:如果成功加载,则bool值为true,否则为false. VirtAddr为加载的地址 #[allow(clippy::too_many_arguments)] fn load_elf_segment( - &self, user_vm_guard: &mut RwLockWriteGuard<'_, InnerAddressSpace>, param: &mut ExecParam, phent: &ProgramHeader, @@ -223,11 +223,11 @@ impl ElfLoader { // debug!("load_elf_segment: addr_to_map={:?}", addr_to_map); // 映射位置的偏移量(页内偏移) - let beginning_page_offset = self.elf_page_offset(addr_to_map); - addr_to_map = self.elf_page_start(addr_to_map); + let beginning_page_offset = Self::elf_page_offset(addr_to_map); + addr_to_map = Self::elf_page_start(addr_to_map); // 计算要映射的内存的大小 let map_size = phent.p_filesz as usize + beginning_page_offset; - let map_size = self.elf_page_align_up(VirtAddr::new(map_size)).data(); + let map_size = Self::elf_page_align_up(VirtAddr::new(map_size)).data(); // 当前段在文件中的大小 let seg_in_file_size = phent.p_filesz as usize; // 当前段在文件中的偏移量 @@ -266,7 +266,9 @@ impl ElfLoader { // So we first map the 'big' image - and unmap the remainder at // the end. (which unmap is needed for ELF images with holes.) if total_size != 0 { - let total_size = self.elf_page_align_up(VirtAddr::new(total_size)).data(); + let total_size = Self::elf_page_align_up(VirtAddr::new(total_size)).data(); + + // log::debug!("total_size={}", total_size); map_addr = user_vm_guard .map_anonymous(addr_to_map, total_size, tmp_prot, *map_flags, false, true) @@ -282,7 +284,7 @@ impl ElfLoader { )?; // 加载文件到内存 - self.do_load_file( + Self::do_load_file( map_addr + beginning_page_offset, seg_in_file_size, file_offset, @@ -307,7 +309,7 @@ impl ElfLoader { // ); // 加载文件到内存 - self.do_load_file( + Self::do_load_file( map_addr + beginning_page_offset, seg_in_file_size, file_offset, @@ -326,6 +328,152 @@ impl ElfLoader { return Ok((map_addr, true)); } + /// 加载elf动态链接器 + /// + /// ## 参数 + /// + /// - `interp_elf_ex`:动态链接器 + /// - `load_bias`偏移量 + /// + /// ## TODO + /// + /// 添加一个Arch state抽象,描述架构相关的elf state(参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#592) + fn load_elf_interp( + interp_elf_ex: &mut ExecParam, + load_bias: usize, + ) -> Result { + // log::debug!("loading elf interp"); + let mut head_buf = [0u8; 512]; + interp_elf_ex + .file_mut() + .lseek(SeekFrom::SeekSet(0)) + .map_err(|_| ExecError::NotSupported)?; + let _bytes = interp_elf_ex + .file_mut() + .read(512, &mut head_buf) + .map_err(|_| ExecError::NotSupported)?; + let interp_hdr = + Self::parse_ehdr(head_buf.as_ref()).map_err(|_| ExecError::NotExecutable)?; + if interp_hdr.e_type != ET_EXEC && interp_hdr.e_type != ET_DYN { + return Err(ExecError::NotExecutable); + } + let mut phdr_buf = Vec::new(); + let phdr_table = Self::parse_segments(interp_elf_ex, &interp_hdr, &mut phdr_buf) + .map_err(|_| ExecError::ParseError)? + .ok_or(ExecError::ParseError)?; + //TODO 架构相关检查 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#610 + let mut total_size = Self::total_mapping_size(&phdr_table); + + if total_size == 0 { + return Err(ExecError::InvalidParemeter); + } + + let mut load_addr_set = false; + let mut load_addr: VirtAddr = VirtAddr::new(0); + let mut elf_bss: VirtAddr = VirtAddr::new(0); + let mut last_bss: VirtAddr = VirtAddr::new(0); + let mut bss_prot: Option = None; + for section in phdr_table { + if section.p_type == PT_LOAD { + // log::debug!("loading {:?}", section); + let mut elf_type = MapFlags::MAP_PRIVATE; + let elf_prot = Self::make_prot(section.p_flags, true, true); + let vaddr = TryInto::::try_into(section.p_vaddr).unwrap(); + let mut addr_to_map = load_addr + vaddr; + if interp_hdr.e_type == ET_EXEC || load_addr_set { + elf_type.insert(MapFlags::MAP_FIXED) + } else if load_bias != 0 && interp_hdr.e_type == ET_DYN { + addr_to_map = VirtAddr::new(0); + } + let map_addr = Self::load_elf_segment( + &mut interp_elf_ex.vm().clone().write(), + interp_elf_ex, + §ion, + addr_to_map, + &elf_prot, + &elf_type, + total_size, + ) + .map_err(|e| { + log::error!("Failed to load elf interpreter :{:?}", e); + return ExecError::InvalidParemeter; + })?; + if !map_addr.1 { + return Err(ExecError::BadAddress(Some(map_addr.0))); + } + let map_addr = map_addr.0; + total_size = 0; + if !load_addr_set && interp_hdr.e_type == ET_DYN { + load_addr = + VirtAddr::new(map_addr - Self::elf_page_start(VirtAddr::new(vaddr))); + load_addr_set = true; + } + let addr = load_addr + TryInto::::try_into(section.p_vaddr).unwrap(); + if addr >= MMArch::USER_END_VADDR + || section.p_filesz > section.p_memsz + || TryInto::::try_into(section.p_memsz).unwrap() + > MMArch::USER_END_VADDR.data() + || MMArch::USER_END_VADDR - TryInto::::try_into(section.p_memsz).unwrap() + < addr + { + return Err(ExecError::OutOfMemory); + } + + let addr = load_addr + + TryInto::::try_into(section.p_vaddr + section.p_filesz).unwrap(); + if addr > elf_bss { + elf_bss = addr; + } + + let addr = load_addr + + TryInto::::try_into(section.p_vaddr + section.p_memsz).unwrap(); + if addr > last_bss { + last_bss = addr; + bss_prot = Some(elf_prot); + } + } + } + Self::pad_zero(elf_bss).map_err(|_| return ExecError::BadAddress(Some(elf_bss)))?; + elf_bss = Self::elf_page_align_up(elf_bss); + last_bss = Self::elf_page_align_up(last_bss); + if last_bss > elf_bss { + if bss_prot.is_none() { + return Err(ExecError::InvalidParemeter); + } + let mut bss_prot = bss_prot.unwrap(); + if bss_prot.contains(ProtFlags::PROT_EXEC) { + bss_prot = ProtFlags::PROT_EXEC; + } else { + bss_prot = ProtFlags::PROT_NONE; + } + interp_elf_ex + .vm() + .clone() + .write() + .map_anonymous( + elf_bss, + last_bss - elf_bss, + bss_prot, + MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED_NOREPLACE, + false, + true, + ) + .map_err(|e| match e { + SystemError::EINVAL => ExecError::InvalidParemeter, + SystemError::ENOMEM => ExecError::OutOfMemory, + _ => return ExecError::InvalidParemeter, + })?; + } + load_addr += TryInto::::try_into(interp_hdr.e_entry).unwrap(); + if load_addr > MMArch::USER_END_VADDR { + return Err(ExecError::BadAddress(Some( + load_addr + TryInto::::try_into(interp_hdr.e_entry).unwrap(), + ))); + } + // log::debug!("sucessfully load elf interp"); + return Ok(BinaryLoaderResult::new(load_addr)); + } + /// 加载ELF文件到用户空间 /// /// ## 参数 @@ -335,7 +483,6 @@ impl ElfLoader { /// - `offset_in_file`:在文件内的偏移量 /// - `param`:执行参数 fn do_load_file( - &self, mut vaddr: VirtAddr, size: usize, offset_in_file: usize, @@ -367,8 +514,8 @@ impl ElfLoader { } /// 我们需要显式的把数据段之后剩余的内存页都清零。 - fn pad_zero(&self, elf_bss: VirtAddr) -> Result<(), SystemError> { - let nbyte = self.elf_page_offset(elf_bss); + fn pad_zero(elf_bss: VirtAddr) -> Result<(), SystemError> { + let nbyte = Self::elf_page_offset(elf_bss); if nbyte > 0 { let nbyte = CurrentElfArch::ELF_PAGE_SIZE - nbyte; unsafe { clear_user(elf_bss, nbyte).map_err(|_| SystemError::EFAULT) }?; @@ -376,6 +523,37 @@ impl ElfLoader { return Ok(()); } + /// 参考https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#1158,获取要加载的total_size + fn total_mapping_size(ehdr_table: &SegmentTable<'_, AnyEndian>) -> usize { + let mut has_load = false; + let mut min_address = VirtAddr::new(usize::MAX); + let mut max_address = VirtAddr::new(0usize); + let loadable_sections = ehdr_table + .into_iter() + .filter(|seg| seg.p_type == elf::abi::PT_LOAD); + for seg_to_load in loadable_sections { + min_address = min( + min_address, + Self::elf_page_start(VirtAddr::new(seg_to_load.p_vaddr.try_into().unwrap())), + ); + max_address = max( + max_address, + VirtAddr::new( + (seg_to_load.p_vaddr + seg_to_load.p_memsz) + .try_into() + .unwrap(), + ), + ); + has_load = true; + } + let total_size = if has_load { + max_address - min_address + } else { + 0 + }; + return total_size; + } + /// 创建auxv /// /// ## 参数 @@ -562,7 +740,7 @@ impl BinaryLoader for ElfLoader { .map_err(|_| ExecError::ParseError)? .ok_or(ExecError::ParseError)?; let mut _gnu_property_data: Option = None; - let interpreter: Option = None; + let mut interpreter: Option = None; for seg in phdr_table { if seg.p_type == PT_GNU_PROPERTY { _gnu_property_data = Some(seg); @@ -594,8 +772,8 @@ impl BinaryLoader for ElfLoader { log::error!("Failed to load interpreter "); return Err(ExecError::NotSupported); } - let _interpreter_path = core::str::from_utf8( - &buffer[0..TryInto::::try_into(seg.p_filesz).unwrap() - 1], // + let interpreter_path = core::str::from_utf8( + &buffer[0..TryInto::::try_into(seg.p_filesz).unwrap() - 1], ) .map_err(|e| { ExecError::Other(format!( @@ -603,9 +781,17 @@ impl BinaryLoader for ElfLoader { e )) })?; - - //TODO 加入对动态链接器的加载,参照 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#890 + // log::debug!("opening interpreter at :{}", interpreter_path); + interpreter = Some( + ExecParam::new(interpreter_path, param.vm().clone(), ExecParamFlags::EXEC) + .map_err(|e| { + log::error!("Failed to load interpreter {interpreter_path}: {:?}", e); + return ExecError::NotSupported; + })?, + ); } + //TODO 缺少一部分逻辑 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#931 + if interpreter.is_some() { /* Some simple consistency checks for the interpreter */ // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#950 @@ -627,39 +813,14 @@ impl BinaryLoader for ElfLoader { // program header的虚拟地址 let mut phdr_vaddr: Option = None; let mut _reloc_func_desc = 0usize; - // 参考https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#1158,获取要加载的total_size - let mut has_load = false; - let mut min_address = VirtAddr::new(usize::MAX); - let mut max_address = VirtAddr::new(0usize); + + let total_size = Self::total_mapping_size(&phdr_table); let loadable_sections = phdr_table .into_iter() .filter(|seg| seg.p_type == elf::abi::PT_LOAD); for seg_to_load in loadable_sections { - min_address = min( - min_address, - self.elf_page_start(VirtAddr::new(seg_to_load.p_vaddr.try_into().unwrap())), - ); - max_address = max( - max_address, - VirtAddr::new( - (seg_to_load.p_vaddr + seg_to_load.p_memsz) - .try_into() - .unwrap(), - ), - ); - has_load = true; - } - let total_size = if has_load { - max_address - min_address - } else { - 0 - }; - let loadable_sections = phdr_table - .into_iter() - .filter(|seg| seg.p_type == elf::abi::PT_LOAD); - for seg_to_load in loadable_sections { - // debug!("seg_to_load = {:?}", seg_to_load); + // log::debug!("seg_to_load = {:?}", seg_to_load); if unlikely(elf_brk > elf_bss) { // debug!( // "to set brk, elf_brk = {:?}, elf_bss = {:?}", @@ -672,7 +833,7 @@ impl BinaryLoader for ElfLoader { elf_brk + load_bias, bss_prot_flags, )?; - let nbyte = self.elf_page_offset(elf_bss); + let nbyte = Self::elf_page_offset(elf_bss); if nbyte > 0 { let nbyte = min(CurrentElfArch::ELF_PAGE_SIZE - nbyte, elf_brk - elf_bss); unsafe { @@ -684,7 +845,7 @@ impl BinaryLoader for ElfLoader { } // 生成ProtFlags. - let elf_prot_flags = self.make_prot(seg_to_load.p_flags, interpreter.is_some(), false); + let elf_prot_flags = Self::make_prot(seg_to_load.p_flags, interpreter.is_some(), false); let mut elf_map_flags = MapFlags::MAP_PRIVATE; @@ -713,37 +874,33 @@ impl BinaryLoader for ElfLoader { load_bias = 0; } } - load_bias = self - .elf_page_start(VirtAddr::new( - load_bias - TryInto::::try_into(seg_to_load.p_vaddr).unwrap(), - )) - .data(); + load_bias = Self::elf_page_start(VirtAddr::new( + load_bias - TryInto::::try_into(seg_to_load.p_vaddr).unwrap(), + )) + .data(); if total_size == 0 { return Err(ExecError::InvalidParemeter); } } // 加载这个段到用户空间 - // debug!("to load elf segment"); - let e = self - .load_elf_segment( - &mut user_vm, - param, - &seg_to_load, - vaddr + load_bias, - &elf_prot_flags, - &elf_map_flags, - total_size, - ) - .map_err(|e| { - error!("load_elf_segment failed: {:?}", e); - match e { - SystemError::EFAULT => ExecError::BadAddress(None), - SystemError::ENOMEM => ExecError::OutOfMemory, - _ => ExecError::Other(format!("load_elf_segment failed: {:?}", e)), - } - })?; + // log::debug!("bias: {load_bias}"); + let e = Self::load_elf_segment( + &mut user_vm, + param, + &seg_to_load, + vaddr + load_bias, + &elf_prot_flags, + &elf_map_flags, + total_size, + ) + .map_err(|e| match e { + SystemError::EFAULT => ExecError::BadAddress(None), + SystemError::ENOMEM => ExecError::OutOfMemory, + _ => ExecError::Other(format!("load_elf_segment failed: {:?}", e)), + })?; + // log::debug!("e.0={:?}", e.0); // 如果地址不对,那么就报错 if !e.1 { return Err(ExecError::BadAddress(Some(e.0))); @@ -754,12 +911,10 @@ impl BinaryLoader for ElfLoader { if elf_type == ElfType::DSO { // todo: 在这里增加对load_bias和reloc_func_desc的更新代码 load_bias += e.0.data() - - self - .elf_page_start(VirtAddr::new( - load_bias - + TryInto::::try_into(seg_to_load.p_vaddr).unwrap(), - )) - .data(); + - Self::elf_page_start(VirtAddr::new( + load_bias + TryInto::::try_into(seg_to_load.p_vaddr).unwrap(), + )) + .data(); _reloc_func_desc = load_bias; } } @@ -793,7 +948,7 @@ impl BinaryLoader for ElfLoader { // 如果程序段要加载的目标地址不在用户空间内,或者是其他不合法的情况,那么就报错 if !p_vaddr.check_user() || seg_to_load.p_filesz > seg_to_load.p_memsz - || self.elf_page_align_up(p_vaddr + seg_to_load.p_memsz as usize) + || Self::elf_page_align_up(p_vaddr + seg_to_load.p_memsz as usize) >= MMArch::USER_END_VADDR { // debug!("ERR: p_vaddr={p_vaddr:?}"); @@ -801,7 +956,7 @@ impl BinaryLoader for ElfLoader { } // end vaddr of this segment(code+data+bss) - let seg_end_vaddr_f = self.elf_page_align_up(VirtAddr::new( + let seg_end_vaddr_f = Self::elf_page_align_up(VirtAddr::new( (seg_to_load.p_vaddr + seg_to_load.p_filesz) as usize, )); @@ -839,7 +994,7 @@ impl BinaryLoader for ElfLoader { end_code = end_code.map(|v| v + load_bias); start_data = start_data.map(|v| v + load_bias); end_data = end_data.map(|v| v + load_bias); - + let mut interp_load_addr: Option = None; // debug!( // "to set brk: elf_bss: {:?}, elf_brk: {:?}, bss_prot_flags: {:?}", // elf_bss, @@ -848,16 +1003,27 @@ impl BinaryLoader for ElfLoader { // ); self.set_elf_brk(&mut user_vm, elf_bss, elf_brk, bss_prot_flags)?; - if likely(elf_bss != elf_brk) && unlikely(self.pad_zero(elf_bss).is_err()) { + if likely(elf_bss != elf_brk) && unlikely(Self::pad_zero(elf_bss).is_err()) { // debug!("elf_bss = {elf_bss:?}, elf_brk = {elf_brk:?}"); return Err(ExecError::BadAddress(Some(elf_bss))); } - if interpreter.is_some() { - // TODO 添加对动态加载器的处理 + drop(user_vm); + if let Some(mut interpreter) = interpreter { // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#1249 + let elf_entry = Self::load_elf_interp(&mut interpreter, load_bias)?.entry_point(); + interp_load_addr = Some(elf_entry); + _reloc_func_desc = elf_entry.data(); + //参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#1269 + //TODO allow_write_access(interpreter); + ProcessManager::current_pcb() + .fd_table() + .write() + .alloc_fd(interpreter.file(), None) + .map(|fd| fd as usize) + .map_err(|_| ExecError::InvalidParemeter)?; } // debug!("to create auxv"); - + let mut user_vm = binding.write(); self.create_auxv(param, program_entrypoint, phdr_vaddr, &ehdr)?; // debug!("auxv create ok"); @@ -866,8 +1032,8 @@ impl BinaryLoader for ElfLoader { user_vm.start_data = start_data.unwrap_or(VirtAddr::new(0)); user_vm.end_data = end_data.unwrap_or(VirtAddr::new(0)); - let result = BinaryLoaderResult::new(program_entrypoint); - // debug!("elf load OK!!!"); + let result = BinaryLoaderResult::new(interp_load_addr.unwrap_or(program_entrypoint)); + // kdebug!("elf load OK!!!"); return Ok(result); } } diff --git a/kernel/src/libs/futex/futex.rs b/kernel/src/libs/futex/futex.rs index cc651ad2..59e3d431 100644 --- a/kernel/src/libs/futex/futex.rs +++ b/kernel/src/libs/futex/futex.rs @@ -677,7 +677,7 @@ impl RobustListHead { /// - head_uaddr:robust list head用户空间地址 /// - len:robust list head的长度 pub fn set_robust_list(head_uaddr: VirtAddr, len: usize) -> Result { - let robust_list_head_len = mem::size_of::<&RobustListHead>(); + let robust_list_head_len = mem::size_of::(); if unlikely(len != robust_list_head_len) { return Err(SystemError::EINVAL); } diff --git a/kernel/src/libs/rand.rs b/kernel/src/libs/rand.rs index 2bd3c810..d001c9ea 100644 --- a/kernel/src/libs/rand.rs +++ b/kernel/src/libs/rand.rs @@ -1,3 +1,5 @@ +use crate::arch::rand::rand; + bitflags! { pub struct GRandFlags: u8{ const GRND_NONBLOCK = 0x0001; @@ -6,6 +8,46 @@ bitflags! { } } +/// Generates an array of random bytes of size `N`. +/// +/// This function fills an array of size `N` with random bytes by repeatedly +/// generating random numbers and converting them to little-endian byte arrays. +/// The function ensures that the entire array is filled with random bytes, +/// even if the size of the array is not a multiple of the size of `usize`. +/// +/// # Type Parameters +/// +/// * `N`: The size of the array to be filled with random bytes. +/// +/// # Returns +/// +/// An array of size `N` filled with random bytes. +/// +/// # Example +/// +/// ```rust +/// let random_bytes = rand_bytes::<16>(); +/// assert_eq!(random_bytes.len(), 16); +/// ``` +pub fn rand_bytes() -> [u8; N] { + let mut bytes = [0u8; N]; + let mut remaining = N; + let mut index = 0; + + while remaining > 0 { + let random_num = rand(); + let random_bytes = random_num.to_le_bytes(); + + let to_copy = core::cmp::min(remaining, size_of::()); + bytes[index..index + to_copy].copy_from_slice(&random_bytes[..to_copy]); + + index += to_copy; + remaining -= to_copy; + } + + bytes +} + // 软件实现的随机数生成器 #[allow(dead_code)] pub fn soft_rand() -> usize { diff --git a/kernel/src/mm/fault.rs b/kernel/src/mm/fault.rs index 53c05580..f8442d77 100644 --- a/kernel/src/mm/fault.rs +++ b/kernel/src/mm/fault.rs @@ -316,7 +316,6 @@ impl PageFaultHandler { } else { return VmFaultReason::VM_FAULT_OOM; } - ret = ret.union(Self::finish_fault(pfm)); ret @@ -635,7 +634,9 @@ impl PageFaultHandler { // TODO 同步预读 //涉及磁盘IO,返回标志为VM_FAULT_MAJOR ret = VmFaultReason::VM_FAULT_MAJOR; + let mut buffer = Box::new([0u8; MMArch::PAGE_SIZE]); + file.pread( file_pgoff * MMArch::PAGE_SIZE, MMArch::PAGE_SIZE, diff --git a/kernel/src/mm/syscall.rs b/kernel/src/mm/syscall.rs index 6c9646a3..66720d41 100644 --- a/kernel/src/mm/syscall.rs +++ b/kernel/src/mm/syscall.rs @@ -251,7 +251,7 @@ impl From for ProtFlags { impl Syscall { pub fn brk(new_addr: VirtAddr) -> Result { - // debug!("brk: new_addr={:?}", new_addr); + // log::debug!("brk: new_addr={:?}", new_addr); let address_space = AddressSpace::current()?; let mut address_space = address_space.write(); @@ -263,6 +263,7 @@ impl Syscall { } unsafe { + // log::debug!("brk: set_brk new_addr={:?}", new_addr); address_space .set_brk(VirtAddr::new(page_align_up(new_addr.data()))) .ok(); @@ -346,7 +347,6 @@ impl Syscall { false, )? }; - return Ok(start_page.virt_address().data()); } diff --git a/kernel/src/process/abi.rs b/kernel/src/process/abi.rs index cbaab9d0..a39f4ff3 100644 --- a/kernel/src/process/abi.rs +++ b/kernel/src/process/abi.rs @@ -38,7 +38,7 @@ pub enum AtType { /// Frequency at which times() increments. ClkTck, /// Secure mode boolean. - Secure, + Secure = 23, /// String identifying real platform, may differ from AT_PLATFORM. BasePlatform, /// Address of 16 random bytes. @@ -46,7 +46,7 @@ pub enum AtType { /// Extension of AT_HWCAP. HwCap2, /// Filename of program. - ExecFn, + ExecFn = 31, /// Minimal stack size for signal delivery. MinSigStackSize, } diff --git a/kernel/src/process/exec.rs b/kernel/src/process/exec.rs index 0dac0529..5eaae376 100644 --- a/kernel/src/process/exec.rs +++ b/kernel/src/process/exec.rs @@ -157,6 +157,11 @@ impl ExecParam { pub fn file_mut(&mut self) -> &mut File { &mut self.file } + + /// 获取File的所有权,用于将动态链接器加入文件描述符表中 + pub fn file(self) -> File { + self.file + } } /// ## 加载二进制文件 @@ -199,6 +204,7 @@ pub struct ProcInitInfo { pub args: Vec, pub envs: Vec, pub auxv: BTreeMap, + pub rand_num: [u8; 16], } impl ProcInitInfo { @@ -208,6 +214,7 @@ impl ProcInitInfo { args: Vec::new(), envs: Vec::new(), auxv: BTreeMap::new(), + rand_num: [0u8; 16], } } @@ -218,7 +225,7 @@ impl ProcInitInfo { /// /// 返回值是一个元组,第一个元素是最终的用户栈顶地址,第二个元素是环境变量pointer数组的起始地址 pub unsafe fn push_at( - &self, + &mut self, ustack: &mut UserStack, ) -> Result<(VirtAddr, VirtAddr), SystemError> { // 先把程序的名称压入栈中 @@ -233,6 +240,7 @@ impl ProcInitInfo { ustack.sp() }) .collect::>(); + // 然后把参数压入栈中 let argps = self .args @@ -243,6 +251,20 @@ impl ProcInitInfo { }) .collect::>(); + // 压入随机数,把指针放入auxv + self.push_slice(ustack, &[self.rand_num])?; + self.auxv + .insert(super::abi::AtType::Random as u8, ustack.sp().data()); + + // 实现栈的16字节对齐 + // 用当前栈顶地址减去后续要压栈的长度,得到的压栈后的栈顶地址与0xF按位与操作得到对齐要填充的字节数 + let length_to_push = (self.auxv.len() + envps.len() + 1 + argps.len() + 1 + 1) + * core::mem::align_of::(); + self.push_slice( + ustack, + &vec![0u8; (ustack.sp().data() - length_to_push) & 0xF], + )?; + // 压入auxv self.push_slice(ustack, &[null::(), null::()])?; for (&k, &v) in self.auxv.iter() { @@ -256,7 +278,6 @@ impl ProcInitInfo { // 把参数指针压入栈中 self.push_slice(ustack, &[null::()])?; self.push_slice(ustack, argps.as_slice())?; - let argv_ptr = ustack.sp(); // 把argc压入栈中 diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 77741b5e..1aa904dd 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -1574,8 +1574,8 @@ pub struct KernelStack { } impl KernelStack { - pub const SIZE: usize = 0x4000; - pub const ALIGN: usize = 0x4000; + pub const SIZE: usize = 0x8000; + pub const ALIGN: usize = 0x8000; pub fn new() -> Result { return Ok(Self { diff --git a/kernel/src/process/syscall.rs b/kernel/src/process/syscall.rs index b464e66f..2276113a 100644 --- a/kernel/src/process/syscall.rs +++ b/kernel/src/process/syscall.rs @@ -25,6 +25,7 @@ use crate::{ procfs::procfs_register_pid, vfs::{file::FileDescriptorVec, MAX_PATHLEN}, }, + libs::rand::rand_bytes, mm::{ ucontext::{AddressSpace, UserStack}, verify_area, MemoryManagementArch, VirtAddr, @@ -50,10 +51,10 @@ pub struct PosixOldUtsName { impl PosixOldUtsName { pub fn new() -> Self { - const SYS_NAME: &[u8] = b"DragonOS"; + const SYS_NAME: &[u8] = b"Linux"; const NODENAME: &[u8] = b"DragonOS"; - const RELEASE: &[u8] = env!("CARGO_PKG_VERSION").as_bytes(); - const VERSION: &[u8] = env!("CARGO_PKG_VERSION").as_bytes(); + const RELEASE: &[u8] = b"5.19.0"; + const VERSION: &[u8] = b"5.19.0"; #[cfg(target_arch = "x86_64")] const MACHINE: &[u8] = b"x86_64"; @@ -176,6 +177,8 @@ impl Syscall { // debug!("argv: {:?}, envp: {:?}", argv, envp); param.init_info_mut().args = argv; param.init_info_mut().envs = envp; + // // 生成16字节随机数 + param.init_info_mut().rand_num = rand_bytes::<16>(); // 把proc_init_info写到用户栈上 let mut ustack_message = unsafe { @@ -187,7 +190,7 @@ impl Syscall { }; let (user_sp, argv_ptr) = unsafe { param - .init_info() + .init_info_mut() .push_at( // address_space // .write() @@ -338,7 +341,7 @@ impl Syscall { /// @brief 获取当前进程的父进程id /// - /// 若为initproc则ppid设置为0 + /// 若为initproc则ppid设置为0 pub fn getppid() -> Result { let current_pcb = ProcessManager::current_pcb(); return Ok(current_pcb.basic().ppid()); diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 2cc41f8f..730c58a4 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -30,7 +30,6 @@ use crate::{ filesystem::vfs::{ fcntl::{AtFlags, FcntlCommand}, file::FileMode, - stat::PosixKstat, syscall::{ModeType, UtimensFlags}, MAX_PATHLEN, }, @@ -668,14 +667,7 @@ impl Syscall { #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] SYS_FSTAT => { let fd = args[0] as i32; - let kstat: *mut PosixKstat = args[1] as *mut PosixKstat; - let vaddr = VirtAddr::new(kstat as usize); - // FIXME 由于c中的verify_area与rust中的verify_area重名,所以在引入时加了前缀区分 - // TODO 应该将用了c版本的verify_area都改为rust的verify_area - match verify_area(vaddr, core::mem::size_of::()) { - Ok(_) => Self::fstat(fd, kstat), - Err(e) => Err(e), - } + Self::fstat(fd, args[1]) } SYS_FCNTL => { @@ -778,15 +770,13 @@ impl Syscall { #[cfg(target_arch = "x86_64")] SYS_LSTAT => { let path = args[0] as *const u8; - let kstat = args[1] as *mut PosixKstat; - Self::lstat(path, kstat) + Self::lstat(path, args[1]) } #[cfg(target_arch = "x86_64")] SYS_STAT => { let path = args[0] as *const u8; - let kstat = args[1] as *mut PosixKstat; - Self::stat(path, kstat) + Self::stat(path, args[1]) } SYS_STATFS => { @@ -902,8 +892,10 @@ impl Syscall { } SYS_EXIT_GROUP => { - warn!("SYS_EXIT_GROUP has not yet been implemented"); - Ok(0) + let exit_code = args[0]; + Self::exit(exit_code) + // warn!("SYS_EXIT_GROUP has not yet been implemented"); + // Ok(0) } SYS_MADVISE => { @@ -1051,7 +1043,7 @@ impl Syscall { SYS_RSEQ => { warn!("SYS_RSEQ has not yet been implemented"); - Ok(0) + Err(SystemError::ENOSYS) } #[cfg(target_arch = "x86_64")] diff --git a/tools/BUILD_CONTAINER_VERSION b/tools/BUILD_CONTAINER_VERSION index b4ffd191..f5a8e286 100644 --- a/tools/BUILD_CONTAINER_VERSION +++ b/tools/BUILD_CONTAINER_VERSION @@ -1 +1 @@ -v1.11 \ No newline at end of file +v1.12 \ No newline at end of file diff --git a/tools/bootstrap.sh b/tools/bootstrap.sh index fd2e68b9..e14535fee 100755 --- a/tools/bootstrap.sh +++ b/tools/bootstrap.sh @@ -338,7 +338,7 @@ rustInstall install_python_pkg # 安装dadk -cargo install dadk || exit 1 +cargo install --git https://git.mirrors.dragonos.org.cn/DragonOS-Community/DADK.git --tag v0.4.0 || exit 1 bashpath=$(cd `dirname $0`; pwd) diff --git a/tools/build_in_docker.sh b/tools/build_in_docker.sh index 6735db68..db679c94 100755 --- a/tools/build_in_docker.sh +++ b/tools/build_in_docker.sh @@ -1,6 +1,6 @@ docker rm -f dragonos-build || echo "No existed container" cpu_count=$(cat /proc/cpuinfo |grep "processor"|wc -l) -docker run --rm --privileged=true --cap-add SYS_ADMIN --cap-add MKNOD -v $(pwd):/data -v /dev:/dev -v dragonos-build-cargo:/root/.cargo/registry --name dragonos-build -i dragonos/dragonos-dev:v1.11 bash << EOF +docker run --rm --privileged=true --cap-add SYS_ADMIN --cap-add MKNOD -v $(pwd):/data -v /dev:/dev -v dragonos-build-cargo:/root/.cargo/registry --name dragonos-build -i dragonos/dragonos-dev:v1.12 bash << EOF source ~/.cargo/env source ~/.bashrc cd /data diff --git a/tools/write_disk_image.sh b/tools/write_disk_image.sh index 24017c9a..c9522f58 100755 --- a/tools/write_disk_image.sh +++ b/tools/write_disk_image.sh @@ -79,6 +79,9 @@ $DADK -w $root_folder rootfs mount || exit 1 LOOP_DEVICE=$($DADK -w $root_folder rootfs show-loop-device || exit 1) echo $LOOP_DEVICE echo ${mount_folder} + +FS_TYPE=$(findmnt -n -o FSTYPE ${mount_folder} || df -T ${mount_folder} | tail -1 | awk '{print $2}') +echo "FS_TYPE: $FS_TYPE" # mkdir -p ${GRUB_INSTALL_PATH} # 检测grub文件夹是否存在 @@ -99,7 +102,12 @@ mkdir -p ${mount_folder}/bin mkdir -p ${mount_folder}/dev mkdir -p ${mount_folder}/proc mkdir -p ${mount_folder}/usr -cp -r ${root_folder}/bin/sysroot/* ${mount_folder}/ + +if [ "$FS_TYPE" = "vfat" ] || [ "$FS_TYPE" = "fat32" ]; then + cp -rL ${root_folder}/bin/sysroot/* ${mount_folder}/ +else + cp -r ${root_folder}/bin/sysroot/* ${mount_folder}/ +fi # 设置 grub 相关数据 if [ ${ARCH} == "i386" ] || [ ${ARCH} == "x86_64" ]; then diff --git a/user/Makefile b/user/Makefile index 0b9c3a98..1f720d74 100644 --- a/user/Makefile +++ b/user/Makefile @@ -2,7 +2,7 @@ user_sub_dirs = apps DADK_VERSION=$(shell dadk -V | awk 'END {print $$2}') # 最小的DADK版本 -MIN_DADK_VERSION = 0.3.0 +MIN_DADK_VERSION = 0.4.0 DADK_CACHE_DIR = $(ROOT_PATH)/bin/dadk_cache ECHO: @@ -20,7 +20,7 @@ ifeq ("$(DADK_VERSION)", "") @echo "\n\tcargo install --git https://git.mirrors.dragonos.org.cn/DragonOS-Community/DADK.git --tag v$(MIN_DADK_VERSION)" --locked @echo "\n" @echo "Auto installing dadk..." - cargo install dadk + cargo install --git https://git.mirrors.dragonos.org.cn/DragonOS-Community/DADK.git --tag v$(MIN_DADK_VERSION)" --locked else # 如果DADK版本过低,则自动更新 @echo "dadk version $(DADK_VERSION) installed" diff --git a/user/apps/clear/Makefile b/user/apps/clear/Makefile index 0d140353..261eba3d 100644 --- a/user/apps/clear/Makefile +++ b/user/apps/clear/Makefile @@ -10,7 +10,7 @@ else endif ifeq ($(ARCH), x86_64) - export RUST_TARGET=x86_64-unknown-linux-musl + export RUST_TARGET=x86_64-unknown-linux-gnu else ifeq ($(ARCH), riscv64) export RUST_TARGET=riscv64gc-unknown-linux-gnu else diff --git a/user/apps/test_fstat/Makefile b/user/apps/test_fstat/Makefile index 6fd5da61..3ccc94bc 100644 --- a/user/apps/test_fstat/Makefile +++ b/user/apps/test_fstat/Makefile @@ -1,5 +1,5 @@ ifeq ($(ARCH), x86_64) - CROSS_COMPILE=x86_64-linux-musl- + CROSS_COMPILE=x86_64-linux-gnu- else ifeq ($(ARCH), riscv64) CROSS_COMPILE=riscv64-linux-musl- endif @@ -8,7 +8,7 @@ CC=$(CROSS_COMPILE)gcc .PHONY: all all: main.c - $(CC) -static -o test_fstat main.c + $(CC) -o test_fstat main.c .PHONY: install clean install: all diff --git a/user/apps/test_newfstatat/Makefile b/user/apps/test_newfstatat/Makefile index bfd2cd45..49682068 100644 --- a/user/apps/test_newfstatat/Makefile +++ b/user/apps/test_newfstatat/Makefile @@ -1,5 +1,5 @@ ifeq ($(ARCH), x86_64) - CROSS_COMPILE=x86_64-linux-musl- + CROSS_COMPILE=x86_64-linux-gnu- else ifeq ($(ARCH), riscv64) CROSS_COMPILE=riscv64-linux-musl- endif @@ -8,7 +8,7 @@ CC=$(CROSS_COMPILE)gcc .PHONY: all all: main.c - $(CC) -static -o test_newfstatat main.c + $(CC) -o test_newfstatat main.c .PHONY: install clean install: all diff --git a/user/dadk/config/core_utils-9.4.0.toml b/user/dadk/config/core_utils-9.4.0.toml index eaf93230..8860f901 100644 --- a/user/dadk/config/core_utils-9.4.0.toml +++ b/user/dadk/config/core_utils-9.4.0.toml @@ -22,6 +22,10 @@ type = "build-from-source" source = "archive" # 路径或URL source-path = "https://mirrors.dragonos.org.cn/pub/third_party/gnu/coreutils/coreutils-9.4.tar.xz" + +# 把压缩包中的哪个目录作为根目录(可选),仅当 source = "archive" 时生效 +archive-rootdir = "coreutils-9.4" + # 构建相关信息 [build] # (可选)构建命令 diff --git a/user/dadk/config/glibc_bin_ubuntu2404.toml b/user/dadk/config/glibc_bin_ubuntu2404.toml new file mode 100644 index 00000000..f455b198 --- /dev/null +++ b/user/dadk/config/glibc_bin_ubuntu2404.toml @@ -0,0 +1,40 @@ +# 用户程序名称 +name = "glibc_bin_ubuntu2404" +# 版本号 +version = "2.39" +# 用户程序描述信息 +description = "GNU C Library for Ubuntu 24.04" +# (可选)默认: false 是否只构建一次,如果为true,DADK会在构建成功后,将构建结果缓存起来,下次构建时,直接使用缓存的构建结果 +build-once = false +# (可选) 默认: false 是否只安装一次,如果为true,DADK会在安装成功后,不再重复安装 +install-once = false +# 目标架构 +# 可选值:"x86_64", "aarch64", "riscv64", "loongarch64" +target-arch = ["x86_64"] +# 任务源 +[task-source] +# 构建类型 +# 可选值:"build-from-source", "install-from-prebuilt" +type = "install-from-prebuilt" +# 构建来源 +# "build_from_source" 可选值:"git", "local", "archive" +# "install_from_prebuilt" 可选值:"local", "archive" +source = "archive" +# 路径或URL +source-path = "https://mirrors.dragonos.org.cn/pub/third_party/gnu/glibc-bin/glibc-ubuntu2404-x86_64-202505111756-8f3207567bf10f4d09027b2cd84b7807.tar.xz" +archive-rootdir = "sysroot/" + +[build] + +# 安装相关信息 +[install] +# (可选)安装到DragonOS的路径 +in-dragonos-path = "/" +# 清除相关信息 +[clean] +# (可选)清除命令 +clean-command = "" +# (可选)依赖项 +# 注意:如果没有依赖项,忽略此项,不允许只留一个[[depends]] +# (可选)环境变量 +# 注意:如果没有环境变量,忽略此项,不允许只留一个[[envs]] diff --git a/user/dadk/config/musl_1_2_4.toml b/user/dadk/config/musl_1_2_4.toml index bad7c371..ec2026f4 100644 --- a/user/dadk/config/musl_1_2_4.toml +++ b/user/dadk/config/musl_1_2_4.toml @@ -22,10 +22,13 @@ type = "build-from-source" source = "archive" # 路径或URL source-path = "https://mirrors.dragonos.org.cn/pub/third_party/musl/musl-1.2.4.tar.gz" +# 把压缩包中的哪个目录作为根目录(可选),仅当 source = "archive" 时生效 +archive-rootdir = "musl-1.2.4" + # 构建相关信息 [build] # (可选)构建命令 -build-command = "touch config.mak && DESTDIR=$DADK_CURRENT_BUILD_DIR make install -j $(nproc)" +build-command = "touch config.mak && DESTDIR=$DADK_CURRENT_BUILD_DIR make install -j $(nproc) && rm -rf $DADK_CURRENT_BUILD_DIR/lib && rm -rf $DADK_CURRENT_BUILD_DIR/lib64" # 安装相关信息 [install] # (可选)安装到DragonOS的路径 diff --git a/user/sysconfig/etc/reach/system/shell.service b/user/sysconfig/etc/reach/system/shell.service index c11de496..942924e2 100644 --- a/user/sysconfig/etc/reach/system/shell.service +++ b/user/sysconfig/etc/reach/system/shell.service @@ -7,4 +7,5 @@ ExecStart=/bin/NovaShell Restart=always ExecStartPre=-/bin/about.elf ExecStartPre=/bin/busybox stty erase 127 -Environment=PATH=/bin:/usr/bin:/usr/local/bin \ No newline at end of file +Environment=PATH=/bin:/usr/bin:/usr/local/bin +Environment=LD_LIBRARY_PATH=/usr/lib:/usr/lib64:/usr/local/lib