Kernel: Remove obtain_user_ref and add copy_typed_to and from_user

This commit is contained in:
apio 2022-11-12 12:08:26 +01:00
parent 58fb422161
commit 5c51b82f6a
4 changed files with 35 additions and 68 deletions

View File

@ -19,33 +19,12 @@ bool validate_user_write(uintptr_t address, size_t size);
bool copy_from_user(const void* user_ptr, void* ptr, size_t size); bool copy_from_user(const void* user_ptr, void* ptr, size_t size);
bool copy_to_user(void* user_ptr, const void* ptr, size_t size); bool copy_to_user(void* user_ptr, const void* ptr, size_t size);
// FIXME: Map the physical addresses into kernel address space. Right now, something overwrites KernelHeap and crashes template <typename T> bool copy_typed_from_user(const T* user_ptr, T* ptr)
// it, so that's not really possible. But it should be done in the future.
template <typename T, unsigned long S = sizeof(T), typename V> T* user_address_to_typed_pointer(V address)
{ {
uint64_t phys = VMM::get_physical((uint64_t)address); return copy_from_user(user_ptr, ptr, sizeof(T));
if (phys == (uint64_t)-1)
{
kinfoln("warning: user pointer is not mapped in its address space");
return nullptr;
}
// return (T*)MemoryManager::get_unaligned_mappings((void*)phys, Utilities::get_blocks_from_size(PAGE_SIZE, S),
// MAP_READ_WRITE);
return (T*)phys;
} }
template <typename T, unsigned long S = sizeof(T)> void free_user_typed_pointer(T*) template <typename T> bool copy_typed_to_user(T* user_ptr, const T* ptr)
{ {
// MemoryManager::release_unaligned_mappings(ptr, Utilities::get_blocks_from_size(PAGE_SIZE, S)); return copy_to_user(user_ptr, ptr, sizeof(T));
}
template <typename T> T* obtain_user_ref(T* user_ptr)
{
return user_address_to_typed_pointer<T>(user_ptr);
}
template <typename T> void release_user_ref(T* ptr)
{
return free_user_typed_pointer(ptr);
} }

View File

@ -33,35 +33,28 @@ static void ms_to_timespec(long ms, struct timespec* tv)
void sys_clock_gettime(Context* context, int clock, struct timespec* tp) void sys_clock_gettime(Context* context, int clock, struct timespec* tp)
{ {
struct timespec* ktp = obtain_user_ref(tp); struct timespec ktp;
if (!ktp)
{
context->rax = -EFAULT; // FIXME: Not sure if clock_gettime can return EFAULT.
return;
}
Task* current_task = Scheduler::current_task(); Task* current_task = Scheduler::current_task();
switch (clock) switch (clock)
{ {
case CLOCK_REALTIME: { case CLOCK_REALTIME: {
ms_to_timespec(PIT::ms_since_boot, ktp); ms_to_timespec(PIT::ms_since_boot, &ktp);
ktp->tv_sec += unix_boot_time; ktp.tv_sec += unix_boot_time;
break; break;
} }
case CLOCK_MONOTONIC: { case CLOCK_MONOTONIC: {
ms_to_timespec(PIT::ms_since_boot, ktp); ms_to_timespec(PIT::ms_since_boot, &ktp);
break; break;
} }
case CLOCK_PROCTIME: { case CLOCK_PROCTIME: {
ms_to_timespec(current_task->cpu_time, ktp); ms_to_timespec(current_task->cpu_time, &ktp);
break; break;
} }
default: default: context->rax = -EINVAL; return;
release_user_ref(ktp);
context->rax = -EINVAL;
return;
} }
release_user_ref(ktp); if (!copy_typed_to_user(tp, &ktp)) context->rax = -EFAULT;
context->rax = 0; else
context->rax = 0;
return; return;
} }

View File

@ -38,20 +38,19 @@ void sys_getdents(Context* context, int fd, struct luna_dirent* buf, size_t coun
return; return;
} }
auto* kdirent = obtain_user_ref(buf); luna_dirent dirent;
if (!kdirent)
dirent.total = node->length;
dirent.offset = dir.offset();
dirent.inode = entry->inode;
strlcpy(dirent.name, entry->name, sizeof(dirent.name));
if (!copy_typed_to_user(buf, &dirent))
{ {
context->rax = -EFAULT; context->rax = -EFAULT;
return; return;
} }
kdirent->total = node->length;
kdirent->offset = dir.offset();
kdirent->inode = entry->inode;
strlcpy(kdirent->name, entry->name, sizeof(kdirent->name));
release_user_ref(kdirent);
dir.seek(dir.offset() + 1); dir.seek(dir.offset() + 1);
buf++; buf++;
nread++; nread++;

View File

@ -24,24 +24,20 @@ struct stat // FIXME: This struct is quite stubbed out.
void do_stat(Context* context, VFS::Node* node, struct stat* buf) void do_stat(Context* context, VFS::Node* node, struct stat* buf)
{ {
struct stat* kstat = obtain_user_ref(buf); struct stat stat;
if (!kstat) stat.st_ino = node->inode;
{ stat.st_mode = node->mode | ((1 << (node->type)) * 010000);
context->rax = -EFAULT; // FIXME: The manual doesn't say fstat can return EFAULT, but it seems logical here... stat.st_size = node->length;
return; stat.st_uid = node->uid;
} stat.st_gid = node->gid;
kstat->st_ino = node->inode; stat.st_atime = node->atime;
kstat->st_mode = node->mode | ((1 << (node->type)) * 010000); stat.st_ctime = node->ctime;
kstat->st_size = node->length; stat.st_mtime = node->mtime;
kstat->st_uid = node->uid; stat.st_dev = 0;
kstat->st_gid = node->gid; stat.st_nlink = 0;
kstat->st_atime = node->atime; if (!copy_typed_to_user(buf, &stat)) context->rax = -EFAULT;
kstat->st_ctime = node->ctime; else
kstat->st_mtime = node->mtime; context->rax = 0;
kstat->st_dev = 0;
kstat->st_nlink = 0;
release_user_ref(kstat);
context->rax = 0;
} }
void sys_fstat(Context* context, int fd, struct stat* buf) void sys_fstat(Context* context, int fd, struct stat* buf)