mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-23 01:13:23 +00:00
Add support for chmod, fchmod, fchmodat
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
743344e3fc
commit
3600a3a439
@ -4,7 +4,7 @@ use log::Level;
|
|||||||
|
|
||||||
pub const USER_STACK_SIZE: usize = PAGE_SIZE * 4;
|
pub const USER_STACK_SIZE: usize = PAGE_SIZE * 4;
|
||||||
pub const KERNEL_STACK_SIZE: usize = PAGE_SIZE * 64;
|
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;
|
pub const KERNEL_OFFSET: usize = 0xffffffff80000000;
|
||||||
|
|
||||||
|
@ -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)))
|
MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||||
CUR_DIR := $(patsubst %/,%,$(dir $(MKFILE_PATH)))
|
CUR_DIR := $(patsubst %/,%,$(dir $(MKFILE_PATH)))
|
||||||
|
3
regression/syscall_test/blocklists/chmod_test
Normal file
3
regression/syscall_test/blocklists/chmod_test
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
ChmodTest.FchmodDirSucceeds_NoRandomSave
|
||||||
|
ChmodTest.FchmodatDirAbsolutePath
|
||||||
|
ChmodTest.FchmodatDir
|
@ -109,7 +109,7 @@ impl FsResolver {
|
|||||||
return_errno_with_message!(Errno::EISDIR, "path refers to a directory");
|
return_errno_with_message!(Errno::EISDIR, "path refers to a directory");
|
||||||
}
|
}
|
||||||
if !dir_dentry.vnode().inode_mode().is_writable() {
|
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)?;
|
let new_dentry = dir_dentry.create(&file_name, InodeType::File, inode_mode)?;
|
||||||
new_dentry
|
new_dentry
|
||||||
|
@ -55,26 +55,34 @@ impl<D: DirOps> ProcDir<D> {
|
|||||||
|
|
||||||
impl<D: DirOps + 'static> Inode for ProcDir<D> {
|
impl<D: DirOps + 'static> Inode for ProcDir<D> {
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
self.info.metadata().size
|
self.info.size()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&self, _new_size: usize) {}
|
fn resize(&self, _new_size: usize) {}
|
||||||
|
|
||||||
fn metadata(&self) -> Metadata {
|
fn metadata(&self) -> Metadata {
|
||||||
self.info.metadata().clone()
|
self.info.metadata()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn atime(&self) -> Duration {
|
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 {
|
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>> {
|
fn create(&self, _name: &str, _type_: InodeType, _mode: InodeMode) -> Result<Arc<dyn Inode>> {
|
||||||
Err(Error::new(Errno::EPERM))
|
Err(Error::new(Errno::EPERM))
|
||||||
|
@ -28,26 +28,34 @@ impl<F: FileOps> ProcFile<F> {
|
|||||||
|
|
||||||
impl<F: FileOps + 'static> Inode for ProcFile<F> {
|
impl<F: FileOps + 'static> Inode for ProcFile<F> {
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
self.info.metadata().size
|
self.info.size()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&self, _new_size: usize) {}
|
fn resize(&self, _new_size: usize) {}
|
||||||
|
|
||||||
fn metadata(&self) -> Metadata {
|
fn metadata(&self) -> Metadata {
|
||||||
self.info.metadata().clone()
|
self.info.metadata()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn atime(&self) -> Duration {
|
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 {
|
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<()> {
|
fn read_page(&self, _idx: usize, _frame: &VmFrame) -> Result<()> {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
@ -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 crate::prelude::*;
|
||||||
|
|
||||||
use super::ProcFS;
|
use super::ProcFS;
|
||||||
@ -14,7 +16,7 @@ mod file;
|
|||||||
mod sym;
|
mod sym;
|
||||||
|
|
||||||
struct ProcInodeInfo {
|
struct ProcInodeInfo {
|
||||||
metadata: Metadata,
|
metadata: RwLock<Metadata>,
|
||||||
fs: Weak<dyn FileSystem>,
|
fs: Weak<dyn FileSystem>,
|
||||||
is_volatile: bool,
|
is_volatile: bool,
|
||||||
}
|
}
|
||||||
@ -22,7 +24,7 @@ struct ProcInodeInfo {
|
|||||||
impl ProcInodeInfo {
|
impl ProcInodeInfo {
|
||||||
pub fn new(metadata: Metadata, fs: Weak<dyn FileSystem>, is_volatile: bool) -> Self {
|
pub fn new(metadata: Metadata, fs: Weak<dyn FileSystem>, is_volatile: bool) -> Self {
|
||||||
Self {
|
Self {
|
||||||
metadata,
|
metadata: RwLock::new(metadata),
|
||||||
fs,
|
fs,
|
||||||
is_volatile,
|
is_volatile,
|
||||||
}
|
}
|
||||||
@ -32,8 +34,32 @@ impl ProcInodeInfo {
|
|||||||
&self.fs
|
&self.fs
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn metadata(&self) -> &Metadata {
|
pub fn metadata(&self) -> 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 {
|
pub fn is_volatile(&self) -> bool {
|
||||||
|
@ -28,26 +28,34 @@ impl<S: SymOps> ProcSym<S> {
|
|||||||
|
|
||||||
impl<S: SymOps + 'static> Inode for ProcSym<S> {
|
impl<S: SymOps + 'static> Inode for ProcSym<S> {
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
self.info.metadata().size
|
self.info.size()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&self, _new_size: usize) {}
|
fn resize(&self, _new_size: usize) {}
|
||||||
|
|
||||||
fn metadata(&self) -> Metadata {
|
fn metadata(&self) -> Metadata {
|
||||||
self.info.metadata().clone()
|
self.info.metadata()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn atime(&self) -> Duration {
|
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 {
|
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<()> {
|
fn read_page(&self, _idx: usize, _frame: &VmFrame) -> Result<()> {
|
||||||
Err(Error::new(Errno::EPERM))
|
Err(Error::new(Errno::EPERM))
|
||||||
|
@ -394,6 +394,10 @@ impl Inode for RamInode {
|
|||||||
self.0.write().metadata.mtime = time;
|
self.0.write().metadata.mtime = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_mode(&self, mode: InodeMode) {
|
||||||
|
self.0.write().metadata.mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
fn mknod(
|
fn mknod(
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
|
@ -110,6 +110,9 @@ impl Dentry {
|
|||||||
if self.vnode.inode_type() != InodeType::Dir {
|
if self.vnode.inode_type() != InodeType::Dir {
|
||||||
return_errno!(Errno::ENOTDIR);
|
return_errno!(Errno::ENOTDIR);
|
||||||
}
|
}
|
||||||
|
if !self.vnode.inode_mode().is_executable() {
|
||||||
|
return_errno!(Errno::EACCES);
|
||||||
|
}
|
||||||
if name.len() > NAME_MAX {
|
if name.len() > NAME_MAX {
|
||||||
return_errno!(Errno::ENAMETOOLONG);
|
return_errno!(Errno::ENAMETOOLONG);
|
||||||
}
|
}
|
||||||
@ -253,6 +256,11 @@ impl Dentry {
|
|||||||
self.vnode.inode_mode()
|
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
|
/// Get the inode length
|
||||||
pub fn inode_len(&self) -> usize {
|
pub fn inode_len(&self) -> usize {
|
||||||
self.vnode.len()
|
self.vnode.len()
|
||||||
|
@ -223,6 +223,8 @@ pub trait Inode: Any + Sync + Send {
|
|||||||
|
|
||||||
fn set_mtime(&self, time: Duration);
|
fn set_mtime(&self, time: Duration);
|
||||||
|
|
||||||
|
fn set_mode(&self, mode: InodeMode);
|
||||||
|
|
||||||
fn read_page(&self, idx: usize, frame: &VmFrame) -> Result<()> {
|
fn read_page(&self, idx: usize, frame: &VmFrame) -> Result<()> {
|
||||||
Err(Error::new(Errno::EISDIR))
|
Err(Error::new(Errno::EISDIR))
|
||||||
}
|
}
|
||||||
|
@ -218,6 +218,10 @@ impl Vnode {
|
|||||||
self.inner.read().inode.metadata().mode
|
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 {
|
pub fn len(&self) -> usize {
|
||||||
self.inner.read().inode.len()
|
self.inner.read().inode.len()
|
||||||
}
|
}
|
||||||
|
55
services/libs/jinux-std/src/syscall/chmod.rs
Normal file
55
services/libs/jinux-std/src/syscall/chmod.rs
Normal 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))
|
||||||
|
}
|
@ -5,6 +5,7 @@ use crate::syscall::access::sys_access;
|
|||||||
use crate::syscall::arch_prctl::sys_arch_prctl;
|
use crate::syscall::arch_prctl::sys_arch_prctl;
|
||||||
use crate::syscall::brk::sys_brk;
|
use crate::syscall::brk::sys_brk;
|
||||||
use crate::syscall::chdir::{sys_chdir, sys_fchdir};
|
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_gettime::sys_clock_gettime;
|
||||||
use crate::syscall::clock_nanosleep::sys_clock_nanosleep;
|
use crate::syscall::clock_nanosleep::sys_clock_nanosleep;
|
||||||
use crate::syscall::clone::sys_clone;
|
use crate::syscall::clone::sys_clone;
|
||||||
@ -89,6 +90,7 @@ mod arch_prctl;
|
|||||||
mod bind;
|
mod bind;
|
||||||
mod brk;
|
mod brk;
|
||||||
mod chdir;
|
mod chdir;
|
||||||
|
mod chmod;
|
||||||
mod clock_gettime;
|
mod clock_gettime;
|
||||||
mod clock_nanosleep;
|
mod clock_nanosleep;
|
||||||
mod clone;
|
mod clone;
|
||||||
@ -252,6 +254,8 @@ define_syscall_nums!(
|
|||||||
SYS_UNLINK = 87,
|
SYS_UNLINK = 87,
|
||||||
SYS_SYMLINK = 88,
|
SYS_SYMLINK = 88,
|
||||||
SYS_READLINK = 89,
|
SYS_READLINK = 89,
|
||||||
|
SYS_CHMOD = 90,
|
||||||
|
SYS_FCHMOD = 91,
|
||||||
SYS_UMASK = 95,
|
SYS_UMASK = 95,
|
||||||
SYS_GETTIMEOFDAY = 96,
|
SYS_GETTIMEOFDAY = 96,
|
||||||
SYS_GETUID = 102,
|
SYS_GETUID = 102,
|
||||||
@ -286,6 +290,7 @@ define_syscall_nums!(
|
|||||||
SYS_LINKAT = 265,
|
SYS_LINKAT = 265,
|
||||||
SYS_SYMLINKAT = 266,
|
SYS_SYMLINKAT = 266,
|
||||||
SYS_READLINKAT = 267,
|
SYS_READLINKAT = 267,
|
||||||
|
SYS_FCHMODAT = 268,
|
||||||
SYS_SET_ROBUST_LIST = 273,
|
SYS_SET_ROBUST_LIST = 273,
|
||||||
SYS_UTIMENSAT = 280,
|
SYS_UTIMENSAT = 280,
|
||||||
SYS_EPOLL_CREATE1 = 291,
|
SYS_EPOLL_CREATE1 = 291,
|
||||||
@ -406,6 +411,8 @@ pub fn syscall_dispatch(
|
|||||||
SYS_UNLINK => syscall_handler!(1, sys_unlink, args),
|
SYS_UNLINK => syscall_handler!(1, sys_unlink, args),
|
||||||
SYS_SYMLINK => syscall_handler!(2, sys_symlink, args),
|
SYS_SYMLINK => syscall_handler!(2, sys_symlink, args),
|
||||||
SYS_READLINK => syscall_handler!(3, sys_readlink, 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_UMASK => syscall_handler!(1, sys_umask, args),
|
||||||
SYS_GETTIMEOFDAY => syscall_handler!(1, sys_gettimeofday, args),
|
SYS_GETTIMEOFDAY => syscall_handler!(1, sys_gettimeofday, args),
|
||||||
SYS_GETUID => syscall_handler!(0, sys_getuid),
|
SYS_GETUID => syscall_handler!(0, sys_getuid),
|
||||||
@ -440,6 +447,7 @@ pub fn syscall_dispatch(
|
|||||||
SYS_LINKAT => syscall_handler!(5, sys_linkat, args),
|
SYS_LINKAT => syscall_handler!(5, sys_linkat, args),
|
||||||
SYS_SYMLINKAT => syscall_handler!(3, sys_symlinkat, args),
|
SYS_SYMLINKAT => syscall_handler!(3, sys_symlinkat, args),
|
||||||
SYS_READLINKAT => syscall_handler!(4, sys_readlinkat, 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_SET_ROBUST_LIST => syscall_handler!(2, sys_set_robust_list, args),
|
||||||
SYS_UTIMENSAT => syscall_handler!(4, sys_utimensat, args),
|
SYS_UTIMENSAT => syscall_handler!(4, sys_utimensat, args),
|
||||||
SYS_EPOLL_CREATE1 => syscall_handler!(1, sys_epoll_create1, args),
|
SYS_EPOLL_CREATE1 => syscall_handler!(1, sys_epoll_create1, args),
|
||||||
|
Reference in New Issue
Block a user