Support syscall fchmodat2
This commit is contained in:
parent
0dd061269e
commit
8152695a17
|
|
@ -288,7 +288,7 @@ which are summarized in the table below.
|
|||
| 265 | linkat | ✅ | ❓ |
|
||||
| 266 | symlinkat | ✅ | 💯 |
|
||||
| 267 | readlinkat | ✅ | 💯 |
|
||||
| 268 | fchmodat | ✅ | ❓ |
|
||||
| 268 | fchmodat | ✅ | 💯 |
|
||||
| 269 | faccessat | ✅ | ❓ |
|
||||
| 270 | pselect6 | ✅ | 💯 |
|
||||
| 271 | ppoll | ✅ | ❓ |
|
||||
|
|
@ -348,6 +348,7 @@ which are summarized in the table below.
|
|||
| 436 | close_range | ✅ | ❓ |
|
||||
| 439 | faccessat2 | ✅ | ❓ |
|
||||
| 441 | epoll_pwait2 | ✅ | ❓ |
|
||||
| 452 | fchmodat2 | ✅ | 💯 |
|
||||
|
||||
- Supported:
|
||||
- ✅ = syscall supported
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ readlinkat(dirfd, path, buf, bufsiz);
|
|||
// Change permissions of a file
|
||||
chmod(path, mode);
|
||||
fchmod(fd, mode);
|
||||
fchmodat(dirfd, path_ptr, mode);
|
||||
fchmodat2(dirfd, path_ptr, mode, flags = AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
|
||||
|
||||
// Change ownership of a file
|
||||
chown(path, owner, group);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use super::{
|
|||
capget::sys_capget,
|
||||
capset::sys_capset,
|
||||
chdir::{sys_chdir, sys_fchdir},
|
||||
chmod::{sys_fchmod, sys_fchmodat},
|
||||
chmod::{sys_fchmod, sys_fchmodat, sys_fchmodat2},
|
||||
chown::{sys_fchown, sys_fchownat},
|
||||
chroot::sys_chroot,
|
||||
clock_gettime::sys_clock_gettime,
|
||||
|
|
@ -356,4 +356,5 @@ impl_syscall_nums_and_dispatch_fn! {
|
|||
SYS_CLOSE_RANGE = 436 => sys_close_range(args[..3]);
|
||||
SYS_FACCESSAT2 = 439 => sys_faccessat2(args[..4]);
|
||||
SYS_EPOLL_PWAIT2 = 441 => sys_epoll_pwait2(args[..5]);
|
||||
SYS_FCHMODAT2 = 452 => sys_fchmodat2(args[..4]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use super::{
|
|||
capget::sys_capget,
|
||||
capset::sys_capset,
|
||||
chdir::{sys_chdir, sys_fchdir},
|
||||
chmod::{sys_fchmod, sys_fchmodat},
|
||||
chmod::{sys_fchmod, sys_fchmodat, sys_fchmodat2},
|
||||
chown::{sys_fchown, sys_fchownat},
|
||||
chroot::sys_chroot,
|
||||
clock_gettime::sys_clock_gettime,
|
||||
|
|
@ -358,4 +358,5 @@ impl_syscall_nums_and_dispatch_fn! {
|
|||
SYS_CLOSE_RANGE = 436 => sys_close_range(args[..3]);
|
||||
SYS_FACCESSAT2 = 439 => sys_faccessat2(args[..4]);
|
||||
SYS_EPOLL_PWAIT2 = 441 => sys_epoll_pwait2(args[..5]);
|
||||
SYS_FCHMODAT2 = 452 => sys_fchmodat2(args[..4]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use super::{
|
|||
capget::sys_capget,
|
||||
capset::sys_capset,
|
||||
chdir::{sys_chdir, sys_fchdir},
|
||||
chmod::{sys_chmod, sys_fchmod, sys_fchmodat},
|
||||
chmod::{sys_chmod, sys_fchmod, sys_fchmodat, sys_fchmodat2},
|
||||
chown::{sys_chown, sys_fchown, sys_fchownat, sys_lchown},
|
||||
chroot::sys_chroot,
|
||||
clock_gettime::sys_clock_gettime,
|
||||
|
|
@ -407,4 +407,5 @@ impl_syscall_nums_and_dispatch_fn! {
|
|||
SYS_CLOSE_RANGE = 436 => sys_close_range(args[..3]);
|
||||
SYS_FACCESSAT2 = 439 => sys_faccessat2(args[..4]);
|
||||
SYS_EPOLL_PWAIT2 = 441 => sys_epoll_pwait2(args[..5]);
|
||||
SYS_FCHMODAT2 = 452 => sys_fchmodat2(args[..4]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,32 +24,62 @@ pub fn sys_fchmod(fd: FileDesc, mode: u16, ctx: &Context) -> Result<SyscallRetur
|
|||
}
|
||||
|
||||
pub fn sys_chmod(path_ptr: Vaddr, mode: u16, ctx: &Context) -> Result<SyscallReturn> {
|
||||
self::sys_fchmodat(AT_FDCWD, path_ptr, mode, ctx)
|
||||
do_fchmodat(AT_FDCWD, path_ptr, mode, ChmodFlags::empty(), ctx)
|
||||
}
|
||||
|
||||
// Glibc handles the `flags` argument, so we just ignore it.
|
||||
pub fn sys_fchmodat(
|
||||
dirfd: FileDesc,
|
||||
path_ptr: Vaddr,
|
||||
mode: u16,
|
||||
/* flags: u32, */
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
do_fchmodat(dirfd, path_ptr, mode, ChmodFlags::empty(), ctx)
|
||||
}
|
||||
|
||||
pub fn sys_fchmodat2(
|
||||
dirfd: FileDesc,
|
||||
path_ptr: Vaddr,
|
||||
mode: u16,
|
||||
flags: u32,
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
let flags = ChmodFlags::from_bits(flags)
|
||||
.ok_or_else(|| Error::with_message(Errno::EINVAL, "invalid chmod flags"))?;
|
||||
|
||||
do_fchmodat(dirfd, path_ptr, mode, flags, ctx)
|
||||
}
|
||||
|
||||
fn do_fchmodat(
|
||||
dirfd: FileDesc,
|
||||
path_ptr: Vaddr,
|
||||
mode: u16,
|
||||
flags: ChmodFlags,
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
let path_name = ctx.user_space().read_cstring(path_ptr, PATH_MAX)?;
|
||||
|
||||
debug!(
|
||||
"dirfd = {}, path_name = {:?}, mode = 0o{:o}",
|
||||
dirfd, path_name, mode,
|
||||
"dirfd = {}, path_name = {:?}, mode = 0o{:o}, flags = {:?}",
|
||||
dirfd, path_name, mode, flags,
|
||||
);
|
||||
|
||||
let path_or_inode = {
|
||||
let path_name = path_name.to_string_lossy();
|
||||
let fs_path = FsPath::from_fd_and_path(dirfd, &path_name)?;
|
||||
ctx.thread_local
|
||||
.borrow_fs()
|
||||
.resolver()
|
||||
.read()
|
||||
.lookup_inode(&fs_path)?
|
||||
let fs_path = if flags.contains(ChmodFlags::AT_EMPTY_PATH) && path_name.is_empty() {
|
||||
FsPath::from_fd(dirfd)?
|
||||
} else {
|
||||
FsPath::from_fd_and_path(dirfd, &path_name)?
|
||||
};
|
||||
|
||||
let fs_ref = ctx.thread_local.borrow_fs();
|
||||
let fs = fs_ref.resolver().read();
|
||||
if flags.contains(ChmodFlags::AT_SYMLINK_NOFOLLOW) {
|
||||
fs.lookup_inode_no_follow(&fs_path)?
|
||||
} else {
|
||||
fs.lookup_inode(&fs_path)?
|
||||
}
|
||||
};
|
||||
|
||||
path_or_inode
|
||||
.inode()
|
||||
.set_mode(InodeMode::from_bits_truncate(mode))?;
|
||||
|
|
@ -58,3 +88,10 @@ pub fn sys_fchmodat(
|
|||
}
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
struct ChmodFlags: u32 {
|
||||
const AT_EMPTY_PATH = 1 << 12;
|
||||
const AT_SYMLINK_NOFOLLOW = 1 << 8;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue