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:
parent
5887f6bcaa
commit
9e4a87021c
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace Kernel
|
|||
}
|
||||
}
|
||||
|
||||
if (flags & O_EXEC)
|
||||
if (flags & (O_EXEC | O_SEARCH))
|
||||
{
|
||||
if (mode().mode & S_IXOTH)
|
||||
{ }
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 {};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -58,7 +58,7 @@ DIR* fdopendir(int fd)
|
|||
|
||||
DIR* opendir(const char* dirname)
|
||||
{
|
||||
int fd = open(dirname, O_SEARCH);
|
||||
int fd = open(dirname, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return nullptr;
|
||||
return fdopendir(fd);
|
||||
|
|
|
@ -52,6 +52,8 @@ __BEGIN_DECLS
|
|||
#define SYS_SET_PGID 45
|
||||
#define SYS_FCNTL 46
|
||||
#define SYS_NANOSLEEP 47
|
||||
#define SYS_FSTATAT 48
|
||||
#define SYS_STAT 49 // stat/lstat
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
if (flag == AT_SYMLINK_NOFOLLOW)
|
||||
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;
|
||||
return syscall(SYS_FSTATAT, fd, path, buf, flag);
|
||||
}
|
||||
|
||||
int lstat(const char* __restrict path, struct stat* __restrict buf)
|
||||
{
|
||||
int fd = open(path, O_SEARCH | O_NOFOLLOW);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
int ret = fstat(fd, buf);
|
||||
close(fd);
|
||||
return ret;
|
||||
return syscall(SYS_STAT, path, buf, AT_SYMLINK_NOFOLLOW);
|
||||
}
|
||||
|
||||
int stat(const char* __restrict path, struct stat* __restrict buf)
|
||||
{
|
||||
int fd = open(path, O_SEARCH);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
int ret = fstat(fd, buf);
|
||||
close(fd);
|
||||
return ret;
|
||||
return syscall(SYS_STAT, path, buf, 0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue