Kernel: Remove obtain_user_ref and add copy_typed_to and from_user
This commit is contained in:
parent
58fb422161
commit
5c51b82f6a
@ -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));
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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++;
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user