Kernel: Fix directory permissions

We did not care about X bit in directories and instead used only the
R bit for search/read.
This commit is contained in:
Bananymous
2023-09-08 11:46:53 +03:00
parent 660f7cbfeb
commit 39a5c52088
10 changed files with 73 additions and 34 deletions

View File

@@ -34,6 +34,8 @@ namespace Kernel
BAN::ErrorOr<off_t> tell(int) const;
BAN::ErrorOr<void> fstat(int fd, struct stat*) const;
BAN::ErrorOr<void> fstatat(int fd, BAN::StringView path, struct stat* buf, int flag);
BAN::ErrorOr<void> stat(BAN::StringView absolute_path, struct stat* buf, int flag);
BAN::ErrorOr<void> close(int);
void close_all();

View File

@@ -106,6 +106,8 @@ namespace Kernel
BAN::ErrorOr<long> sys_tell(int fd);
BAN::ErrorOr<long> sys_fstat(int fd, struct stat*);
BAN::ErrorOr<long> sys_fstatat(int fd, const char* path, struct stat* buf, int flag);
BAN::ErrorOr<long> sys_stat(const char* path, struct stat* buf, int flag);
BAN::ErrorOr<void> mount(BAN::StringView source, BAN::StringView target);

View File

@@ -38,7 +38,7 @@ namespace Kernel
}
}
if (flags & O_EXEC)
if (flags & (O_EXEC | O_SEARCH))
{
if (mode().mode & S_IXOTH)
{ }

View File

@@ -133,7 +133,7 @@ namespace Kernel
}
else
{
if (!inode->can_access(credentials, O_RDONLY))
if (!inode->can_access(credentials, O_SEARCH))
return BAN::Error::from_errno(EACCES);
inode = TRY(inode->directory_find_inode(path_part));
@@ -152,7 +152,7 @@ namespace Kernel
auto target = TRY(inode->link_target());
if (target.empty())
return BAN::Error::from_errno(ENOENT);
if (target.front() == '/')
{
inode = root_inode();

View File

@@ -179,11 +179,8 @@ namespace Kernel
return m_open_files[fd]->offset;
}
BAN::ErrorOr<void> OpenFileDescriptorSet::fstat(int fd, struct stat* out) const
static void read_stat_from_inode(BAN::RefPtr<Inode> inode, struct stat* out)
{
TRY(validate_fd(fd));
auto inode = m_open_files[fd]->inode;
out->st_dev = inode->dev();
out->st_ino = inode->ino();
out->st_mode = inode->mode().mode;
@@ -197,7 +194,42 @@ namespace Kernel
out->st_ctim = inode->ctime();
out->st_blksize = inode->blksize();
out->st_blocks = inode->blocks();
}
BAN::ErrorOr<void> OpenFileDescriptorSet::fstat(int fd, struct stat* out) const
{
TRY(validate_fd(fd));
read_stat_from_inode(m_open_files[fd]->inode, out);
return {};
}
BAN::ErrorOr<void> OpenFileDescriptorSet::fstatat(int fd, BAN::StringView path, struct stat* out, int flag)
{
if (flag & ~AT_SYMLINK_NOFOLLOW)
return BAN::Error::from_errno(EINVAL);
if (flag == AT_SYMLINK_NOFOLLOW)
flag = O_NOFOLLOW;
BAN::String absolute_path;
TRY(absolute_path.append(TRY(path_of(fd))));
TRY(absolute_path.push_back('/'));
TRY(absolute_path.append(path));
// FIXME: handle O_SEARCH in fd
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flag));
read_stat_from_inode(file.inode, out);
return {};
}
BAN::ErrorOr<void> OpenFileDescriptorSet::stat(BAN::StringView absolute_path, struct stat* out, int flag)
{
if (flag & ~AT_SYMLINK_NOFOLLOW)
return BAN::Error::from_errno(EINVAL);
if (flag == AT_SYMLINK_NOFOLLOW)
flag = O_NOFOLLOW;
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flag));
read_stat_from_inode(file.inode, out);
return {};
}
@@ -256,6 +288,8 @@ namespace Kernel
{
TRY(validate_fd(fd));
auto& open_file = m_open_files[fd];
if (!(open_file->flags & O_RDONLY))
return BAN::Error::from_errno(EACCES);
TRY(open_file->inode->directory_read_next_entries(open_file->offset, list, list_size));
open_file->offset++;
return {};

View File

@@ -630,6 +630,8 @@ namespace Kernel
{
LockGuard _(m_lock);
// FIXME: handle O_SEARCH in fd
BAN::String absolute_path;
TRY(absolute_path.append(TRY(m_open_file_descriptors.path_of(fd))));
TRY(absolute_path.push_back('/'));
@@ -737,6 +739,20 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<long> Process::sys_fstatat(int fd, const char* path, struct stat* buf, int flag)
{
LockGuard _(m_lock);
TRY(m_open_file_descriptors.fstatat(fd, path, buf, flag));
return 0;
}
BAN::ErrorOr<long> Process::sys_stat(const char* path, struct stat* buf, int flag)
{
LockGuard _(m_lock);
TRY(m_open_file_descriptors.stat(TRY(absolute_path_of(path)), buf, flag));
return 0;
}
BAN::ErrorOr<long> Process::sys_read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size)
{
LockGuard _(m_lock);

View File

@@ -185,6 +185,12 @@ namespace Kernel
case SYS_NANOSLEEP:
ret = Process::current().sys_nanosleep((const timespec*)arg1, (timespec*)arg2);
break;
case SYS_FSTATAT:
ret = Process::current().sys_fstatat((int)arg1, (const char*)arg2, (struct stat*)arg3, (int)arg4);
break;
case SYS_STAT:
ret = Process::current().sys_stat((const char*)arg1, (struct stat*)arg2, (int)arg3);
break;
default:
dwarnln("Unknown syscall {}", syscall);
break;