Kernel: Cleanup file descriptor validation

This commit is contained in:
apio 2022-10-25 18:35:17 +02:00
parent ec2c314234
commit af46b8d9ac
3 changed files with 60 additions and 58 deletions

View File

@ -79,4 +79,6 @@ struct Task
void resume_read();
bool is_still_blocking();
Descriptor* descriptor_from_fd(int fd, int& error);
};

View File

@ -27,18 +27,14 @@
void sys_fcntl(Context* context, int fd, int command, uintptr_t arg)
{
if (fd >= TASK_MAX_FDS || fd < 0)
{
context->rax = -EBADF;
return;
}
Task* current_task = Scheduler::current_task();
if (!current_task->files[fd].is_open())
int err;
Descriptor* file = current_task->descriptor_from_fd(fd, err);
if (!file)
{
context->rax = -EBADF;
context->rax = -err;
return;
}
Descriptor& file = current_task->files[fd];
if (command == FCNTL_DUPFD)
{
if ((int)arg < 0 || (int)arg >= TASK_MAX_FDS)
@ -52,14 +48,14 @@ void sys_fcntl(Context* context, int fd, int command, uintptr_t arg)
context->rax = -EMFILE;
return;
}
current_task->files[dupfd] = file;
current_task->files[dupfd] = *file;
context->rax = dupfd;
kdbgln("fcntl(F_DUPFD): duplicated fd %d, result is %d", fd, dupfd);
return;
}
else if (command == FCNTL_ISTTY)
{
VFS::Node* node = file.node();
VFS::Node* node = file->node();
if (node->tty) { context->rax = 1; }
else
context->rax = -ENOTTY;
@ -79,24 +75,19 @@ void sys_seek(Context* context, int fd, long offset, int whence)
context->rax = -EINVAL;
return;
}
if (fd >= TASK_MAX_FDS || fd < 0)
int err;
Descriptor* file = Scheduler::current_task()->descriptor_from_fd(fd, err);
if (!file)
{
context->rax = -EBADF;
context->rax = -err;
return;
}
Task* current_task = Scheduler::current_task();
if (!current_task->files[fd].is_open())
{
context->rax = -EBADF;
return;
}
Descriptor& file = current_task->files[fd];
long new_offset;
if (whence == SEEK_SET) new_offset = offset;
else if (whence == SEEK_CUR)
new_offset = offset + file.offset();
new_offset = offset + file->offset();
else if (whence == SEEK_END)
new_offset = file.length() + offset;
new_offset = file->length() + offset;
else
__builtin_unreachable();
if (new_offset < 0)
@ -104,12 +95,12 @@ void sys_seek(Context* context, int fd, long offset, int whence)
context->rax = -EINVAL; // FIXME: Is this the right error?
return;
}
if (new_offset == file.offset())
if (new_offset == file->offset())
{
context->rax = new_offset;
return;
}
int result = file.seek(new_offset);
int result = file->seek(new_offset);
if (result < 0)
{
context->rax = result;
@ -126,24 +117,19 @@ void sys_write(Context* context, int fd, size_t size, const char* addr)
context->rax = -EFAULT;
return;
}
if (fd >= TASK_MAX_FDS || fd < 0)
int err;
Descriptor* file = Scheduler::current_task()->descriptor_from_fd(fd, err);
if (!file)
{
context->rax = -err;
return;
}
if (!file->can_write())
{
context->rax = -EBADF;
return;
}
Task* current_task = Scheduler::current_task();
if (!current_task->files[fd].is_open())
{
context->rax = -EBADF;
return;
}
Descriptor& file = current_task->files[fd];
if (!file.can_write())
{
context->rax = -EBADF;
return;
}
ssize_t result = file.write(size, (const char*)VMM::get_physical((uint64_t)addr));
ssize_t result = file->write(size, (const char*)VMM::get_physical((uint64_t)addr));
context->rax = (size_t)result;
return;
}
@ -213,52 +199,50 @@ void sys_read(Context* context, int fd, size_t size, char* buffer)
context->rax = -EFAULT;
return;
}
if (fd >= TASK_MAX_FDS || fd < 0)
int err;
Descriptor* file = Scheduler::current_task()->descriptor_from_fd(fd, err);
if (!err)
{
context->rax = -err;
return;
}
if (!file->is_open() || !file->can_read())
{
context->rax = -EBADF;
return;
}
Task* current_task = Scheduler::current_task();
if (!current_task->files[fd].is_open() || !current_task->files[fd].can_read())
if (VFS::would_block(file->node()))
{
context->rax = -EBADF;
return;
}
if (VFS::would_block(current_task->files[fd].node()))
{
if (!current_task->files[fd].able_to_block())
if (!file->able_to_block())
{
context->rax = -EAGAIN;
return;
}
Task* current_task = Scheduler::current_task();
current_task->state = current_task->Blocking;
current_task->blocking_read_info.fd = fd;
current_task->blocking_read_info.buf = (char*)VMM::get_physical((uint64_t)buffer); // FIXME: Handle errors.
current_task->blocking_read_info.size = size;
return Scheduler::task_yield(context);
}
ssize_t result = current_task->files[fd].read(
size, (char*)VMM::get_physical((uint64_t)buffer)); // FIXME: Handle errors, and big buffers which may not be
// across continuous physical pages.
ssize_t result =
file->read(size, (char*)VMM::get_physical((uint64_t)buffer)); // FIXME: Handle errors, and big buffers which may
// not be across continuous physical pages.
context->rax = (size_t)result;
return;
}
void sys_close(Context* context, int fd)
{
if (fd >= TASK_MAX_FDS || fd < 0)
int err;
Descriptor* file = Scheduler::current_task()->descriptor_from_fd(fd, err);
if (!err)
{
context->rax = -EBADF;
return;
}
Task* current_task = Scheduler::current_task();
if (!current_task->files[fd].is_open())
{
context->rax = -EBADF;
context->rax = -err;
return;
}
kdbgln("close(): releasing file descriptor %d", fd);
current_task->files[fd].close();
file->close();
context->rax = 0;
return;
}

View File

@ -3,6 +3,7 @@
#include "thread/Task.h"
#include "log/Log.h"
#include "memory/VMM.h"
#include "std/errno.h"
#include "std/string.h"
void Task::restore_context(Context* context)
@ -82,4 +83,19 @@ void Task::resume_read()
bool Task::is_still_blocking()
{
return VFS::would_block(files[blocking_read_info.fd].node());
}
Descriptor* Task::descriptor_from_fd(int fd, int& error)
{
if (fd < 0 || fd >= TASK_MAX_FDS)
{
error = EBADF;
return nullptr;
}
if (!files[fd].is_open())
{
error = EBADF;
return nullptr;
}
return &files[fd];
}