forked from Bananymous/banan-os
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
660f7cbfeb
commit
39a5c52088
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{ }
|
{ }
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 {};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue