Explorar o código

Merge branch 'master' into robust-list

greatbridf hai 7 meses
pai
achega
1751a0cb89

+ 2 - 2
crates/eonix_hal/src/arch/riscv64/memory.x

@@ -2,10 +2,10 @@ OUTPUT_ARCH(riscv)
 ENTRY(_start)
 
 MEMORY {
-    RAM    : org = 0x0000000080200000, len = 4M
+    RAM    : org = 0x0000000080200000, len = 8M
     VDSO   : org = 0x00007f0000000000, len = 4K
     KBSS   : org = 0xffffffff40000000, len = 2M
-    KIMAGE : org = 0xffffffff80200000, len = 2M
+    KIMAGE : org = 0xffffffff80200000, len = 8M
 }
 
 REGION_ALIAS("REGION_TEXT", KIMAGE);

+ 7 - 7
crates/posix_types/src/stat.rs

@@ -46,14 +46,14 @@ pub struct Stat {
     pub st_dev: u64,
     pub st_ino: u64,
     pub st_mode: u32,
-    pub st_nlink: usize,
+    pub st_nlink: u32,
     pub st_uid: u32,
     pub st_gid: u32,
     pub st_rdev: u64,
-    __padding: usize,
+    __padding: u64,
 
     pub st_size: u64,
-    pub st_blksize: usize,
+    pub st_blksize: u32,
     __padding2: u32,
 
     pub st_blocks: u64,
@@ -65,17 +65,17 @@ pub struct Stat {
 impl From<StatX> for Stat {
     fn from(statx: StatX) -> Self {
         Self {
-            st_dev: statx.stx_dev_major as u64 | ((statx.stx_dev_minor as u64) << 32),
+            st_dev: statx.stx_dev_minor as u64 | ((statx.stx_dev_major as u64) << 8),
             st_ino: statx.stx_ino,
             st_mode: statx.stx_mode as u32,
-            st_nlink: statx.stx_nlink as usize,
+            st_nlink: statx.stx_nlink,
             st_uid: statx.stx_uid,
             st_gid: statx.stx_gid,
-            st_rdev: statx.stx_rdev_major as u64 | ((statx.stx_rdev_minor as u64) << 32),
+            st_rdev: statx.stx_rdev_minor as u64 | ((statx.stx_rdev_major as u64) << 8),
             __padding: 0,
 
             st_size: statx.stx_size,
-            st_blksize: statx.stx_blksize as usize,
+            st_blksize: statx.stx_blksize,
             __padding2: 0,
 
             st_blocks: statx.stx_blocks,

+ 1 - 1
crates/posix_types/src/syscall_no/riscv64.rs

@@ -88,7 +88,7 @@ pub const SYS_SYNC_FILE_RANGE: usize = 84;
 pub const SYS_TIMERFD_CREATE: usize = 85;
 pub const SYS_TIMERFD_SETTIME: usize = 411;
 pub const SYS_TIMERFD_GETTIME: usize = 410;
-pub const SYS_UTIMENSAT: usize = 412;
+pub const SYS_UTIMENSAT: usize = 88;
 pub const SYS_ACCT: usize = 89;
 pub const SYS_CAPGET: usize = 90;
 pub const SYS_CAPSET: usize = 91;

+ 1 - 1
src/kernel/mem/mm_list.rs

@@ -753,7 +753,7 @@ where
             .as_page_attr()
             .expect("Not a page attribute");
 
-        if !from_attr.contains(PageAttribute::PRESENT) {
+        if !from_attr.intersects(PageAttribute::PRESENT | PageAttribute::MAPPED) {
             return;
         }
 

+ 3 - 3
src/kernel/mem/mm_list/page_fault.rs

@@ -35,15 +35,15 @@ impl FixEntry {
 
     fn entries() -> &'static [FixEntry] {
         extern "C" {
-            static FIX_START: *const FixEntry;
-            static FIX_END: *const FixEntry;
+            fn FIX_START();
+            fn FIX_END();
         }
 
         unsafe {
             // SAFETY: `FIX_START` and `FIX_END` are defined in the
             //         linker script in `.rodata` section.
             core::slice::from_raw_parts(
-                FIX_START,
+                FIX_START as usize as *const FixEntry,
                 (FIX_END as usize - FIX_START as usize) / size_of::<FixEntry>(),
             )
         }

+ 8 - 0
src/kernel/syscall.rs

@@ -68,6 +68,14 @@ impl SyscallRetVal for SyscallNoReturn {
     }
 }
 
+#[cfg(not(target_arch = "x86_64"))]
+impl SyscallRetVal for u64 {
+    fn into_retval(self) -> Option<usize> {
+        Some(self as usize)
+    }
+}
+
+#[cfg(not(target_arch = "x86_64"))]
 impl FromSyscallArg for u64 {
     fn from_arg(value: usize) -> u64 {
         value as u64

+ 98 - 16
src/kernel/syscall/file_rw.rs

@@ -25,9 +25,12 @@ use eonix_runtime::task::Task;
 use posix_types::ctypes::{Long, PtrT};
 use posix_types::open::{AtFlags, OpenFlags};
 use posix_types::signal::SigSet;
-use posix_types::stat::{Stat, StatX, TimeSpec};
+use posix_types::stat::{StatX, TimeSpec};
 use posix_types::syscall_no::*;
 
+#[cfg(not(target_arch = "x86_64"))]
+use posix_types::stat::Stat;
+
 impl FromSyscallArg for OpenFlags {
     fn from_arg(value: usize) -> Self {
         OpenFlags::from_bits_retain(value as u32)
@@ -275,20 +278,30 @@ fn readlink(pathname: *const u8, buffer: *mut u8, bufsize: usize) -> KResult<usi
     sys_readlinkat(thread, FD::AT_FDCWD, pathname, buffer, bufsize)
 }
 
-#[cfg(target_arch = "x86_64")]
-#[eonix_macros::define_syscall(SYS_LLSEEK)]
-fn llseek(fd: FD, offset_high: u32, offset_low: u32, result: *mut u64, whence: u32) -> KResult<()> {
-    let mut result = UserBuffer::new(result as *mut u8, core::mem::size_of::<u64>())?;
+fn do_lseek(thread: &Thread, fd: FD, offset: u64, whence: u32) -> KResult<u64> {
     let file = thread.files.get(fd).ok_or(EBADF)?;
 
-    let offset = ((offset_high as u64) << 32) | offset_low as u64;
-
-    let new_offset = match whence {
+    Ok(match whence {
         SEEK_SET => file.seek(SeekOption::Set(offset as usize))?,
         SEEK_CUR => file.seek(SeekOption::Current(offset as isize))?,
         SEEK_END => file.seek(SeekOption::End(offset as isize))?,
         _ => return Err(EINVAL),
-    } as u64;
+    } as u64)
+}
+
+#[cfg(not(target_arch = "x86_64"))]
+#[eonix_macros::define_syscall(SYS_LSEEK)]
+fn lseek(fd: FD, offset: u64, whence: u32) -> KResult<u64> {
+    do_lseek(thread, fd, offset, whence)
+}
+
+#[cfg(target_arch = "x86_64")]
+#[eonix_macros::define_syscall(SYS_LLSEEK)]
+fn llseek(fd: FD, offset_high: u32, offset_low: u32, result: *mut u64, whence: u32) -> KResult<()> {
+    let mut result = UserBuffer::new(result as *mut u8, core::mem::size_of::<u64>())?;
+    let offset = ((offset_high as u64) << 32) | (offset_low as u64);
+
+    let new_offset = do_lseek(thread, fd, offset, whence)?;
 
     result.copy(&new_offset)?.ok_or(EFAULT)
 }
@@ -370,13 +383,14 @@ fn writev(fd: FD, iov_user: *const IoVec, iovcnt: u32) -> KResult<usize> {
     Ok(tot)
 }
 
-#[cfg(target_arch = "x86_64")]
-#[eonix_macros::define_syscall(SYS_ACCESS)]
-fn access(pathname: *const u8, _mode: u32) -> KResult<()> {
-    let path = UserString::new(pathname)?;
-    let path = Path::new(path.as_cstr().to_bytes())?;
-
-    let dentry = Dentry::open(&thread.fs_context, path, true)?;
+#[eonix_macros::define_syscall(SYS_FACCESSAT)]
+fn faccessat(dirfd: FD, pathname: *const u8, _mode: u32, flags: AtFlags) -> KResult<()> {
+    let dentry = if flags.at_empty_path() {
+        let file = thread.files.get(dirfd).ok_or(EBADF)?;
+        file.as_path().ok_or(EBADF)?.clone()
+    } else {
+        dentry_from(thread, dirfd, pathname, !flags.no_follow())?
+    };
 
     if !dentry.is_valid() {
         return Err(ENOENT);
@@ -390,9 +404,16 @@ fn access(pathname: *const u8, _mode: u32) -> KResult<()> {
     //     X_OK => todo!(),
     //     _ => Err(EINVAL),
     // }
+
     Ok(())
 }
 
+#[cfg(target_arch = "x86_64")]
+#[eonix_macros::define_syscall(SYS_ACCESS)]
+fn access(pathname: *const u8, mode: u32) -> KResult<()> {
+    sys_faccessat(thread, FD::AT_FDCWD, pathname, mode, AtFlags::empty())
+}
+
 #[eonix_macros::define_syscall(SYS_SENDFILE64)]
 fn sendfile64(out_fd: FD, in_fd: FD, offset: *mut u8, count: usize) -> KResult<usize> {
     let in_file = thread.files.get(in_fd).ok_or(EBADF)?;
@@ -463,4 +484,65 @@ fn poll(fds: *mut UserPollFd, nfds: u32, timeout: u32) -> KResult<u32> {
     do_poll(thread, fds, nfds, timeout)
 }
 
+#[eonix_macros::define_syscall(SYS_FCHOWNAT)]
+fn fchownat(dirfd: FD, pathname: *const u8, uid: u32, gid: u32, flags: AtFlags) -> KResult<()> {
+    let dentry = dentry_from(thread, dirfd, pathname, !flags.no_follow())?;
+    if !dentry.is_valid() {
+        return Err(ENOENT);
+    }
+
+    dentry.chown(uid, gid)
+}
+
+#[eonix_macros::define_syscall(SYS_FCHMODAT)]
+fn fchmodat(dirfd: FD, pathname: *const u8, mode: u32, flags: AtFlags) -> KResult<()> {
+    let dentry = if flags.at_empty_path() {
+        let file = thread.files.get(dirfd).ok_or(EBADF)?;
+        file.as_path().ok_or(EBADF)?.clone()
+    } else {
+        dentry_from(thread, dirfd, pathname, !flags.no_follow())?
+    };
+
+    if !dentry.is_valid() {
+        return Err(ENOENT);
+    }
+
+    dentry.chmod(mode)
+}
+
+#[eonix_macros::define_syscall(SYS_FCHMOD)]
+fn chmod(pathname: *const u8, mode: u32) -> KResult<()> {
+    sys_fchmodat(thread, FD::AT_FDCWD, pathname, mode, AtFlags::empty())
+}
+
+#[eonix_macros::define_syscall(SYS_UTIMENSAT)]
+fn utimensat(
+    dirfd: FD,
+    pathname: *const u8,
+    times: *const TimeSpec,
+    flags: AtFlags,
+) -> KResult<()> {
+    let dentry = if flags.at_empty_path() {
+        let file = thread.files.get(dirfd).ok_or(EBADF)?;
+        file.as_path().ok_or(EBADF)?.clone()
+    } else {
+        dentry_from(thread, dirfd, pathname, !flags.no_follow())?
+    };
+
+    if !dentry.is_valid() {
+        return Err(ENOENT);
+    }
+
+    let _times = if times.is_null() {
+        [TimeSpec::default(), TimeSpec::default()]
+    } else {
+        let times = UserPointer::new(times)?;
+        [times.read()?, times.offset(1)?.read()?]
+    };
+
+    // TODO: Implement utimensat
+    // dentry.utimens(&times)
+    Ok(())
+}
+
 pub fn keep_alive() {}

+ 19 - 34
src/kernel/syscall/procops.rs

@@ -170,29 +170,27 @@ fn execve(exec: *const u8, argv: *const PtrT, envp: *const PtrT) -> KResult<Sysc
 
     // TODO: When `execve` is called by one of the threads in a process, the other threads
     //       should be terminated and `execve` is performed in the thread group leader.
-    if let Ok(load_info) = ProgramLoader::parse(dentry.clone())?.load(argv, envp) {
-        if let Some(robust_list) = thread.get_robust_list() {
-            let _ = Task::block_on(robust_list.wake_all());
-            thread.set_robust_list(None);
-        }
+    let load_info = ProgramLoader::parse(dentry.clone())?.load(argv, envp)?;
 
-        unsafe {
-            // SAFETY: We are doing execve, all other threads are terminated.
-            thread.process.mm_list.replace(Some(load_info.mm_list));
-        }
-        thread.files.on_exec();
-        thread.signal_list.clear_non_ignore();
-        thread.set_name(dentry.name().clone());
-
-        let mut trap_ctx = thread.trap_ctx.borrow();
-        trap_ctx.set_program_counter(load_info.entry_ip.addr());
-        trap_ctx.set_stack_pointer(load_info.sp.addr());
-        Ok(SyscallNoReturn)
-    } else {
-        // We can't hold any ownership when we call `kill_current`.
-        // ProcessList::kill_current(Signal::SIGSEGV);
-        todo!()
+    if let Some(robust_list) = thread.get_robust_list() {
+        let _ = Task::block_on(robust_list.wake_all());
+        thread.set_robust_list(None);
+    }
+
+    unsafe {
+        // SAFETY: We are doing execve, all other threads are terminated.
+        thread.process.mm_list.replace(Some(load_info.mm_list));
     }
+
+    thread.files.on_exec();
+    thread.signal_list.clear_non_ignore();
+    thread.set_name(dentry.name().clone());
+
+    let mut trap_ctx = thread.trap_ctx.borrow();
+    trap_ctx.set_program_counter(load_info.entry_ip.addr());
+    trap_ctx.set_stack_pointer(load_info.sp.addr());
+
+    Ok(SyscallNoReturn)
 }
 
 #[eonix_macros::define_syscall(SYS_EXIT)]
@@ -689,19 +687,6 @@ fn getrusage(who: u32, rusage: *mut RUsage) -> KResult<()> {
     Ok(())
 }
 
-#[eonix_macros::define_syscall(SYS_FCHMOD)]
-fn chmod(pathname: *const u8, mode: u32) -> KResult<()> {
-    let path = UserString::new(pathname)?;
-    let path = Path::new(path.as_cstr().to_bytes())?;
-
-    let dentry = Dentry::open(&thread.fs_context, path, true)?;
-    if !dentry.is_valid() {
-        return Err(ENOENT);
-    }
-
-    dentry.chmod(mode)
-}
-
 #[cfg(target_arch = "x86_64")]
 #[eonix_macros::define_syscall(SYS_VFORK)]
 fn vfork() -> KResult<u32> {

+ 8 - 2
src/kernel/syscall/sysinfo.rs

@@ -40,9 +40,15 @@ fn newuname(buffer: *mut NewUTSName) -> KResult<()> {
     // Linux compatible
     copy_cstr_to_array(b"Linux", &mut uname.sysname);
     copy_cstr_to_array(b"(none)", &mut uname.nodename);
-    copy_cstr_to_array(b"1.0.0", &mut uname.release);
-    copy_cstr_to_array(b"1.0.0", &mut uname.version);
+    copy_cstr_to_array(b"5.17.1", &mut uname.release);
+    copy_cstr_to_array(b"eonix 1.1.4", &mut uname.version);
+
+    #[cfg(target_arch = "x86_64")]
     copy_cstr_to_array(b"x86", &mut uname.machine);
+
+    #[cfg(target_arch = "riscv64")]
+    copy_cstr_to_array(b"riscv64", &mut uname.machine);
+
     copy_cstr_to_array(b"(none)", &mut uname.domainname);
 
     buffer.write(uname)

+ 2 - 3
src/kernel/task/loader/elf.rs

@@ -377,9 +377,8 @@ impl<E: ElfArch> Elf<E> {
 
         if let Some(ldso_path) = ldso_path {
             let fs_context = FsContext::global();
-            let ldso_file =
-                Dentry::open(fs_context, Path::new(ldso_path.as_bytes()).unwrap(), true).unwrap();
-            let ldso_elf = Elf::<E>::parse(ldso_file).unwrap();
+            let ldso_file = Dentry::open(fs_context, Path::new(ldso_path.as_bytes())?, true)?;
+            let ldso_elf = Elf::<E>::parse(ldso_file)?;
 
             let base = VAddr::from(E::LDSO_BASE_ADDR);
 

+ 3 - 6
src/kernel/task/process_list.rs

@@ -135,14 +135,11 @@ impl ProcessList {
         }
 
         if let Some(clear_ctid) = thread.get_clear_ctid() {
-            UserPointerMut::new(clear_ctid as *mut u32)
+            let _ = UserPointerMut::new(clear_ctid as *mut u32)
                 .unwrap()
-                .write(0u32)
-                .expect("should clear child tid successfully");
+                .write(0u32);
 
-            futex_wake(clear_ctid, None, 1)
-                .await
-                .expect("should wake up child tid");
+            let _ = futex_wake(clear_ctid, None, 1).await;
         }
 
         if let Some(robust_list) = thread.get_robust_list() {

+ 16 - 20
src/kernel/user/dataflow.rs

@@ -142,11 +142,10 @@ impl CheckedUserPointer<'_> {
                 "3:",
                 "nop",
                 ".pushsection .fix, \"a\", @progbits",
-                ".align 16",
-                ".quad 2b",      // instruction address
-                ".quad 3b - 2b", // instruction length
-                ".quad 3b",      // fix jump address
-                ".quad 0x3",     // type: load
+                ".8byte 2b",      // instruction address
+                ".8byte 3b - 2b", // instruction length
+                ".8byte 3b",      // fix jump address
+                ".8byte 0x3",     // type: load
                 ".popsection",
                 inout("a0") total => error_bytes,
                 inout("a1") self.ptr => _,
@@ -203,11 +202,10 @@ impl CheckedUserPointer<'_> {
                 "3:",
                 "nop",
                 ".pushsection .fix, \"a\", @progbits",
-                ".align 16",
-                ".quad 2b",  // instruction address
-                ".quad 3b - 2b",  // instruction length
-                ".quad 3b",  // fix jump address
-                ".quad 0x1", // type: store
+                ".8byte 2b",  // instruction address
+                ".8byte 3b - 2b",  // instruction length
+                ".8byte 3b",  // fix jump address
+                ".8byte 0x1", // type: store
                 ".popsection",
                 inout("a0") total => error_bytes,
                 inout("a1") data => _,
@@ -263,11 +261,10 @@ impl CheckedUserPointer<'_> {
                 "3:",
                 "nop",
                 ".pushsection .fix, \"a\", @progbits",
-                ".align 16",
-                ".quad 2b",  // instruction address
-                ".quad 3b - 2b",  // instruction length
-                ".quad 3b",  // fix jump address
-                ".quad 0x1", // type: store
+                ".8byte 2b",  // instruction address
+                ".8byte 3b - 2b",  // instruction length
+                ".8byte 3b",  // fix jump address
+                ".8byte 0x1", // type: store
                 ".popsection",
                 inout("a0") self.len => error_bytes,
                 inout("a1") self.ptr => _,
@@ -370,11 +367,10 @@ impl<'lt> UserString<'lt> {
                 "3:",
                 "nop",
                 ".pushsection .fix, \"a\", @progbits",
-                ".align 16",
-                ".quad 2b",  // instruction address
-                ".quad 4b - 2b",  // instruction length
-                ".quad 3b",  // fix jump address
-                ".quad 0x2", // type: string
+                ".8byte 2b",  // instruction address
+                ".8byte 4b - 2b",  // instruction length
+                ".8byte 3b",  // fix jump address
+                ".8byte 0x2", // type: string
                 ".popsection",
                 out("t0") _,
                 inout("a0") MAX_LEN => result,

+ 4 - 0
src/kernel/vfs/dentry.rs

@@ -453,4 +453,8 @@ impl Dentry {
     pub fn chmod(&self, mode: Mode) -> KResult<()> {
         self.get_inode()?.chmod(mode)
     }
+
+    pub fn chown(&self, uid: u32, gid: u32) -> KResult<()> {
+        self.get_inode()?.chown(uid, gid)
+    }
 }

+ 1 - 1
src/kernel/vfs/file.rs

@@ -516,7 +516,7 @@ impl File {
 
     pub fn as_path(&self) -> Option<&Arc<Dentry>> {
         match self {
-            File::Inode(inode_file) if s_isdir(inode_file.mode) => Some(&inode_file.dentry),
+            File::Inode(inode_file) => Some(&inode_file.dentry),
             _ => None,
         }
     }

+ 5 - 3
src/kernel/vfs/filearray.rs

@@ -79,9 +79,11 @@ impl FileArray {
     }
 
     pub fn close_all(&self) {
-        let mut inner = self.inner.lock();
-        inner.fd_min_avail = FD(0);
-        inner.files.clear();
+        let _old_files = {
+            let mut inner = self.inner.lock();
+            inner.fd_min_avail = FD(0);
+            core::mem::take(&mut inner.files)
+        };
     }
 
     pub fn close(&self, fd: FD) -> KResult<()> {

+ 4 - 0
src/kernel/vfs/inode.rs

@@ -144,6 +144,10 @@ pub trait Inode: Send + Sync + InodeInner {
         Err(EPERM)
     }
 
+    fn chown(&self, uid: u32, gid: u32) -> KResult<()> {
+        Err(EPERM)
+    }
+
     fn statx(&self, stat: &mut StatX, mask: u32) -> KResult<()> {
         // Safety: ffi should have checked reference
         let vfs = self.vfs.upgrade().expect("Vfs is dropped");