Compare commits

..

3 Commits

Author SHA1 Message Date
cedefaf93d libc: Exit with -errno if we fail initialization 2022-11-05 11:56:31 +01:00
9ab3ab7c40 Kernel: Show init's exit status before restarting 2022-11-05 11:56:16 +01:00
b63a9f5ba9 Kernel: Improve strdup_from_user and add copy to and from user
Still a bit funky, that's why we're not using it in read() and write() yet.
2022-11-05 11:54:55 +01:00
4 changed files with 159 additions and 8 deletions

View File

@ -16,6 +16,9 @@ bool validate_user_writable_page(uintptr_t address);
bool validate_user_read(uintptr_t address, size_t size); bool validate_user_read(uintptr_t address, size_t size);
bool validate_user_write(uintptr_t address, size_t size); 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 // 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. // it, so that's not really possible. But it should be done in the future.

View File

@ -1,14 +1,44 @@
#include "sys/UserMemory.h" #include "sys/UserMemory.h"
#include "memory/Memory.h" #include "memory/Memory.h"
#include "memory/MemoryManager.h"
#include "std/stdlib.h"
#include "std/string.h" #include "std/string.h"
#include "utils/Addresses.h" #include "utils/Addresses.h"
char* strdup_from_user( struct dynamic_string
const char* user_string) // FIXME: This function is a little hacky. Use the obtain_user_ref and similar functions.
{ {
uint64_t phys = VMM::get_physical((uint64_t)user_string); char* buf;
if (phys == (uint64_t)-1) { return nullptr; } long capacity;
return strdup((const char*)phys); long size;
};
bool dynamic_expand(dynamic_string* str, long new_capacity)
{
char* buffer = (char*)krealloc(str->buf, new_capacity);
if (!buffer) { return false; }
str->buf = buffer;
str->capacity = new_capacity;
return true;
}
bool dynamic_push(dynamic_string* str, char c)
{
if (str->size == str->capacity)
{
if (!dynamic_expand(str, str->capacity + 16)) return false;
}
str->buf[str->size] = c;
str->size++;
return true;
}
bool dynamic_init(dynamic_string* str)
{
str->buf = (char*)kmalloc(10);
if (!str->buf) return false;
str->capacity = 10;
str->size = 0;
return true;
} }
bool validate_user_readable_page(uintptr_t address) bool validate_user_readable_page(uintptr_t address)
@ -29,6 +59,54 @@ bool validate_user_writable_page(uintptr_t address)
return false; return false;
} }
char* strdup_from_user(const char* user_string)
{
uintptr_t user_ptr = (uintptr_t)user_string;
auto aligned = round_down_to_nearest_page(user_ptr);
char* ptr = nullptr;
uintptr_t index = 0;
if (aligned != user_ptr) // Otherwise, we already do this check below.
{
if (!validate_user_readable_page(aligned)) return nullptr;
ptr = (char*)MemoryManager::get_mapping((void*)VMM::get_physical(aligned), 0);
index = user_ptr - aligned;
}
dynamic_string str;
if (!dynamic_init(&str))
{
if (ptr) MemoryManager::release_mapping(ptr);
return nullptr;
}
while (true) // FIXME: set a limit for this and fail with ENAMETOOLONG otherwise.
{
if (user_ptr % PAGE_SIZE == 0)
{
index = 0;
if (ptr) MemoryManager::release_mapping(ptr);
if (!validate_user_readable_page(user_ptr))
{
kfree(str.buf);
return nullptr;
}
ptr = (char*)MemoryManager::get_mapping((void*)VMM::get_physical(user_ptr), 0);
}
char c = ptr[index];
if (!dynamic_push(&str, c))
{
MemoryManager::release_mapping(ptr);
kfree(str.buf);
return nullptr;
}
if (!c) // We reached the null terminator!!
{
MemoryManager::release_mapping(ptr);
return str.buf;
}
user_ptr++;
index++;
}
}
bool validate_user_read(uintptr_t address, size_t size) bool validate_user_read(uintptr_t address, size_t size)
{ {
auto aligned = round_down_to_nearest_page(address); auto aligned = round_down_to_nearest_page(address);
@ -64,3 +142,71 @@ bool validate_user_write(uintptr_t address, size_t size)
} }
return true; return true;
} }
bool do_copy_from_user(const char* uptr, char* ptr, size_t size)
{
uintptr_t user_ptr = (uintptr_t)uptr;
auto aligned = round_down_to_nearest_page(user_ptr);
char* mapping = nullptr;
uintptr_t index = 0;
if (aligned != user_ptr) // Otherwise, we already do this check below.
{
if (!validate_user_readable_page(aligned)) return false;
mapping = (char*)MemoryManager::get_mapping((void*)VMM::get_physical(aligned), 0);
index = user_ptr - aligned;
}
while (size--)
{
if (user_ptr % PAGE_SIZE == 0)
{
if (mapping) MemoryManager::release_mapping(mapping);
index = 0;
if (!validate_user_readable_page(user_ptr)) return false;
mapping = (char*)MemoryManager::get_mapping((void*)VMM::get_physical(user_ptr), 0);
}
*ptr = mapping[index];
user_ptr++;
ptr++;
index++;
}
return true;
}
bool do_copy_to_user(char* uptr, const char* ptr, size_t size)
{
uintptr_t user_ptr = (uintptr_t)uptr;
auto aligned = round_down_to_nearest_page(user_ptr);
char* mapping = nullptr;
uintptr_t index = 0;
if (aligned != user_ptr) // Otherwise, we already do this check below.
{
if (!validate_user_writable_page(aligned)) return false;
mapping = (char*)MemoryManager::get_mapping((void*)VMM::get_physical(aligned));
index = user_ptr - aligned;
}
while (size--)
{
if (user_ptr % PAGE_SIZE == 0)
{
if (mapping) MemoryManager::release_mapping(mapping);
index = 0;
if (!validate_user_writable_page(user_ptr)) return false;
mapping = (char*)MemoryManager::get_mapping((void*)VMM::get_physical(user_ptr));
}
mapping[index] = *ptr;
user_ptr++;
ptr++;
index++;
}
return true;
}
bool copy_from_user(const void* user_ptr, void* ptr, size_t size)
{
return do_copy_from_user((const char*)user_ptr, (char*)ptr, size);
}
bool copy_to_user(void* user_ptr, const void* ptr, size_t size)
{
return do_copy_to_user((char*)user_ptr, (const char*)ptr, size);
}

View File

@ -196,7 +196,8 @@ long Scheduler::load_user_task(const char* filename)
new_task->regs.rip = image->entry; new_task->regs.rip = image->entry;
new_task->image = image; new_task->image = image;
new_task->allocated_stack = (uint64_t)MemoryManager::get_pages_at( new_task->allocated_stack = (uint64_t)MemoryManager::get_pages_at(
0x100000, TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER | MAP_AS_OWNED_BY_TASK); // 16 KB is enough for everyone, right? 0x100000, TASK_PAGES_IN_STACK,
MAP_READ_WRITE | MAP_USER | MAP_AS_OWNED_BY_TASK); // 16 KB is enough for everyone, right?
if (!new_task->allocated_stack) if (!new_task->allocated_stack)
{ {
new_task->address_space.destroy(); new_task->address_space.destroy();
@ -291,6 +292,7 @@ void sched_common_exit(Context* context, int64_t status)
} }
else else
{ {
kinfoln("PID 1 exited with code %ld", status);
#ifndef RUN_TEST_AS_INIT #ifndef RUN_TEST_AS_INIT
reboot(); reboot();
#else #else

View File

@ -47,8 +47,8 @@ static void check_for_file(int fd, FILE** target_stream, const char* path, const
{ {
if (errno == EBADF) *target_stream = fopen(path, mode); if (errno == EBADF) *target_stream = fopen(path, mode);
else else
exit(-127); exit(-errno);
if (!*target_stream) exit(-127); if (!*target_stream) exit(-errno);
errno = 0; errno = 0;
} }
else { *target_stream = fdopen(fd, mode); } else { *target_stream = fdopen(fd, mode); }