diff --git a/etc/syscalls_linux_aarch64.md b/etc/syscalls_linux_aarch64.md index 82371995..3e1285af 100644 --- a/etc/syscalls_linux_aarch64.md +++ b/etc/syscalls_linux_aarch64.md @@ -41,7 +41,7 @@ | 0x25 (37) | linkat | (int olddfd, const char *oldname, int newdfd, const char *newname, int flags) | __arm64_sys_linkat | true | | 0x26 (38) | renameat | (int olddfd, const char *oldname, int newdfd, const char *newname) | __arm64_sys_renameat | true | | 0x27 (39) | umount | (char *name, int flags) | __arm64_sys_umount | false | -| 0x28 (40) | mount | (char *dev_name, char *dir_name, char *type, unsigned long flags, void *data) | __arm64_sys_mount | false | +| 0x28 (40) | mount | (char *dev_name, char *dir_name, char *type, unsigned long flags, void *data) | __arm64_sys_mount | partial | | 0x29 (41) | pivot_root | (const char *new_root, const char *put_old) | __arm64_sys_pivot_root | false | | 0x2b (43) | statfs | (const char *pathname, struct statfs *buf) | __arm64_sys_statfs | partial | | 0x2c (44) | fstatfs | (unsigned int fd, struct statfs *buf) | __arm64_sys_fstatfs | partial | diff --git a/src/arch/arm64/exceptions/syscall.rs b/src/arch/arm64/exceptions/syscall.rs index ae84d00b..d59b5f0a 100644 --- a/src/arch/arm64/exceptions/syscall.rs +++ b/src/arch/arm64/exceptions/syscall.rs @@ -34,6 +34,7 @@ use crate::{ ioctl::sys_ioctl, iov::{sys_preadv, sys_preadv2, sys_pwritev, sys_pwritev2, sys_readv, sys_writev}, listxattr::{sys_flistxattr, sys_listxattr, sys_llistxattr}, + mount::sys_mount, removexattr::{sys_fremovexattr, sys_lremovexattr, sys_removexattr}, rw::{sys_pread64, sys_pwrite64, sys_read, sys_write}, seek::sys_lseek, @@ -231,6 +232,16 @@ pub async fn handle_syscall() { ) .await } + 0x28 => { + sys_mount( + TUA::from_value(arg1 as _), + TUA::from_value(arg2 as _), + TUA::from_value(arg3 as _), + arg4 as _, + TUA::from_value(arg5 as _), + ) + .await + } 0x2b => sys_statfs(TUA::from_value(arg1 as _), TUA::from_value(arg2 as _)).await, 0x2c => sys_fstatfs(arg1.into(), TUA::from_value(arg2 as _)).await, 0x2d => sys_truncate(TUA::from_value(arg1 as _), arg2 as _).await, diff --git a/src/fs/mod.rs b/src/fs/mod.rs index 9dc7918c..750c22c5 100644 --- a/src/fs/mod.rs +++ b/src/fs/mod.rs @@ -79,6 +79,13 @@ impl VfsState { self.mounts.insert(mount_point_id, mount); } + /// Removes a mount point by its inode ID. + fn remove_mount(&mut self, mount_point_id: &InodeId) -> Option<()> { + let mount = self.mounts.remove(mount_point_id)?; + self.filesystems.remove(&mount.fs.id())?; + Some(()) + } + /// Checks if an inode is a mount point and returns the root inode of the /// mounted filesystem if it is. fn get_mount_root(&self, inode_id: &InodeId) -> Option> { @@ -177,6 +184,19 @@ impl VFS { Ok(()) } + #[expect(unused)] + pub async fn unmount(&self, mount_point: Arc) -> Result<()> { + let mount_point_id = mount_point.id(); + + // Lock the state and remove the mount. + self.state + .lock_save_irq() + .remove_mount(&mount_point_id) + .ok_or(FsError::NotFound)?; + + Ok(()) + } + pub async fn get_fs(&self, inode: Arc) -> Result> { self.state .lock_save_irq() diff --git a/src/fs/syscalls/mod.rs b/src/fs/syscalls/mod.rs index 1cd8a2d5..1cc4c3c9 100644 --- a/src/fs/syscalls/mod.rs +++ b/src/fs/syscalls/mod.rs @@ -8,6 +8,7 @@ pub mod getxattr; pub mod ioctl; pub mod iov; pub mod listxattr; +pub mod mount; pub mod open; pub mod removexattr; pub mod rw; diff --git a/src/fs/syscalls/mount.rs b/src/fs/syscalls/mount.rs new file mode 100644 index 00000000..981a25e5 --- /dev/null +++ b/src/fs/syscalls/mount.rs @@ -0,0 +1,99 @@ +use crate::fs::VFS; +use crate::memory::uaccess::cstr::UserCStr; +use crate::sched::current::current_task_shared; +use bitflags::bitflags; +use core::ffi::c_char; +use libkernel::error::{KernelError, Result}; +use libkernel::fs::path::Path; +use libkernel::memory::address::{TUA, UA}; + +bitflags! { + #[derive(Debug)] + pub struct MountFlags: u64 { + const MS_RDONLY = 1; + const MS_NOSUID = 2; + const MS_NODEV = 4; + const MS_NOEXEC = 8; + const MS_SYNCHRONOUS = 16; + const MS_REMOUNT = 32; + const MS_MANDLOCK = 64; + const MS_DIRSYNC = 128; + const NOSYMFOLLOW = 256; + const MS_NOATIME = 1024; + const MS_NODIRATIME = 2048; + const MS_BIND = 4096; + const MS_MOVE = 8192; + const MS_REC = 16384; + const MS_VERBOSE = 32768; + const MS_SILENT = 65536; + const MS_POSIXACL = 1 << 16; + const MS_UNBINDABLE = 1 << 17; + const MS_PRIVATE = 1 << 18; + const MS_SLAVE = 1 << 19; + const MS_SHARED = 1 << 20; + const MS_RELATIME = 1 << 21; + const MS_KERNMOUNT = 1 << 22; + const MS_I_VERSION = 1 << 23; + const MS_STRICTATIME = 1 << 24; + const MS_LAZYTIME = 1 << 25; + const MS_SUBMOUNT = 1 << 26; + const MS_NOREMOTELOCK = 1 << 27; + const MS_NOSEC = 1 << 28; + const MS_BORN = 1 << 29; + const MS_ACTIVE = 1 << 30; + const MS_NOUSER = 1 << 31; + } +} + +pub async fn sys_mount( + dev_name: TUA, + dir_name: TUA, + type_: TUA, + flags: i64, + _data: UA, +) -> Result { + let flags = MountFlags::from_bits_truncate(flags as u64); + if flags.contains(MountFlags::MS_REC) { + // TODO: Handle later + return Ok(0); + } + let mut buf = [0u8; 1024]; + let dev_name = if dev_name.is_null() { + None + } else { + Some( + UserCStr::from_ptr(dev_name) + .copy_from_user(&mut buf) + .await?, + ) + }; + let mut buf = [0u8; 1024]; + let dir_name = UserCStr::from_ptr(dir_name) + .copy_from_user(&mut buf) + .await?; + let mount_point = VFS + .resolve_path( + Path::new(dir_name), + VFS.root_inode(), + ¤t_task_shared(), + ) + .await?; + let mut buf = [0u8; 1024]; + let _type = if type_.is_null() { + None + } else { + Some(UserCStr::from_ptr(type_).copy_from_user(&mut buf).await?) + }; + if let Some(dev_name) = dev_name { + let dev_name = match dev_name { + "proc" => "procfs", + "devtmpfs" => "devfs", + "cgroup2" => "cgroupfs", + s => s, + }; + VFS.mount(mount_point, dev_name, None).await?; + Ok(0) + } else { + Err(KernelError::NotSupported) + } +}