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 5887f6bcaa
commit 9e4a87021c
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<off_t> tell(int) const;
BAN::ErrorOr<void> fstat(int fd, struct stat*) 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); BAN::ErrorOr<void> close(int);
void close_all(); void close_all();

View File

@ -106,6 +106,8 @@ namespace Kernel
BAN::ErrorOr<long> sys_tell(int fd); BAN::ErrorOr<long> sys_tell(int fd);
BAN::ErrorOr<long> sys_fstat(int fd, struct stat*); 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); 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) if (mode().mode & S_IXOTH)
{ } { }

View File

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

View File

@ -179,11 +179,8 @@ namespace Kernel
return m_open_files[fd]->offset; 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_dev = inode->dev();
out->st_ino = inode->ino(); out->st_ino = inode->ino();
out->st_mode = inode->mode().mode; out->st_mode = inode->mode().mode;
@ -197,7 +194,42 @@ namespace Kernel
out->st_ctim = inode->ctime(); out->st_ctim = inode->ctime();
out->st_blksize = inode->blksize(); out->st_blksize = inode->blksize();
out->st_blocks = inode->blocks(); 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 {}; return {};
} }
@ -256,6 +288,8 @@ namespace Kernel
{ {
TRY(validate_fd(fd)); TRY(validate_fd(fd));
auto& open_file = m_open_files[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)); TRY(open_file->inode->directory_read_next_entries(open_file->offset, list, list_size));
open_file->offset++; open_file->offset++;
return {}; return {};

View File

@ -630,6 +630,8 @@ namespace Kernel
{ {
LockGuard _(m_lock); LockGuard _(m_lock);
// FIXME: handle O_SEARCH in fd
BAN::String absolute_path; BAN::String absolute_path;
TRY(absolute_path.append(TRY(m_open_file_descriptors.path_of(fd)))); TRY(absolute_path.append(TRY(m_open_file_descriptors.path_of(fd))));
TRY(absolute_path.push_back('/')); TRY(absolute_path.push_back('/'));
@ -737,6 +739,20 @@ namespace Kernel
return 0; 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) BAN::ErrorOr<long> Process::sys_read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size)
{ {
LockGuard _(m_lock); LockGuard _(m_lock);

View File

@ -185,6 +185,12 @@ namespace Kernel
case SYS_NANOSLEEP: case SYS_NANOSLEEP:
ret = Process::current().sys_nanosleep((const timespec*)arg1, (timespec*)arg2); ret = Process::current().sys_nanosleep((const timespec*)arg1, (timespec*)arg2);
break; 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: default:
dwarnln("Unknown syscall {}", syscall); dwarnln("Unknown syscall {}", syscall);
break; break;

View File

@ -58,7 +58,7 @@ DIR* fdopendir(int fd)
DIR* opendir(const char* dirname) DIR* opendir(const char* dirname)
{ {
int fd = open(dirname, O_SEARCH); int fd = open(dirname, O_RDONLY);
if (fd == -1) if (fd == -1)
return nullptr; return nullptr;
return fdopendir(fd); return fdopendir(fd);

View File

@ -52,6 +52,8 @@ __BEGIN_DECLS
#define SYS_SET_PGID 45 #define SYS_SET_PGID 45
#define SYS_FCNTL 46 #define SYS_FCNTL 46
#define SYS_NANOSLEEP 47 #define SYS_NANOSLEEP 47
#define SYS_FSTATAT 48
#define SYS_STAT 49 // stat/lstat
__END_DECLS __END_DECLS

View File

@ -11,38 +11,15 @@ int fstat(int fildes, struct stat* buf)
int fstatat(int fd, const char* __restrict path, struct stat* __restrict buf, int flag) int fstatat(int fd, const char* __restrict path, struct stat* __restrict buf, int flag)
{ {
if (flag == AT_SYMLINK_NOFOLLOW) return syscall(SYS_FSTATAT, fd, path, buf, flag);
flag = O_NOFOLLOW;
else if (flag)
{
errno = EINVAL;
return -1;
}
int target = openat(fd, path, O_SEARCH | flag);
if (target == -1)
return -1;
int ret = fstat(target, buf);
close(target);
return ret;
} }
int lstat(const char* __restrict path, struct stat* __restrict buf) int lstat(const char* __restrict path, struct stat* __restrict buf)
{ {
int fd = open(path, O_SEARCH | O_NOFOLLOW); return syscall(SYS_STAT, path, buf, AT_SYMLINK_NOFOLLOW);
if (fd == -1)
return -1;
int ret = fstat(fd, buf);
close(fd);
return ret;
} }
int stat(const char* __restrict path, struct stat* __restrict buf) int stat(const char* __restrict path, struct stat* __restrict buf)
{ {
int fd = open(path, O_SEARCH); return syscall(SYS_STAT, path, buf, 0);
if (fd == -1)
return -1;
int ret = fstat(fd, buf);
close(fd);
return ret;
} }