Add sys_access and sys_faccessat

This commit is contained in:
Fabing Li 2024-06-27 11:12:22 +08:00 committed by Tate, Hongliang Tian
parent 212dd562a0
commit d33f90eaeb
6 changed files with 99 additions and 8 deletions

View File

@ -289,7 +289,7 @@ provided by Linux on x86-64 architecture.
| 266 | symlinkat | ✅ | | 266 | symlinkat | ✅ |
| 267 | readlinkat | ✅ | | 267 | readlinkat | ✅ |
| 268 | fchmodat | ✅ | | 268 | fchmodat | ✅ |
| 269 | faccessat | | | 269 | faccessat | |
| 270 | pselect6 | ❌ | | 270 | pselect6 | ❌ |
| 271 | ppoll | ❌ | | 271 | ppoll | ❌ |
| 272 | unshare | ❌ | | 272 | unshare | ❌ |

View File

@ -1,11 +1,96 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use super::{constants::*, SyscallReturn}; use super::SyscallReturn;
use crate::{prelude::*, util::read_cstring_from_user}; 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)) Ok(SyscallReturn::Return(0))
} }

View File

@ -2,7 +2,7 @@
use crate::syscall::{ use crate::syscall::{
accept::{sys_accept, sys_accept4}, accept::{sys_accept, sys_accept4},
access::sys_access, access::{sys_access, sys_faccessat},
alarm::sys_alarm, alarm::sys_alarm,
arch_prctl::sys_arch_prctl, arch_prctl::sys_arch_prctl,
bind::sys_bind, bind::sys_bind,
@ -272,6 +272,7 @@ impl_syscall_nums_and_dispatch_fn! {
SYS_SYMLINKAT = 266 => sys_symlinkat(args[..3]); SYS_SYMLINKAT = 266 => sys_symlinkat(args[..3]);
SYS_READLINKAT = 267 => sys_readlinkat(args[..4]); SYS_READLINKAT = 267 => sys_readlinkat(args[..4]);
SYS_FCHMODAT = 268 => sys_fchmodat(args[..3]); 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_SET_ROBUST_LIST = 273 => sys_set_robust_list(args[..2]);
SYS_UTIMENSAT = 280 => sys_utimensat(args[..4]); SYS_UTIMENSAT = 280 => sys_utimensat(args[..4]);
SYS_EPOLL_PWAIT = 281 => sys_epoll_pwait(args[..6]); SYS_EPOLL_PWAIT = 281 => sys_epoll_pwait(args[..6]);

View File

@ -6,6 +6,7 @@
# #
# Please keep the list sorted by name. # Please keep the list sorted by name.
TESTS ?= \ TESTS ?= \
access_test \
alarm_test \ alarm_test \
chmod_test \ chmod_test \
chown_test \ chown_test \

View File

@ -0,0 +1 @@
AccessTest.UsrReadWrite

View File

@ -0,0 +1,3 @@
AccessTest.NoPerms
AccessTest.UsrReadOnly
AccessTest.UsrReadExec