mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 05:16:47 +00:00
Add sys_access and sys_faccessat
This commit is contained in:
parent
212dd562a0
commit
d33f90eaeb
@ -289,7 +289,7 @@ provided by Linux on x86-64 architecture.
|
||||
| 266 | symlinkat | ✅ |
|
||||
| 267 | readlinkat | ✅ |
|
||||
| 268 | fchmodat | ✅ |
|
||||
| 269 | faccessat | ❌ |
|
||||
| 269 | faccessat | ✅ |
|
||||
| 270 | pselect6 | ❌ |
|
||||
| 271 | ppoll | ❌ |
|
||||
| 272 | unshare | ❌ |
|
||||
|
@ -1,11 +1,96 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use super::{constants::*, SyscallReturn};
|
||||
use crate::{prelude::*, util::read_cstring_from_user};
|
||||
use super::SyscallReturn;
|
||||
use crate::{
|
||||
fs::{
|
||||
file_table::FileDesc,
|
||||
fs_resolver::{FsPath, AT_FDCWD},
|
||||
utils::PATH_MAX,
|
||||
},
|
||||
prelude::*,
|
||||
util::read_cstring_from_user,
|
||||
};
|
||||
|
||||
pub fn sys_faccessat(dirfd: FileDesc, path_ptr: Vaddr, mode: u16) -> Result<SyscallReturn> {
|
||||
debug!(
|
||||
"faccessat: dirfd = {}, path_ptr = {:#x}, mode = {:o}",
|
||||
dirfd, path_ptr, mode
|
||||
);
|
||||
|
||||
do_faccessat(dirfd, path_ptr, mode, 0)
|
||||
}
|
||||
|
||||
pub fn sys_access(path_ptr: Vaddr, mode: u16) -> Result<SyscallReturn> {
|
||||
debug!("access: path_ptr = {:#x}, mode = {:o}", path_ptr, mode);
|
||||
|
||||
do_faccessat(AT_FDCWD, path_ptr, mode, 0)
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
struct FaccessatFlags: i32 {
|
||||
const AT_EACCESS = 0x200;
|
||||
const AT_SYMLINK_NOFOLLOW = 0x100;
|
||||
const AT_EMPTY_PATH = 0x1000;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
struct AccessMode: u16 {
|
||||
const R_OK = 0x4;
|
||||
const W_OK = 0x2;
|
||||
const X_OK = 0x1;
|
||||
// We could ignore F_OK in bitflags.
|
||||
// const F_OK = 0x0;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn do_faccessat(
|
||||
dirfd: FileDesc,
|
||||
path_ptr: Vaddr,
|
||||
mode: u16,
|
||||
flags: i32,
|
||||
) -> Result<SyscallReturn> {
|
||||
let mode = AccessMode::from_bits(mode)
|
||||
.ok_or_else(|| Error::with_message(Errno::EINVAL, "Invalid mode"))?;
|
||||
let flags = FaccessatFlags::from_bits(flags)
|
||||
.ok_or_else(|| Error::with_message(Errno::EINVAL, "Invalid flags"))?;
|
||||
|
||||
let path = read_cstring_from_user(path_ptr, PATH_MAX)?;
|
||||
debug!(
|
||||
"dirfd = {}, path = {:?}, mode = {:o}, flags = {:?}",
|
||||
dirfd, path, mode, flags
|
||||
);
|
||||
|
||||
let current = current!();
|
||||
let dentry = {
|
||||
let path = path.to_string_lossy();
|
||||
let fs_path = FsPath::new(dirfd, path.as_ref())?;
|
||||
let fs = current.fs().read();
|
||||
if flags.contains(FaccessatFlags::AT_SYMLINK_NOFOLLOW) {
|
||||
fs.lookup_no_follow(&fs_path)?
|
||||
} else {
|
||||
fs.lookup(&fs_path)?
|
||||
}
|
||||
};
|
||||
// AccessMode::empty() means F_OK and no more permission check needed.
|
||||
if mode.is_empty() {
|
||||
return Ok(SyscallReturn::Return(0));
|
||||
}
|
||||
|
||||
let inode_mode = dentry.mode()?;
|
||||
|
||||
// FIXME: The current implementation is dummy
|
||||
if mode.contains(AccessMode::R_OK) && !inode_mode.is_readable() {
|
||||
return_errno_with_message!(Errno::EACCES, "Read permission denied");
|
||||
}
|
||||
|
||||
if mode.contains(AccessMode::W_OK) && !inode_mode.is_writable() {
|
||||
return_errno_with_message!(Errno::EACCES, "Write permission denied");
|
||||
}
|
||||
|
||||
if mode.contains(AccessMode::X_OK) && !inode_mode.is_executable() {
|
||||
return_errno_with_message!(Errno::EACCES, "Execute permission denied");
|
||||
}
|
||||
|
||||
pub fn sys_access(filename_ptr: Vaddr, file_mode: u64) -> Result<SyscallReturn> {
|
||||
let filename = read_cstring_from_user(filename_ptr, MAX_FILENAME_LEN)?;
|
||||
debug!("filename: {:?}, file_mode = {}", filename, file_mode);
|
||||
// TODO: access currenly does not check and just return success
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use crate::syscall::{
|
||||
accept::{sys_accept, sys_accept4},
|
||||
access::sys_access,
|
||||
access::{sys_access, sys_faccessat},
|
||||
alarm::sys_alarm,
|
||||
arch_prctl::sys_arch_prctl,
|
||||
bind::sys_bind,
|
||||
@ -272,6 +272,7 @@ impl_syscall_nums_and_dispatch_fn! {
|
||||
SYS_SYMLINKAT = 266 => sys_symlinkat(args[..3]);
|
||||
SYS_READLINKAT = 267 => sys_readlinkat(args[..4]);
|
||||
SYS_FCHMODAT = 268 => sys_fchmodat(args[..3]);
|
||||
SYS_FACCESSAT = 269 => sys_faccessat(args[..3]);
|
||||
SYS_SET_ROBUST_LIST = 273 => sys_set_robust_list(args[..2]);
|
||||
SYS_UTIMENSAT = 280 => sys_utimensat(args[..4]);
|
||||
SYS_EPOLL_PWAIT = 281 => sys_epoll_pwait(args[..6]);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#
|
||||
# Please keep the list sorted by name.
|
||||
TESTS ?= \
|
||||
access_test \
|
||||
alarm_test \
|
||||
chmod_test \
|
||||
chown_test \
|
||||
|
1
regression/syscall_test/blocklists.exfat/access_test
Normal file
1
regression/syscall_test/blocklists.exfat/access_test
Normal file
@ -0,0 +1 @@
|
||||
AccessTest.UsrReadWrite
|
3
regression/syscall_test/blocklists/access_test
Normal file
3
regression/syscall_test/blocklists/access_test
Normal file
@ -0,0 +1,3 @@
|
||||
AccessTest.NoPerms
|
||||
AccessTest.UsrReadOnly
|
||||
AccessTest.UsrReadExec
|
Loading…
x
Reference in New Issue
Block a user