Kernel/LibC: Implement all chmod family functions using fchmodat

This commit is contained in:
Bananymous 2024-09-17 17:16:46 +03:00
parent 04ae53b6df
commit 4aa466b948
4 changed files with 34 additions and 22 deletions

View File

@ -113,8 +113,7 @@ namespace Kernel
BAN::ErrorOr<long> sys_pread(int fd, void* buffer, size_t count, off_t offset); BAN::ErrorOr<long> sys_pread(int fd, void* buffer, size_t count, off_t offset);
BAN::ErrorOr<long> sys_chmod(const char* path, mode_t mode); BAN::ErrorOr<long> sys_fchmodat(int fd, const char* path, mode_t mode, int flag);
BAN::ErrorOr<long> sys_fchmod(int fildes, mode_t mode);
BAN::ErrorOr<long> sys_chown(const char* path, uid_t uid, gid_t gid); BAN::ErrorOr<long> sys_chown(const char* path, uid_t uid, gid_t gid);
BAN::ErrorOr<long> sys_socket(int domain, int type, int protocol); BAN::ErrorOr<long> sys_socket(int domain, int type, int protocol);

View File

@ -1026,28 +1026,37 @@ namespace Kernel
return TRY(inode->read(offset, { (uint8_t*)buffer, count })); return TRY(inode->read(offset, { (uint8_t*)buffer, count }));
} }
BAN::ErrorOr<long> Process::sys_chmod(const char* path, mode_t mode) BAN::ErrorOr<long> Process::sys_fchmodat(int fd, const char* path, mode_t mode, int flag)
{ {
if (mode & S_IFMASK) if (mode & S_IFMASK)
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
if (flag & ~AT_SYMLINK_NOFOLLOW)
LockGuard _(m_process_lock);
TRY(validate_string_access(path));
auto absolute_path = TRY(absolute_path_of(path));
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, O_WRONLY));
TRY(file.inode->chmod(mode));
return 0;
}
BAN::ErrorOr<long> Process::sys_fchmod(int fildes, mode_t mode)
{
if (mode & S_IFMASK)
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
if (flag == AT_SYMLINK_NOFOLLOW)
flag = O_NOFOLLOW;
LockGuard _(m_process_lock); LockGuard _(m_process_lock);
auto inode = TRY(m_open_file_descriptors.inode_of(fildes)); if (path)
TRY(validate_string_access(path));
VirtualFileSystem::File parent_file;
if (path && path[0] == '/')
parent_file = VirtualFileSystem::get().root_file();
else if (fd == AT_FDCWD)
parent_file = TRY(m_working_directory.clone());
else
parent_file = TRY(m_open_file_descriptors.file_of(fd));
auto inode = path
? TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flag)).inode
: parent_file.inode;
if (!m_credentials.is_superuser() && inode->uid() != m_credentials.euid())
{
dwarnln("cannot chmod uid {} vs {}", inode->uid(), m_credentials.euid());
return BAN::Error::from_errno(EPERM);
}
TRY(inode->chmod(mode)); TRY(inode->chmod(mode));
return 0; return 0;

View File

@ -51,8 +51,7 @@ __BEGIN_DECLS
O(SYS_MUNMAP, munmap) \ O(SYS_MUNMAP, munmap) \
O(SYS_TTY_CTRL, tty_ctrl) \ O(SYS_TTY_CTRL, tty_ctrl) \
O(SYS_POWEROFF, poweroff) \ O(SYS_POWEROFF, poweroff) \
O(SYS_CHMOD, chmod) \ O(SYS_FCHMODAT, fchmodat) \
O(SYS_FCHMOD, fchmod) \
O(SYS_CREATE_DIR, create_dir) \ O(SYS_CREATE_DIR, create_dir) \
O(SYS_UNLINK, unlink) \ O(SYS_UNLINK, unlink) \
O(SYS_READLINKAT, readlinkat) \ O(SYS_READLINKAT, readlinkat) \

View File

@ -9,12 +9,17 @@ mode_t __umask = 0;
int chmod(const char* path, mode_t mode) int chmod(const char* path, mode_t mode)
{ {
return syscall(SYS_CHMOD, path, mode); return fchmodat(AT_FDCWD, path, mode, 0);
} }
int fchmod(int fildes, mode_t mode) int fchmod(int fildes, mode_t mode)
{ {
return syscall(SYS_FCHMOD, fildes, mode); return fchmodat(fildes, nullptr, mode, 0);
}
int fchmodat(int fildes, const char* path, mode_t mode, int flag)
{
return syscall(SYS_FCHMODAT, fildes, path, mode, flag);
} }
int fstat(int fildes, struct stat* buf) int fstat(int fildes, struct stat* buf)