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_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
// 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)
template <typename T> bool copy_typed_from_user(const T* user_ptr, T* ptr)
{
uint64_t phys = VMM::get_physical((uint64_t)address);
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;
return copy_from_user(user_ptr, ptr, sizeof(T));
}
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));
}
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);
return copy_to_user(user_ptr, ptr, sizeof(T));
}

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)
{
struct timespec* ktp = obtain_user_ref(tp);
if (!ktp)
{
context->rax = -EFAULT; // FIXME: Not sure if clock_gettime can return EFAULT.
return;
}
struct timespec ktp;
Task* current_task = Scheduler::current_task();
switch (clock)
{
case CLOCK_REALTIME: {
ms_to_timespec(PIT::ms_since_boot, ktp);
ktp->tv_sec += unix_boot_time;
ms_to_timespec(PIT::ms_since_boot, &ktp);
ktp.tv_sec += unix_boot_time;
break;
}
case CLOCK_MONOTONIC: {
ms_to_timespec(PIT::ms_since_boot, ktp);
ms_to_timespec(PIT::ms_since_boot, &ktp);
break;
}
case CLOCK_PROCTIME: {
ms_to_timespec(current_task->cpu_time, ktp);
ms_to_timespec(current_task->cpu_time, &ktp);
break;
}
default:
release_user_ref(ktp);
context->rax = -EINVAL;
return;
default: context->rax = -EINVAL; return;
}
release_user_ref(ktp);
context->rax = 0;
if (!copy_typed_to_user(tp, &ktp)) context->rax = -EFAULT;
else
context->rax = 0;
return;
}

View File

@ -38,20 +38,19 @@ void sys_getdents(Context* context, int fd, struct luna_dirent* buf, size_t coun
return;
}
auto* kdirent = obtain_user_ref(buf);
if (!kdirent)
luna_dirent dirent;
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;
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);
buf++;
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)
{
struct stat* kstat = obtain_user_ref(buf);
if (!kstat)
{
context->rax = -EFAULT; // FIXME: The manual doesn't say fstat can return EFAULT, but it seems logical here...
return;
}
kstat->st_ino = node->inode;
kstat->st_mode = node->mode | ((1 << (node->type)) * 010000);
kstat->st_size = node->length;
kstat->st_uid = node->uid;
kstat->st_gid = node->gid;
kstat->st_atime = node->atime;
kstat->st_ctime = node->ctime;
kstat->st_mtime = node->mtime;
kstat->st_dev = 0;
kstat->st_nlink = 0;
release_user_ref(kstat);
context->rax = 0;
struct stat stat;
stat.st_ino = node->inode;
stat.st_mode = node->mode | ((1 << (node->type)) * 010000);
stat.st_size = node->length;
stat.st_uid = node->uid;
stat.st_gid = node->gid;
stat.st_atime = node->atime;
stat.st_ctime = node->ctime;
stat.st_mtime = node->mtime;
stat.st_dev = 0;
stat.st_nlink = 0;
if (!copy_typed_to_user(buf, &stat)) context->rax = -EFAULT;
else
context->rax = 0;
}
void sys_fstat(Context* context, int fd, struct stat* buf)