Add support for chmod, fchmod, fchmodat

This commit is contained in:
LI Qing
2023-07-03 16:14:40 +08:00
committed by Tate, Hongliang Tian
parent 743344e3fc
commit 3600a3a439
14 changed files with 160 additions and 26 deletions

View File

@ -4,7 +4,7 @@ use log::Level;
pub const USER_STACK_SIZE: usize = PAGE_SIZE * 4;
pub const KERNEL_STACK_SIZE: usize = PAGE_SIZE * 64;
pub const KERNEL_HEAP_SIZE: usize = 0x4_000_000;
pub const KERNEL_HEAP_SIZE: usize = 0x5_000_000;
pub const KERNEL_OFFSET: usize = 0xffffffff80000000;

View File

@ -1,4 +1,4 @@
TESTS ?= open_test read_test statfs_test
TESTS ?= open_test read_test statfs_test chmod_test
MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
CUR_DIR := $(patsubst %/,%,$(dir $(MKFILE_PATH)))

View File

@ -0,0 +1,3 @@
ChmodTest.FchmodDirSucceeds_NoRandomSave
ChmodTest.FchmodatDirAbsolutePath
ChmodTest.FchmodatDir

View File

@ -109,7 +109,7 @@ impl FsResolver {
return_errno_with_message!(Errno::EISDIR, "path refers to a directory");
}
if !dir_dentry.vnode().inode_mode().is_writable() {
return_errno_with_message!(Errno::EPERM, "file cannot be created");
return_errno_with_message!(Errno::EACCES, "file cannot be created");
}
let new_dentry = dir_dentry.create(&file_name, InodeType::File, inode_mode)?;
new_dentry

View File

@ -55,26 +55,34 @@ impl<D: DirOps> ProcDir<D> {
impl<D: DirOps + 'static> Inode for ProcDir<D> {
fn len(&self) -> usize {
self.info.metadata().size
self.info.size()
}
fn resize(&self, _new_size: usize) {}
fn metadata(&self) -> Metadata {
self.info.metadata().clone()
self.info.metadata()
}
fn atime(&self) -> Duration {
self.info.metadata().atime
self.info.atime()
}
fn set_atime(&self, _time: Duration) {}
fn set_atime(&self, time: Duration) {
self.info.set_atime(time)
}
fn mtime(&self) -> Duration {
self.info.metadata().mtime
self.info.mtime()
}
fn set_mtime(&self, _time: Duration) {}
fn set_mtime(&self, time: Duration) {
self.info.set_mtime(time)
}
fn set_mode(&self, mode: InodeMode) {
self.info.set_mode(mode)
}
fn create(&self, _name: &str, _type_: InodeType, _mode: InodeMode) -> Result<Arc<dyn Inode>> {
Err(Error::new(Errno::EPERM))

View File

@ -28,26 +28,34 @@ impl<F: FileOps> ProcFile<F> {
impl<F: FileOps + 'static> Inode for ProcFile<F> {
fn len(&self) -> usize {
self.info.metadata().size
self.info.size()
}
fn resize(&self, _new_size: usize) {}
fn metadata(&self) -> Metadata {
self.info.metadata().clone()
self.info.metadata()
}
fn atime(&self) -> Duration {
self.info.metadata().atime
self.info.atime()
}
fn set_atime(&self, _time: Duration) {}
fn set_atime(&self, time: Duration) {
self.info.set_atime(time)
}
fn mtime(&self) -> Duration {
self.info.metadata().mtime
self.info.mtime()
}
fn set_mtime(&self, _time: Duration) {}
fn set_mtime(&self, time: Duration) {
self.info.set_mtime(time)
}
fn set_mode(&self, mode: InodeMode) {
self.info.set_mode(mode)
}
fn read_page(&self, _idx: usize, _frame: &VmFrame) -> Result<()> {
unreachable!()

View File

@ -1,4 +1,6 @@
use crate::fs::utils::{FileSystem, Metadata};
use core::time::Duration;
use crate::fs::utils::{FileSystem, InodeMode, Metadata};
use crate::prelude::*;
use super::ProcFS;
@ -14,7 +16,7 @@ mod file;
mod sym;
struct ProcInodeInfo {
metadata: Metadata,
metadata: RwLock<Metadata>,
fs: Weak<dyn FileSystem>,
is_volatile: bool,
}
@ -22,7 +24,7 @@ struct ProcInodeInfo {
impl ProcInodeInfo {
pub fn new(metadata: Metadata, fs: Weak<dyn FileSystem>, is_volatile: bool) -> Self {
Self {
metadata,
metadata: RwLock::new(metadata),
fs,
is_volatile,
}
@ -32,8 +34,32 @@ impl ProcInodeInfo {
&self.fs
}
pub fn metadata(&self) -> &Metadata {
&self.metadata
pub fn metadata(&self) -> Metadata {
self.metadata.read().clone()
}
pub fn size(&self) -> usize {
self.metadata.read().size
}
pub fn atime(&self) -> Duration {
self.metadata.read().atime
}
pub fn set_atime(&self, time: Duration) {
self.metadata.write().atime = time;
}
pub fn mtime(&self) -> Duration {
self.metadata.read().mtime
}
pub fn set_mtime(&self, time: Duration) {
self.metadata.write().mtime = time;
}
pub fn set_mode(&self, mode: InodeMode) {
self.metadata.write().mode = mode;
}
pub fn is_volatile(&self) -> bool {

View File

@ -28,26 +28,34 @@ impl<S: SymOps> ProcSym<S> {
impl<S: SymOps + 'static> Inode for ProcSym<S> {
fn len(&self) -> usize {
self.info.metadata().size
self.info.size()
}
fn resize(&self, _new_size: usize) {}
fn metadata(&self) -> Metadata {
self.info.metadata().clone()
self.info.metadata()
}
fn atime(&self) -> Duration {
self.info.metadata().atime
self.info.atime()
}
fn set_atime(&self, _time: Duration) {}
fn set_atime(&self, time: Duration) {
self.info.set_atime(time)
}
fn mtime(&self) -> Duration {
self.info.metadata().mtime
self.info.mtime()
}
fn set_mtime(&self, _time: Duration) {}
fn set_mtime(&self, time: Duration) {
self.info.set_mtime(time)
}
fn set_mode(&self, mode: InodeMode) {
self.info.set_mode(mode)
}
fn read_page(&self, _idx: usize, _frame: &VmFrame) -> Result<()> {
Err(Error::new(Errno::EPERM))

View File

@ -394,6 +394,10 @@ impl Inode for RamInode {
self.0.write().metadata.mtime = time;
}
fn set_mode(&self, mode: InodeMode) {
self.0.write().metadata.mode = mode;
}
fn mknod(
&self,
name: &str,

View File

@ -110,6 +110,9 @@ impl Dentry {
if self.vnode.inode_type() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
if !self.vnode.inode_mode().is_executable() {
return_errno!(Errno::EACCES);
}
if name.len() > NAME_MAX {
return_errno!(Errno::ENAMETOOLONG);
}
@ -253,6 +256,11 @@ impl Dentry {
self.vnode.inode_mode()
}
/// Set the inode permission mode
pub fn set_inode_mode(&self, mode: InodeMode) {
self.vnode.set_inode_mode(mode)
}
/// Get the inode length
pub fn inode_len(&self) -> usize {
self.vnode.len()

View File

@ -223,6 +223,8 @@ pub trait Inode: Any + Sync + Send {
fn set_mtime(&self, time: Duration);
fn set_mode(&self, mode: InodeMode);
fn read_page(&self, idx: usize, frame: &VmFrame) -> Result<()> {
Err(Error::new(Errno::EISDIR))
}

View File

@ -218,6 +218,10 @@ impl Vnode {
self.inner.read().inode.metadata().mode
}
pub fn set_inode_mode(&self, mode: InodeMode) {
self.inner.read().inode.set_mode(mode)
}
pub fn len(&self) -> usize {
self.inner.read().inode.len()
}

View File

@ -0,0 +1,55 @@
use crate::fs::{
file_table::FileDescripter,
fs_resolver::{FsPath, AT_FDCWD},
inode_handle::InodeHandle,
utils::{InodeMode, PATH_MAX},
};
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::util::read_cstring_from_user;
use super::SyscallReturn;
use super::{SYS_FCHMOD, SYS_FCHMODAT};
pub fn sys_fchmod(fd: FileDescripter, mode: u16) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_FCHMOD);
debug!("fd = {}, mode = 0o{:o}", fd, mode);
let current = current!();
let file_table = current.file_table().lock();
let file = file_table.get_file(fd)?;
let inode_handle = file
.downcast_ref::<InodeHandle>()
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
let dentry = inode_handle.dentry();
dentry.set_inode_mode(InodeMode::from_bits_truncate(mode));
Ok(SyscallReturn::Return(0))
}
pub fn sys_chmod(path_ptr: Vaddr, mode: u16) -> Result<SyscallReturn> {
self::sys_fchmodat(AT_FDCWD, path_ptr, mode)
}
// Glibc handles the `flags` argument, so we just ignore it.
pub fn sys_fchmodat(
dirfd: FileDescripter,
path_ptr: Vaddr,
mode: u16,
/* flags: u32, */
) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_FCHMODAT);
let path = read_cstring_from_user(path_ptr, PATH_MAX)?;
debug!("dirfd = {}, path = {:?}, mode = 0o{:o}", dirfd, path, mode,);
let current = current!();
let dentry = {
let path = path.to_string_lossy();
if path.is_empty() {
return_errno_with_message!(Errno::ENOENT, "path is empty");
}
let fs_path = FsPath::new(dirfd, path.as_ref())?;
current.fs().read().lookup(&fs_path)?
};
dentry.set_inode_mode(InodeMode::from_bits_truncate(mode));
Ok(SyscallReturn::Return(0))
}

View File

@ -5,6 +5,7 @@ use crate::syscall::access::sys_access;
use crate::syscall::arch_prctl::sys_arch_prctl;
use crate::syscall::brk::sys_brk;
use crate::syscall::chdir::{sys_chdir, sys_fchdir};
use crate::syscall::chmod::{sys_chmod, sys_fchmod, sys_fchmodat};
use crate::syscall::clock_gettime::sys_clock_gettime;
use crate::syscall::clock_nanosleep::sys_clock_nanosleep;
use crate::syscall::clone::sys_clone;
@ -89,6 +90,7 @@ mod arch_prctl;
mod bind;
mod brk;
mod chdir;
mod chmod;
mod clock_gettime;
mod clock_nanosleep;
mod clone;
@ -252,6 +254,8 @@ define_syscall_nums!(
SYS_UNLINK = 87,
SYS_SYMLINK = 88,
SYS_READLINK = 89,
SYS_CHMOD = 90,
SYS_FCHMOD = 91,
SYS_UMASK = 95,
SYS_GETTIMEOFDAY = 96,
SYS_GETUID = 102,
@ -286,6 +290,7 @@ define_syscall_nums!(
SYS_LINKAT = 265,
SYS_SYMLINKAT = 266,
SYS_READLINKAT = 267,
SYS_FCHMODAT = 268,
SYS_SET_ROBUST_LIST = 273,
SYS_UTIMENSAT = 280,
SYS_EPOLL_CREATE1 = 291,
@ -406,6 +411,8 @@ pub fn syscall_dispatch(
SYS_UNLINK => syscall_handler!(1, sys_unlink, args),
SYS_SYMLINK => syscall_handler!(2, sys_symlink, args),
SYS_READLINK => syscall_handler!(3, sys_readlink, args),
SYS_CHMOD => syscall_handler!(2, sys_chmod, args),
SYS_FCHMOD => syscall_handler!(2, sys_fchmod, args),
SYS_UMASK => syscall_handler!(1, sys_umask, args),
SYS_GETTIMEOFDAY => syscall_handler!(1, sys_gettimeofday, args),
SYS_GETUID => syscall_handler!(0, sys_getuid),
@ -440,6 +447,7 @@ pub fn syscall_dispatch(
SYS_LINKAT => syscall_handler!(5, sys_linkat, args),
SYS_SYMLINKAT => syscall_handler!(3, sys_symlinkat, args),
SYS_READLINKAT => syscall_handler!(4, sys_readlinkat, args),
SYS_FCHMODAT => syscall_handler!(3, sys_fchmodat, args),
SYS_SET_ROBUST_LIST => syscall_handler!(2, sys_set_robust_list, args),
SYS_UTIMENSAT => syscall_handler!(4, sys_utimensat, args),
SYS_EPOLL_CREATE1 => syscall_handler!(1, sys_epoll_create1, args),