Add chmod and chown system calls
This commit is contained in:
parent
e1648fc870
commit
978edf8a17
2
deps/sefs
vendored
2
deps/sefs
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 69f265cdaacd063f87033627c7ef297ae78bd29f
|
Subproject commit 12ddbb4f6356a1496cf818b4f043bbe9931b8c96
|
@ -52,7 +52,7 @@ impl File for DevRandom {
|
|||||||
mtime: Timespec { sec: 0, nsec: 0 },
|
mtime: Timespec { sec: 0, nsec: 0 },
|
||||||
ctime: Timespec { sec: 0, nsec: 0 },
|
ctime: Timespec { sec: 0, nsec: 0 },
|
||||||
type_: FileType::CharDevice,
|
type_: FileType::CharDevice,
|
||||||
mode: 0444,
|
mode: (FileMode::S_IRUSR | FileMode::S_IRGRP | FileMode::S_IROTH).bits(),
|
||||||
nlinks: 0,
|
nlinks: 0,
|
||||||
uid: 0,
|
uid: 0,
|
||||||
gid: 0,
|
gid: 0,
|
||||||
|
@ -47,6 +47,10 @@ pub trait File: Debug + Sync + Send + Any {
|
|||||||
return_op_unsupported_error!("metadata")
|
return_op_unsupported_error!("metadata")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_metadata(&self, metadata: &Metadata) -> Result<()> {
|
||||||
|
return_op_unsupported_error!("set_metadata")
|
||||||
|
}
|
||||||
|
|
||||||
fn set_len(&self, len: u64) -> Result<()> {
|
fn set_len(&self, len: u64) -> Result<()> {
|
||||||
return_op_unsupported_error!("set_len")
|
return_op_unsupported_error!("set_len")
|
||||||
}
|
}
|
||||||
|
78
src/libos/src/fs/file_ops/chmod.rs
Normal file
78
src/libos/src/fs/file_ops/chmod.rs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct FileMode: u16 {
|
||||||
|
/// set-user-ID
|
||||||
|
const S_ISUID = 0o4000;
|
||||||
|
/// set-group-ID
|
||||||
|
const S_ISGID = 0o2000;
|
||||||
|
/// sticky bit
|
||||||
|
const S_ISVTX = 0o1000;
|
||||||
|
/// read by owner
|
||||||
|
const S_IRUSR = 0o0400;
|
||||||
|
/// write by owner
|
||||||
|
const S_IWUSR = 0o0200;
|
||||||
|
/// execute/search by owner
|
||||||
|
const S_IXUSR = 0o0100;
|
||||||
|
/// read by group
|
||||||
|
const S_IRGRP = 0o0040;
|
||||||
|
/// write by group
|
||||||
|
const S_IWGRP = 0o0020;
|
||||||
|
/// execute/search by group
|
||||||
|
const S_IXGRP = 0o0010;
|
||||||
|
/// read by others
|
||||||
|
const S_IROTH = 0o0004;
|
||||||
|
/// write by others
|
||||||
|
const S_IWOTH = 0o0002;
|
||||||
|
/// execute/search by others
|
||||||
|
const S_IXOTH = 0o0001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileMode {
|
||||||
|
pub fn is_readable(&self) -> bool {
|
||||||
|
self.contains(FileMode::S_IRUSR)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_writable(&self) -> bool {
|
||||||
|
self.contains(FileMode::S_IWUSR)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_executable(&self) -> bool {
|
||||||
|
self.contains(FileMode::S_IXUSR)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_sticky_bit(&self) -> bool {
|
||||||
|
self.contains(FileMode::S_ISVTX)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_set_uid(&self) -> bool {
|
||||||
|
self.contains(FileMode::S_ISUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_set_gid(&self) -> bool {
|
||||||
|
self.contains(FileMode::S_ISGID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_chmod(path: &str, mode: FileMode) -> Result<()> {
|
||||||
|
debug!("chmod: path: {:?}, mode: {:?}", path, mode);
|
||||||
|
let inode = {
|
||||||
|
let current_ref = process::get_current();
|
||||||
|
let mut current = current_ref.lock().unwrap();
|
||||||
|
current.lookup_inode(path)?
|
||||||
|
};
|
||||||
|
let mut info = inode.metadata()?;
|
||||||
|
info.mode = mode.bits();
|
||||||
|
inode.set_metadata(&info)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_fchmod(fd: FileDesc, mode: FileMode) -> Result<()> {
|
||||||
|
debug!("fchmod: fd: {}, mode: {:?}", fd, mode);
|
||||||
|
let file_ref = process::get_file(fd)?;
|
||||||
|
let mut info = file_ref.metadata()?;
|
||||||
|
info.mode = mode.bits();
|
||||||
|
file_ref.set_metadata(&info)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
30
src/libos/src/fs/file_ops/chown.rs
Normal file
30
src/libos/src/fs/file_ops/chown.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub fn do_chown(path: &str, uid: u32, gid: u32) -> Result<()> {
|
||||||
|
warn!("chown is partial implemented as lchown");
|
||||||
|
do_lchown(path, uid, gid)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_fchown(fd: FileDesc, uid: u32, gid: u32) -> Result<()> {
|
||||||
|
debug!("fchown: fd: {}, uid: {}, gid: {}", fd, uid, gid);
|
||||||
|
let file_ref = process::get_file(fd)?;
|
||||||
|
let mut info = file_ref.metadata()?;
|
||||||
|
info.uid = uid as usize;
|
||||||
|
info.gid = gid as usize;
|
||||||
|
file_ref.set_metadata(&info)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_lchown(path: &str, uid: u32, gid: u32) -> Result<()> {
|
||||||
|
debug!("lchown: path: {:?}, uid: {}, gid: {}", path, uid, gid);
|
||||||
|
let inode = {
|
||||||
|
let current_ref = process::get_current();
|
||||||
|
let mut current = current_ref.lock().unwrap();
|
||||||
|
current.lookup_inode(path)?
|
||||||
|
};
|
||||||
|
let mut info = inode.metadata()?;
|
||||||
|
info.uid = uid as usize;
|
||||||
|
info.gid = gid as usize;
|
||||||
|
inode.set_metadata(&info)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -4,6 +4,8 @@ use process::Process;
|
|||||||
|
|
||||||
pub use self::access::{do_access, do_faccessat, AccessibilityCheckFlags, AccessibilityCheckMode};
|
pub use self::access::{do_access, do_faccessat, AccessibilityCheckFlags, AccessibilityCheckMode};
|
||||||
pub use self::chdir::do_chdir;
|
pub use self::chdir::do_chdir;
|
||||||
|
pub use self::chmod::{do_chmod, do_fchmod, FileMode};
|
||||||
|
pub use self::chown::{do_chown, do_fchown, do_lchown};
|
||||||
pub use self::close::do_close;
|
pub use self::close::do_close;
|
||||||
pub use self::dirent::do_getdents64;
|
pub use self::dirent::do_getdents64;
|
||||||
pub use self::dirfd::{get_dir_path, DirFd};
|
pub use self::dirfd::{get_dir_path, DirFd};
|
||||||
@ -29,6 +31,8 @@ pub use self::write::{do_pwrite, do_write, do_writev};
|
|||||||
|
|
||||||
mod access;
|
mod access;
|
||||||
mod chdir;
|
mod chdir;
|
||||||
|
mod chmod;
|
||||||
|
mod chown;
|
||||||
mod close;
|
mod close;
|
||||||
mod dirent;
|
mod dirent;
|
||||||
mod dirfd;
|
mod dirfd;
|
||||||
|
@ -9,6 +9,14 @@ pub fn do_rename(oldpath: &str, newpath: &str) -> Result<()> {
|
|||||||
let (new_dir_path, new_file_name) = split_path(&newpath);
|
let (new_dir_path, new_file_name) = split_path(&newpath);
|
||||||
let old_dir_inode = current_process.lookup_inode(old_dir_path)?;
|
let old_dir_inode = current_process.lookup_inode(old_dir_path)?;
|
||||||
let new_dir_inode = current_process.lookup_inode(new_dir_path)?;
|
let new_dir_inode = current_process.lookup_inode(new_dir_path)?;
|
||||||
|
let old_file_mode = {
|
||||||
|
let old_file_inode = old_dir_inode.find(old_file_name)?;
|
||||||
|
let metadata = old_file_inode.metadata()?;
|
||||||
|
FileMode::from_bits_truncate(metadata.mode)
|
||||||
|
};
|
||||||
|
if old_file_mode.has_sticky_bit() {
|
||||||
|
warn!("ignoring the sticky bit");
|
||||||
|
}
|
||||||
// TODO: support to modify file's absolute path
|
// TODO: support to modify file's absolute path
|
||||||
old_dir_inode.move_(old_file_name, &new_dir_inode, new_file_name)?;
|
old_dir_inode.move_(old_file_name, &new_dir_inode, new_file_name)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -10,9 +10,14 @@ pub fn do_unlink(path: &str) -> Result<()> {
|
|||||||
current_process.lookup_inode(dir_path)?
|
current_process.lookup_inode(dir_path)?
|
||||||
};
|
};
|
||||||
let file_inode = dir_inode.find(file_name)?;
|
let file_inode = dir_inode.find(file_name)?;
|
||||||
if file_inode.metadata()?.type_ == FileType::Dir {
|
let metadata = file_inode.metadata()?;
|
||||||
|
if metadata.type_ == FileType::Dir {
|
||||||
return_errno!(EISDIR, "unlink on directory");
|
return_errno!(EISDIR, "unlink on directory");
|
||||||
}
|
}
|
||||||
|
let file_mode = FileMode::from_bits_truncate(metadata.mode);
|
||||||
|
if file_mode.has_sticky_bit() {
|
||||||
|
warn!("ignoring the sticky bit");
|
||||||
|
}
|
||||||
dir_inode.unlink(file_name)?;
|
dir_inode.unlink(file_name)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use rcore_fs_sefs::dev::SefsMac;
|
use rcore_fs_sefs::dev::SefsMac;
|
||||||
use sgx_trts::libc::{S_IRUSR, S_IWUSR};
|
|
||||||
|
|
||||||
pub struct INodeFile {
|
pub struct INodeFile {
|
||||||
inode: Arc<dyn INode>,
|
inode: Arc<dyn INode>,
|
||||||
@ -13,7 +12,7 @@ pub struct INodeFile {
|
|||||||
impl File for INodeFile {
|
impl File for INodeFile {
|
||||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
if !self.access_mode.readable() {
|
if !self.access_mode.readable() {
|
||||||
return_errno!(EBADF, "File not readable");
|
return_errno!(EACCES, "File not readable");
|
||||||
}
|
}
|
||||||
let mut offset = self.offset.lock().unwrap();
|
let mut offset = self.offset.lock().unwrap();
|
||||||
let len = self.inode.read_at(*offset, buf).map_err(|e| errno!(e))?;
|
let len = self.inode.read_at(*offset, buf).map_err(|e| errno!(e))?;
|
||||||
@ -23,7 +22,7 @@ impl File for INodeFile {
|
|||||||
|
|
||||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||||
if !self.access_mode.writable() {
|
if !self.access_mode.writable() {
|
||||||
return_errno!(EBADF, "File not writable");
|
return_errno!(EACCES, "File not writable");
|
||||||
}
|
}
|
||||||
let mut offset = self.offset.lock().unwrap();
|
let mut offset = self.offset.lock().unwrap();
|
||||||
if self.status_flags.read().unwrap().always_append() {
|
if self.status_flags.read().unwrap().always_append() {
|
||||||
@ -37,7 +36,7 @@ impl File for INodeFile {
|
|||||||
|
|
||||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||||
if !self.access_mode.readable() {
|
if !self.access_mode.readable() {
|
||||||
return_errno!(EBADF, "File not readable");
|
return_errno!(EACCES, "File not readable");
|
||||||
}
|
}
|
||||||
let len = self.inode.read_at(offset, buf)?;
|
let len = self.inode.read_at(offset, buf)?;
|
||||||
Ok(len)
|
Ok(len)
|
||||||
@ -45,7 +44,7 @@ impl File for INodeFile {
|
|||||||
|
|
||||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||||
if !self.access_mode.writable() {
|
if !self.access_mode.writable() {
|
||||||
return_errno!(EBADF, "File not writable");
|
return_errno!(EACCES, "File not writable");
|
||||||
}
|
}
|
||||||
let len = self.inode.write_at(offset, buf)?;
|
let len = self.inode.write_at(offset, buf)?;
|
||||||
Ok(len)
|
Ok(len)
|
||||||
@ -53,7 +52,7 @@ impl File for INodeFile {
|
|||||||
|
|
||||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
||||||
if !self.access_mode.readable() {
|
if !self.access_mode.readable() {
|
||||||
return_errno!(EBADF, "File not readable");
|
return_errno!(EACCES, "File not readable");
|
||||||
}
|
}
|
||||||
let mut offset = self.offset.lock().unwrap();
|
let mut offset = self.offset.lock().unwrap();
|
||||||
let mut total_len = 0;
|
let mut total_len = 0;
|
||||||
@ -72,7 +71,7 @@ impl File for INodeFile {
|
|||||||
|
|
||||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize> {
|
fn writev(&self, bufs: &[&[u8]]) -> Result<usize> {
|
||||||
if !self.access_mode.writable() {
|
if !self.access_mode.writable() {
|
||||||
return_errno!(EBADF, "File not writable");
|
return_errno!(EACCES, "File not writable");
|
||||||
}
|
}
|
||||||
let mut offset = self.offset.lock().unwrap();
|
let mut offset = self.offset.lock().unwrap();
|
||||||
if self.status_flags.read().unwrap().always_append() {
|
if self.status_flags.read().unwrap().always_append() {
|
||||||
@ -116,9 +115,14 @@ impl File for INodeFile {
|
|||||||
Ok(metadata)
|
Ok(metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_metadata(&self, metadata: &Metadata) -> Result<()> {
|
||||||
|
self.inode.set_metadata(metadata)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn set_len(&self, len: u64) -> Result<()> {
|
fn set_len(&self, len: u64) -> Result<()> {
|
||||||
if !self.access_mode.writable() {
|
if !self.access_mode.writable() {
|
||||||
return_errno!(EBADF, "File not writable. Can't set len.");
|
return_errno!(EACCES, "File not writable. Can't set len.");
|
||||||
}
|
}
|
||||||
self.inode.resize(len as usize)?;
|
self.inode.resize(len as usize)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -136,7 +140,7 @@ impl File for INodeFile {
|
|||||||
|
|
||||||
fn read_entry(&self) -> Result<String> {
|
fn read_entry(&self) -> Result<String> {
|
||||||
if !self.access_mode.readable() {
|
if !self.access_mode.readable() {
|
||||||
return_errno!(EBADF, "File not readable. Can't read entry.");
|
return_errno!(EACCES, "File not readable. Can't read entry.");
|
||||||
}
|
}
|
||||||
let mut offset = self.offset.lock().unwrap();
|
let mut offset = self.offset.lock().unwrap();
|
||||||
let name = self.inode.get_entry(*offset)?;
|
let name = self.inode.get_entry(*offset)?;
|
||||||
@ -177,12 +181,12 @@ impl File for INodeFile {
|
|||||||
match lock.l_type {
|
match lock.l_type {
|
||||||
FlockType::F_RDLCK => {
|
FlockType::F_RDLCK => {
|
||||||
if !self.access_mode.readable() {
|
if !self.access_mode.readable() {
|
||||||
return_errno!(EBADF, "File not readable");
|
return_errno!(EACCES, "File not readable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FlockType::F_WRLCK => {
|
FlockType::F_WRLCK => {
|
||||||
if !self.access_mode.writable() {
|
if !self.access_mode.writable() {
|
||||||
return_errno!(EBADF, "File not writable");
|
return_errno!(EACCES, "File not writable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
@ -201,10 +205,10 @@ impl INodeFile {
|
|||||||
pub fn open(inode: Arc<dyn INode>, abs_path: &str, flags: u32) -> Result<Self> {
|
pub fn open(inode: Arc<dyn INode>, abs_path: &str, flags: u32) -> Result<Self> {
|
||||||
let access_mode = AccessMode::from_u32(flags)?;
|
let access_mode = AccessMode::from_u32(flags)?;
|
||||||
if (access_mode.readable() && !inode.allow_read()?) {
|
if (access_mode.readable() && !inode.allow_read()?) {
|
||||||
return_errno!(EBADF, "File not readable");
|
return_errno!(EACCES, "File not readable");
|
||||||
}
|
}
|
||||||
if (access_mode.writable() && !inode.allow_write()?) {
|
if (access_mode.writable() && !inode.allow_write()?) {
|
||||||
return_errno!(EBADF, "File not writable");
|
return_errno!(EACCES, "File not writable");
|
||||||
}
|
}
|
||||||
let status_flags = StatusFlags::from_bits_truncate(flags);
|
let status_flags = StatusFlags::from_bits_truncate(flags);
|
||||||
Ok(INodeFile {
|
Ok(INodeFile {
|
||||||
@ -253,16 +257,14 @@ impl INodeExt for dyn INode {
|
|||||||
|
|
||||||
fn allow_write(&self) -> Result<bool> {
|
fn allow_write(&self) -> Result<bool> {
|
||||||
let info = self.metadata()?;
|
let info = self.metadata()?;
|
||||||
let perms = info.mode as u32;
|
let file_mode = FileMode::from_bits_truncate(info.mode);
|
||||||
let writable = (perms & S_IWUSR) == S_IWUSR;
|
Ok(file_mode.is_writable())
|
||||||
Ok(writable)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allow_read(&self) -> Result<bool> {
|
fn allow_read(&self) -> Result<bool> {
|
||||||
let info = self.metadata()?;
|
let info = self.metadata()?;
|
||||||
let perms = info.mode as u32;
|
let file_mode = FileMode::from_bits_truncate(info.mode);
|
||||||
let readable = (perms & S_IRUSR) == S_IRUSR;
|
Ok(file_mode.is_readable())
|
||||||
Ok(readable)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use std::path::Path;
|
|||||||
pub use self::dev_fs::AsDevRandom;
|
pub use self::dev_fs::AsDevRandom;
|
||||||
pub use self::event_file::{AsEvent, EventFile};
|
pub use self::event_file::{AsEvent, EventFile};
|
||||||
pub use self::file::{File, FileRef};
|
pub use self::file::{File, FileRef};
|
||||||
pub use self::file_ops::{AccessMode, CreationFlags, Stat, StatusFlags};
|
pub use self::file_ops::{AccessMode, CreationFlags, FileMode, Stat, StatusFlags};
|
||||||
pub use self::file_ops::{Flock, FlockType};
|
pub use self::file_ops::{Flock, FlockType};
|
||||||
pub use self::file_ops::{IoctlCmd, StructuredIoctlArgType, StructuredIoctlNum};
|
pub use self::file_ops::{IoctlCmd, StructuredIoctlArgType, StructuredIoctlNum};
|
||||||
pub use self::file_table::{FileDesc, FileTable};
|
pub use self::file_table::{FileDesc, FileTable};
|
||||||
|
@ -369,6 +369,42 @@ pub fn do_readlink(path: *const i8, buf: *mut u8, size: usize) -> Result<isize>
|
|||||||
Ok(len as isize)
|
Ok(len as isize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn do_chmod(path: *const i8, mode: u16) -> Result<isize> {
|
||||||
|
let path = from_user::clone_cstring_safely(path)?
|
||||||
|
.to_string_lossy()
|
||||||
|
.into_owned();
|
||||||
|
let mode = FileMode::from_bits_truncate(mode);
|
||||||
|
file_ops::do_chmod(&path, mode)?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_fchmod(fd: FileDesc, mode: u16) -> Result<isize> {
|
||||||
|
let mode = FileMode::from_bits_truncate(mode);
|
||||||
|
file_ops::do_fchmod(fd, mode)?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_chown(path: *const i8, uid: u32, gid: u32) -> Result<isize> {
|
||||||
|
let path = from_user::clone_cstring_safely(path)?
|
||||||
|
.to_string_lossy()
|
||||||
|
.into_owned();
|
||||||
|
file_ops::do_chown(&path, uid, gid)?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_fchown(fd: FileDesc, uid: u32, gid: u32) -> Result<isize> {
|
||||||
|
file_ops::do_fchown(fd, uid, gid)?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_lchown(path: *const i8, uid: u32, gid: u32) -> Result<isize> {
|
||||||
|
let path = from_user::clone_cstring_safely(path)?
|
||||||
|
.to_string_lossy()
|
||||||
|
.into_owned();
|
||||||
|
file_ops::do_lchown(&path, uid, gid)?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn do_sendfile(
|
pub fn do_sendfile(
|
||||||
out_fd: FileDesc,
|
out_fd: FileDesc,
|
||||||
in_fd: FileDesc,
|
in_fd: FileDesc,
|
||||||
|
@ -5,8 +5,8 @@ use std::path::Path;
|
|||||||
use std::sgxfs::SgxFile;
|
use std::sgxfs::SgxFile;
|
||||||
|
|
||||||
use super::fs::{
|
use super::fs::{
|
||||||
CreationFlags, File, FileDesc, FileTable, HostStdioFds, INodeExt, StdinFile, StdoutFile,
|
CreationFlags, File, FileDesc, FileMode, FileTable, HostStdioFds, INodeExt, StdinFile,
|
||||||
ROOT_INODE,
|
StdoutFile, ROOT_INODE,
|
||||||
};
|
};
|
||||||
use super::misc::ResourceLimitsRef;
|
use super::misc::ResourceLimitsRef;
|
||||||
use super::vm::{ProcessVM, ProcessVMBuilder};
|
use super::vm::{ProcessVM, ProcessVMBuilder};
|
||||||
@ -146,14 +146,27 @@ pub enum FileAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_elf_to_vec(elf_path: &str, parent_ref: &ProcessRef) -> Result<Vec<u8>> {
|
fn load_elf_to_vec(elf_path: &str, parent_ref: &ProcessRef) -> Result<Vec<u8>> {
|
||||||
#[rustfmt::skip]
|
let inode = parent_ref
|
||||||
parent_ref
|
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.lookup_inode(elf_path)
|
.lookup_inode(elf_path)
|
||||||
.map_err(|e| errno!(e.errno(), "cannot find the ELF"))?
|
.map_err(|e| errno!(e.errno(), "cannot find the ELF"))?;
|
||||||
|
let file_mode = {
|
||||||
|
let info = inode.metadata()?;
|
||||||
|
FileMode::from_bits_truncate(info.mode)
|
||||||
|
};
|
||||||
|
if !file_mode.is_executable() {
|
||||||
|
return_errno!(EACCES, "elf file is not executable");
|
||||||
|
}
|
||||||
|
if file_mode.has_set_uid() || file_mode.has_set_gid() {
|
||||||
|
warn!(
|
||||||
|
"set-user-ID and set-group-ID are not supportted, FileMode:{:?}",
|
||||||
|
file_mode
|
||||||
|
);
|
||||||
|
}
|
||||||
|
inode
|
||||||
.read_as_vec()
|
.read_as_vec()
|
||||||
.map_err(|e| errno!(e.errno(), "failed to read the executable ELF"))
|
.map_err(|e| errno!(e.errno(), "failed to read the executable ELF"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_files(
|
fn init_files(
|
||||||
|
@ -8,12 +8,12 @@
|
|||||||
//! 4. Call `do_*` to process the system call (in other modules)
|
//! 4. Call `do_*` to process the system call (in other modules)
|
||||||
|
|
||||||
use fs::{
|
use fs::{
|
||||||
do_access, do_chdir, do_close, do_dup, do_dup2, do_dup3, do_eventfd, do_eventfd2, do_faccessat,
|
do_access, do_chdir, do_chmod, do_chown, do_close, do_dup, do_dup2, do_dup3, do_eventfd,
|
||||||
do_fcntl, do_fdatasync, do_fstat, do_fstatat, do_fsync, do_ftruncate, do_getdents64, do_ioctl,
|
do_eventfd2, do_faccessat, do_fchmod, do_fchown, do_fcntl, do_fdatasync, do_fstat, do_fstatat,
|
||||||
do_link, do_lseek, do_lstat, do_mkdir, do_open, do_openat, do_pipe, do_pipe2, do_pread,
|
do_fsync, do_ftruncate, do_getdents64, do_ioctl, do_lchown, do_link, do_lseek, do_lstat,
|
||||||
do_pwrite, do_read, do_readlink, do_readv, do_rename, do_rmdir, do_sendfile, do_stat, do_sync,
|
do_mkdir, do_open, do_openat, do_pipe, do_pipe2, do_pread, do_pwrite, do_read, do_readlink,
|
||||||
do_truncate, do_unlink, do_write, do_writev, iovec_t, File, FileDesc, FileRef, HostStdioFds,
|
do_readv, do_rename, do_rmdir, do_sendfile, do_stat, do_sync, do_truncate, do_unlink, do_write,
|
||||||
Stat,
|
do_writev, iovec_t, File, FileDesc, FileRef, HostStdioFds, Stat,
|
||||||
};
|
};
|
||||||
use misc::{resource_t, rlimit_t, utsname_t};
|
use misc::{resource_t, rlimit_t, utsname_t};
|
||||||
use net::{
|
use net::{
|
||||||
@ -154,11 +154,11 @@ macro_rules! process_syscall_table_with_callback {
|
|||||||
(Unlink = 87) => do_unlink(path: *const i8),
|
(Unlink = 87) => do_unlink(path: *const i8),
|
||||||
(Symlink = 88) => handle_unsupported(),
|
(Symlink = 88) => handle_unsupported(),
|
||||||
(Readlink = 89) => do_readlink(path: *const i8, buf: *mut u8, size: usize),
|
(Readlink = 89) => do_readlink(path: *const i8, buf: *mut u8, size: usize),
|
||||||
(Chmod = 90) => handle_unsupported(),
|
(Chmod = 90) => do_chmod(path: *const i8, mode: u16),
|
||||||
(Fchmod = 91) => handle_unsupported(),
|
(Fchmod = 91) => do_fchmod(fd: FileDesc, mode: u16),
|
||||||
(Chown = 92) => handle_unsupported(),
|
(Chown = 92) => do_chown(path: *const i8, uid: u32, gid: u32),
|
||||||
(Fchown = 93) => handle_unsupported(),
|
(Fchown = 93) => do_fchown(fd: FileDesc, uid: u32, gid: u32),
|
||||||
(Lchown = 94) => handle_unsupported(),
|
(Lchown = 94) => do_lchown(path: *const i8, uid: u32, gid: u32),
|
||||||
(Umask = 95) => handle_unsupported(),
|
(Umask = 95) => handle_unsupported(),
|
||||||
(Gettimeofday = 96) => do_gettimeofday(tv_u: *mut timeval_t),
|
(Gettimeofday = 96) => do_gettimeofday(tv_u: *mut timeval_t),
|
||||||
(Getrlimit = 97) => handle_unsupported(),
|
(Getrlimit = 97) => handle_unsupported(),
|
||||||
|
@ -12,8 +12,8 @@ endif
|
|||||||
TEST_DEPS := client data_sink
|
TEST_DEPS := client data_sink
|
||||||
# Tests: need to be compiled and run by test-% target
|
# Tests: need to be compiled and run by test-% target
|
||||||
TESTS ?= empty env hello_world malloc mmap file fs_perms getpid spawn sched pipe time \
|
TESTS ?= empty env hello_world malloc mmap file fs_perms getpid spawn sched pipe time \
|
||||||
truncate readdir mkdir open stat link symlink tls pthread uname rlimit server \
|
truncate readdir mkdir open stat link symlink chmod chown tls pthread uname rlimit \
|
||||||
server_epoll unix_socket cout hostfs cpuid rdtsc device sleep exit_group \
|
server server_epoll unix_socket cout hostfs cpuid rdtsc device sleep exit_group \
|
||||||
ioctl fcntl eventfd
|
ioctl fcntl eventfd
|
||||||
# Benchmarks: need to be compiled and run by bench-% target
|
# Benchmarks: need to be compiled and run by bench-% target
|
||||||
BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput
|
BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput
|
||||||
|
5
test/chmod/Makefile
Normal file
5
test/chmod/Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
include ../test_common.mk
|
||||||
|
|
||||||
|
EXTRA_C_FLAGS :=
|
||||||
|
EXTRA_LINK_FLAGS :=
|
||||||
|
BIN_ARGS :=
|
116
test/chmod/main.c
Normal file
116
test/chmod/main.c
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Helper function
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static int create_file(const char *file_path) {
|
||||||
|
int fd;
|
||||||
|
int flags = O_RDONLY | O_CREAT| O_TRUNC;
|
||||||
|
int mode = 00444;
|
||||||
|
|
||||||
|
fd = open(file_path, flags, mode);
|
||||||
|
if (fd < 0) {
|
||||||
|
THROW_ERROR("failed to create a file");
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int remove_file(const char *file_path) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = unlink(file_path);
|
||||||
|
if (ret < 0) {
|
||||||
|
THROW_ERROR("failed to unlink the created file");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test cases for stat
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static int __test_chmod(const char *file_path) {
|
||||||
|
struct stat stat_buf;
|
||||||
|
mode_t mode = 00664;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = chmod(file_path, mode);
|
||||||
|
if (ret < 0) {
|
||||||
|
THROW_ERROR("failed to chmod file");
|
||||||
|
}
|
||||||
|
ret = stat(file_path, &stat_buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
THROW_ERROR("failed to stat file");
|
||||||
|
}
|
||||||
|
if ((stat_buf.st_mode & 07777) != mode) {
|
||||||
|
THROW_ERROR("check chmod result failed");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __test_fchmod(const char *file_path) {
|
||||||
|
struct stat stat_buf;
|
||||||
|
mode_t mode = 00664;
|
||||||
|
int fd, ret;
|
||||||
|
|
||||||
|
fd = open(file_path, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
THROW_ERROR("failed to open file");
|
||||||
|
}
|
||||||
|
ret = fchmod(fd, mode);
|
||||||
|
if (ret < 0) {
|
||||||
|
close(fd);
|
||||||
|
THROW_ERROR("failed to fchmod file");
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
ret = stat(file_path, &stat_buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
THROW_ERROR("failed to stat file");
|
||||||
|
}
|
||||||
|
if ((stat_buf.st_mode & 07777) != mode) {
|
||||||
|
THROW_ERROR("check fchmod result failed");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int(*test_chmod_func_t)(const char *);
|
||||||
|
|
||||||
|
static int test_chmod_framework(test_chmod_func_t fn) {
|
||||||
|
const char *file_path = "/root/test_filesystem_chmod.txt";
|
||||||
|
|
||||||
|
if (create_file(file_path) < 0)
|
||||||
|
return -1;
|
||||||
|
if (fn(file_path) < 0)
|
||||||
|
return -1;
|
||||||
|
if (remove_file(file_path) < 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_chmod() {
|
||||||
|
return test_chmod_framework(__test_chmod);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_fchmod() {
|
||||||
|
return test_chmod_framework(__test_fchmod);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test suite main
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static test_case_t test_cases[] = {
|
||||||
|
TEST_CASE(test_chmod),
|
||||||
|
TEST_CASE(test_fchmod),
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, const char *argv[]) {
|
||||||
|
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
|
||||||
|
}
|
5
test/chown/Makefile
Normal file
5
test/chown/Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
include ../test_common.mk
|
||||||
|
|
||||||
|
EXTRA_C_FLAGS :=
|
||||||
|
EXTRA_LINK_FLAGS :=
|
||||||
|
BIN_ARGS :=
|
143
test/chown/main.c
Normal file
143
test/chown/main.c
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Helper function
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static int create_file(const char *file_path) {
|
||||||
|
int fd;
|
||||||
|
int flags = O_RDONLY | O_CREAT| O_TRUNC;
|
||||||
|
int mode = 00444;
|
||||||
|
|
||||||
|
fd = open(file_path, flags, mode);
|
||||||
|
if (fd < 0) {
|
||||||
|
THROW_ERROR("failed to create a file");
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int remove_file(const char *file_path) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = unlink(file_path);
|
||||||
|
if (ret < 0) {
|
||||||
|
THROW_ERROR("failed to unlink the created file");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test cases for stat
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static int __test_chown(const char *file_path) {
|
||||||
|
struct stat stat_buf;
|
||||||
|
uid_t uid = 100;
|
||||||
|
gid_t gid = 1000;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = chown(file_path, uid, gid);
|
||||||
|
if (ret < 0) {
|
||||||
|
THROW_ERROR("failed to chown file");
|
||||||
|
}
|
||||||
|
ret = stat(file_path, &stat_buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
THROW_ERROR("failed to stat file");
|
||||||
|
}
|
||||||
|
if (stat_buf.st_uid != uid || stat_buf.st_gid != gid) {
|
||||||
|
THROW_ERROR("check chown result failed");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __test_lchown(const char *file_path) {
|
||||||
|
struct stat stat_buf;
|
||||||
|
uid_t uid = 100;
|
||||||
|
gid_t gid = 1000;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = lchown(file_path, uid, gid);
|
||||||
|
if (ret < 0) {
|
||||||
|
THROW_ERROR("failed to lchown file");
|
||||||
|
}
|
||||||
|
ret = stat(file_path, &stat_buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
THROW_ERROR("failed to stat file");
|
||||||
|
}
|
||||||
|
if (stat_buf.st_uid != uid || stat_buf.st_gid != gid) {
|
||||||
|
THROW_ERROR("check lchown result failed");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __test_fchown(const char *file_path) {
|
||||||
|
struct stat stat_buf;
|
||||||
|
uid_t uid = 100;
|
||||||
|
gid_t gid = 1000;
|
||||||
|
int fd, ret;
|
||||||
|
|
||||||
|
fd = open(file_path, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
THROW_ERROR("failed to open file");
|
||||||
|
}
|
||||||
|
ret = fchown(fd, uid, gid);
|
||||||
|
if (ret < 0) {
|
||||||
|
close(fd);
|
||||||
|
THROW_ERROR("failed to fchown file");
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
ret = stat(file_path, &stat_buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
THROW_ERROR("failed to stat file");
|
||||||
|
}
|
||||||
|
if (stat_buf.st_uid != uid || stat_buf.st_gid != gid) {
|
||||||
|
THROW_ERROR("check fchown result failed");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int(*test_chown_func_t)(const char *);
|
||||||
|
|
||||||
|
static int test_chown_framework(test_chown_func_t fn) {
|
||||||
|
const char *file_path = "/root/test_filesystem_chown.txt";
|
||||||
|
|
||||||
|
if (create_file(file_path) < 0)
|
||||||
|
return -1;
|
||||||
|
if (fn(file_path) < 0)
|
||||||
|
return -1;
|
||||||
|
if (remove_file(file_path) < 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_chown() {
|
||||||
|
return test_chown_framework(__test_chown);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_lchown() {
|
||||||
|
return test_chown_framework(__test_lchown);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_fchown() {
|
||||||
|
return test_chown_framework(__test_fchown);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test suite main
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static test_case_t test_cases[] = {
|
||||||
|
TEST_CASE(test_chown),
|
||||||
|
TEST_CASE(test_lchown),
|
||||||
|
TEST_CASE(test_fchown),
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, const char *argv[]) {
|
||||||
|
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user