Kernel: Cleanup file descriptor validation
This commit is contained in:
parent
ec2c314234
commit
af46b8d9ac
@ -79,4 +79,6 @@ struct Task
|
|||||||
void resume_read();
|
void resume_read();
|
||||||
|
|
||||||
bool is_still_blocking();
|
bool is_still_blocking();
|
||||||
|
|
||||||
|
Descriptor* descriptor_from_fd(int fd, int& error);
|
||||||
};
|
};
|
@ -27,18 +27,14 @@
|
|||||||
|
|
||||||
void sys_fcntl(Context* context, int fd, int command, uintptr_t arg)
|
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();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
Descriptor& file = current_task->files[fd];
|
|
||||||
if (command == FCNTL_DUPFD)
|
if (command == FCNTL_DUPFD)
|
||||||
{
|
{
|
||||||
if ((int)arg < 0 || (int)arg >= TASK_MAX_FDS)
|
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;
|
context->rax = -EMFILE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
current_task->files[dupfd] = file;
|
current_task->files[dupfd] = *file;
|
||||||
context->rax = dupfd;
|
context->rax = dupfd;
|
||||||
kdbgln("fcntl(F_DUPFD): duplicated fd %d, result is %d", fd, dupfd);
|
kdbgln("fcntl(F_DUPFD): duplicated fd %d, result is %d", fd, dupfd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (command == FCNTL_ISTTY)
|
else if (command == FCNTL_ISTTY)
|
||||||
{
|
{
|
||||||
VFS::Node* node = file.node();
|
VFS::Node* node = file->node();
|
||||||
if (node->tty) { context->rax = 1; }
|
if (node->tty) { context->rax = 1; }
|
||||||
else
|
else
|
||||||
context->rax = -ENOTTY;
|
context->rax = -ENOTTY;
|
||||||
@ -79,24 +75,19 @@ void sys_seek(Context* context, int fd, long offset, int whence)
|
|||||||
context->rax = -EINVAL;
|
context->rax = -EINVAL;
|
||||||
return;
|
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;
|
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;
|
long new_offset;
|
||||||
if (whence == SEEK_SET) new_offset = offset;
|
if (whence == SEEK_SET) new_offset = offset;
|
||||||
else if (whence == SEEK_CUR)
|
else if (whence == SEEK_CUR)
|
||||||
new_offset = offset + file.offset();
|
new_offset = offset + file->offset();
|
||||||
else if (whence == SEEK_END)
|
else if (whence == SEEK_END)
|
||||||
new_offset = file.length() + offset;
|
new_offset = file->length() + offset;
|
||||||
else
|
else
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
if (new_offset < 0)
|
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?
|
context->rax = -EINVAL; // FIXME: Is this the right error?
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (new_offset == file.offset())
|
if (new_offset == file->offset())
|
||||||
{
|
{
|
||||||
context->rax = new_offset;
|
context->rax = new_offset;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int result = file.seek(new_offset);
|
int result = file->seek(new_offset);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
context->rax = result;
|
context->rax = result;
|
||||||
@ -126,24 +117,19 @@ void sys_write(Context* context, int fd, size_t size, const char* addr)
|
|||||||
context->rax = -EFAULT;
|
context->rax = -EFAULT;
|
||||||
return;
|
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;
|
context->rax = -EBADF;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Task* current_task = Scheduler::current_task();
|
ssize_t result = file->write(size, (const char*)VMM::get_physical((uint64_t)addr));
|
||||||
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));
|
|
||||||
context->rax = (size_t)result;
|
context->rax = (size_t)result;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -213,52 +199,50 @@ void sys_read(Context* context, int fd, size_t size, char* buffer)
|
|||||||
context->rax = -EFAULT;
|
context->rax = -EFAULT;
|
||||||
return;
|
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;
|
context->rax = -EBADF;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Task* current_task = Scheduler::current_task();
|
if (VFS::would_block(file->node()))
|
||||||
if (!current_task->files[fd].is_open() || !current_task->files[fd].can_read())
|
|
||||||
{
|
{
|
||||||
context->rax = -EBADF;
|
if (!file->able_to_block())
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (VFS::would_block(current_task->files[fd].node()))
|
|
||||||
{
|
|
||||||
if (!current_task->files[fd].able_to_block())
|
|
||||||
{
|
{
|
||||||
context->rax = -EAGAIN;
|
context->rax = -EAGAIN;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Task* current_task = Scheduler::current_task();
|
||||||
current_task->state = current_task->Blocking;
|
current_task->state = current_task->Blocking;
|
||||||
current_task->blocking_read_info.fd = fd;
|
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.buf = (char*)VMM::get_physical((uint64_t)buffer); // FIXME: Handle errors.
|
||||||
current_task->blocking_read_info.size = size;
|
current_task->blocking_read_info.size = size;
|
||||||
return Scheduler::task_yield(context);
|
return Scheduler::task_yield(context);
|
||||||
}
|
}
|
||||||
ssize_t result = current_task->files[fd].read(
|
ssize_t result =
|
||||||
size, (char*)VMM::get_physical((uint64_t)buffer)); // FIXME: Handle errors, and big buffers which may not be
|
file->read(size, (char*)VMM::get_physical((uint64_t)buffer)); // FIXME: Handle errors, and big buffers which may
|
||||||
// across continuous physical pages.
|
// not be across continuous physical pages.
|
||||||
context->rax = (size_t)result;
|
context->rax = (size_t)result;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_close(Context* context, int fd)
|
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;
|
context->rax = -err;
|
||||||
return;
|
|
||||||
}
|
|
||||||
Task* current_task = Scheduler::current_task();
|
|
||||||
if (!current_task->files[fd].is_open())
|
|
||||||
{
|
|
||||||
context->rax = -EBADF;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
kdbgln("close(): releasing file descriptor %d", fd);
|
kdbgln("close(): releasing file descriptor %d", fd);
|
||||||
current_task->files[fd].close();
|
file->close();
|
||||||
context->rax = 0;
|
context->rax = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "thread/Task.h"
|
#include "thread/Task.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
|
#include "std/errno.h"
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
|
|
||||||
void Task::restore_context(Context* context)
|
void Task::restore_context(Context* context)
|
||||||
@ -83,3 +84,18 @@ bool Task::is_still_blocking()
|
|||||||
{
|
{
|
||||||
return VFS::would_block(files[blocking_read_info.fd].node());
|
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];
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user