slightly leaking exec

This commit is contained in:
2024-03-24 13:19:27 +01:00
parent fb2c56594f
commit ad5a161c59
13 changed files with 142 additions and 39 deletions

View File

@@ -38,7 +38,7 @@ void idt_set_descriptor(uint8_t vector, void (*isr)(), uint8_t flags)
descriptor->isr_low = (uint64_t) isr & 0xFFFF;
descriptor->kernel_cs = Arch::GDT::gdt_code.selector();
descriptor->ist = 1;
descriptor->ist = 0;
descriptor->attributes = flags;
descriptor->isr_mid = ((uint64_t) isr >> 16) & 0xFFFF;
descriptor->isr_high = ((uint64_t) isr >> 32) & 0xFFFFFFFF;

View File

@@ -12,6 +12,7 @@
#include "String.hpp"
#include "TestTemplates.hpp"
#include "TtyManager.hpp"
#include "VFSApi.hpp"
#include "VFSGlobals.hpp"
#include "VFSTester.hpp"
#include "VMA.hpp"
@@ -152,15 +153,24 @@ void ktask_main() {
(new Task(Task::TaskMode::TASKMODE_KERN, vfs_tester, "vfs_tester"))->start();
for (int i = 0; i < saved_modules_size; i++) {
GlobalTtyManager.all_tty_putstr("Starting ");
GlobalTtyManager.all_tty_putstr(saved_modules_names[i]);
GlobalTtyManager.all_tty_putchar('\n');
VFSApi::touch(StrToPath(saved_modules_names[i]));
FDT::FD fd = VFSApi::open(StrToPath(saved_modules_names[i]));
File *f = VFSApi::get(fd);
f->write(saved_modules_data[i], saved_modules_data_size[i]);
Task *utask = new Task(Task::TaskMode::TASKMODE_USER, (void (*)()) 0x00020000, saved_modules_names[i]);
assert(saved_modules_size > 0);
utask->_vma->mmap_phys((void *) 0x00020000, (void *) KERN_V2P(saved_modules_data[i]),
max_saved_module_file_size, PAGE_USER | PAGE_RW);
utask->start();
if (strcmp(saved_modules_names[i], "/init") == 0) {
GlobalTtyManager.all_tty_putstr("Starting ");
GlobalTtyManager.all_tty_putstr(saved_modules_names[i]);
GlobalTtyManager.all_tty_putchar('\n');
Task *utask = new Task(Task::TaskMode::TASKMODE_USER, (void (*)()) 0x00020000, saved_modules_names[i]);
assert(saved_modules_size > 0);
utask->_vma->mmap_phys((void *) 0x00020000, (void *) KERN_V2P(saved_modules_data[i]),
max_saved_module_file_size, PAGE_USER | PAGE_RW);
utask->start();
}
VFSApi::close(fd);
}
}

View File

@@ -14,6 +14,7 @@ static volatile struct limine_module_request module_request = {
limine_file saved_modules[max_saved_modules];
char saved_modules_data[max_saved_modules][max_saved_module_file_size] __attribute__((aligned(4096)));
uint64_t saved_modules_data_size[max_saved_modules] __attribute__((aligned(4096)));
char saved_modules_names[max_saved_modules][max_saved_module_name] __attribute__((aligned(4096)));
unsigned saved_modules_size = 0;
@@ -25,5 +26,6 @@ void limine_modules_save() {
assert(saved_modules[i].size < max_saved_module_file_size);
memcpy(saved_modules_data[i], saved_modules[i].address, saved_modules[i].size);
memcpy(saved_modules_names[i], saved_modules[i].path, max_saved_module_name);
saved_modules_data_size[i] = saved_modules[i].size;
}
}

View File

@@ -16,6 +16,7 @@ static constexpr unsigned max_saved_module_name = 256;
extern unsigned saved_modules_size;
extern limine_file saved_modules[max_saved_modules];
extern char saved_modules_data[max_saved_modules][max_saved_module_file_size] __attribute__((aligned(4096)));
extern uint64_t saved_modules_data_size[max_saved_modules] __attribute__((aligned(4096)));
extern char saved_modules_names[max_saved_modules][max_saved_module_name] __attribute__((aligned(4096)));
#endif //OS2_LIMINE_MODULES_HPP

View File

@@ -58,13 +58,11 @@ void *AddressSpace::virt2real(void *virt) {
uint64_t *pdpeb = (uint64_t *) HHDM_P2V((*pml4e & 0x000FFFFFFFFFF000ULL));
uint64_t *pdpee = pdpeb + pdpei;
if (!((*pdpee) & PAGE_PRESENT)) return 0;
// Calculations here might be incorrect
if (*pdpee & PAGE_PS) return (void *) ((*pdpee & 0x000FFFFFFFFFF000ULL) | ((uint64_t) virt & 0x00000003FFFF000ULL));
uint64_t *pdeb = (uint64_t *) HHDM_P2V((*pdpee & 0x000FFFFFFFFFF000ULL));
uint64_t *pdee = pdeb + pdei;
if (!((*pdee) & PAGE_PRESENT)) return 0;
// Calculations here might be incorrect
if (*pdee & PAGE_PS) return (void *) ((*pdee & 0x000FFFFFFFFFF000ULL) | ((uint64_t) virt & 0x0000000001FF000ULL));
uint64_t *ptsb = (uint64_t *) HHDM_P2V((*pdee & 0x000FFFFFFFFFF000ULL));

View File

@@ -3,6 +3,8 @@
//
#include "syscalls.hpp"
#include "VFSApi.hpp"
#include "VMA.hpp"
#include "syscalls_defs.h"
#include <cstdint>
@@ -16,6 +18,7 @@
#include "FDT.hpp"
#include "File.hpp"
#include "memman.hpp"
#include "paging.hpp"
#include "task.hpp"
#include "timer.hpp"
@@ -162,6 +165,29 @@ uint64_t syscall_print_mem() {
return 0;
}
uint64_t syscall_execve(const char *pathname, char *const argv[], char *const envp[]) {
// Just copy for now;
FDT::FD fd = VFSApi::open(StrToPath(pathname));
if (fd == -1) return -1;
File *f = VFSApi::get(fd);
Task *utask = new Task(Task::TaskMode::TASKMODE_USER, (void (*)()) 0x00020000, pathname);
char *mapped = static_cast<char *>(utask->_vma->mmap_mem((void *) 0x00020000, f->size(), 0, PAGE_USER | PAGE_RW));
assert(mapped == (void *) 0x00020000);
char *target = mapped + f->size();
for (; mapped < target; mapped += PAGE_SIZE) {
char buf[PAGE_SIZE];
uint64_t read = f->read(buf, PAGE_SIZE);
memcpy((char *) HHDM_P2V(utask->_addressSpace->virt2real(mapped)), buf, read);
}
VFSApi::close(fd);
utask->start();
return 0;
}
extern "C" uint64_t syscall_impl(uint64_t id_rdi, uint64_t a1_rsi, uint64_t a2_rdx, uint64_t a3_rcx) {
assert2(are_interrupts_enabled(), "why wouldn't they be?");
switch (id_rdi) {
@@ -185,7 +211,8 @@ extern "C" uint64_t syscall_impl(uint64_t id_rdi, uint64_t a1_rsi, uint64_t a2_r
return syscall_write(a1_rsi, reinterpret_cast<const char *>(a2_rdx), a3_rcx);
case SYSCALL_LSEEK_ID:
return syscall_lseek(a1_rsi, a2_rdx, a3_rcx);
case SYSCALL_EXECVE_ID:
return syscall_execve(reinterpret_cast<const char *>(a1_rsi), reinterpret_cast<char *const *>(a2_rdx), reinterpret_cast<char *const *>(a3_rcx));
case SYSCALL_OPENDIR_ID:
case SYSCALL_READDIR_ID:
case SYSCALL_CLOSEDIR_ID:

View File

@@ -9,7 +9,7 @@ TIMEOUT=1
# Path to the kernel to boot. boot:/// represents the partition on which limine.cfg is located.
KERNEL_PATH=boot:///os2.elf
MODULE_PATH=boot:///hello
MODULE_PATH=boot:///init
MODULE_PATH=boot:///hello2
# Same thing, but without KASLR.
@@ -20,5 +20,5 @@ TIMEOUT=1
KASLR=no
KERNEL_PATH=boot:///os2.elf
MODULE_PATH=boot:///hello
MODULE_PATH=boot:///init
MODULE_PATH=boot:///hello2

View File

@@ -14,12 +14,48 @@
VMA::VMA(AddressSpace *space) : space(space) {
LockGuard l(regions_lock);
regions.add(0x10000, {0x10000, 0xFFF8000000000000ULL - 0x20000, true});
regions.add(0x1000, {0x1000, 0xFFF8000000000000ULL - 0x20000, EntryType::FREE});
}
void VMA::mark_taken(void *addr, size_t length) {
}
VMA::ListEntry *VMA::get_entry(uintptr_t v_addr, size_t length) {
ListEntry *found = nullptr;
{
LockGuard l(regions_lock);
// Find the region with start before or at v_addr
if (v_addr) {
found = &regions.find(v_addr)->data;
// Check if it fits
if (found->length < length || found->type != EntryType::FREE) found = nullptr;
}
// Otherwise try to find something else
if (!found)
for (auto &n: regions) {
if (n.data.type == EntryType::FREE && n.data.length >= length) {
found = &n.data;
break;
}
}
if (!found)
return nullptr;
ListEntry tmpFound = *found;
regions.erase(found->begin);
// If our region actually starts before what we requested, then cut it up
if ((tmpFound.begin < v_addr) && (tmpFound.length > ((v_addr - tmpFound.begin) + length))) {
regions.add(tmpFound.begin, {tmpFound.begin, v_addr - tmpFound.begin, EntryType::FREE});
tmpFound.begin = v_addr;
tmpFound.length -= v_addr - tmpFound.begin;
}
regions.add(tmpFound.begin + length, {tmpFound.begin + length, tmpFound.length - length, EntryType::FREE});
found = &regions.add(tmpFound.begin, {tmpFound.begin, length, EntryType::ANON})->data;
}
return found;
}
void VMA::map_kern() {
LockGuard l(space_lock);
for (uintptr_t i = 256; i < 512; i++) {
@@ -31,39 +67,30 @@ void *VMA::mmap_phys(void *v_addr, void *real_addr, size_t length, int flags) {
LockGuard l(space_lock);
assert((((uintptr_t) v_addr) & PAGE_SIZE) == 0);
ListEntry *entry = get_entry(reinterpret_cast<uintptr_t>(v_addr), length);
if (!entry) return nullptr;
entry->type = EntryType::PHYS;
for (size_t i = 0; i < length; i += PAGE_SIZE) {
space->map(v_addr + i, real_addr + i, flags);
space->map((char *) v_addr + i, (char *) real_addr + i, flags);
}
return v_addr;
}
void *VMA::mmap_mem(void *v_addr, size_t length, int prot, int flags) {
size_t origlen = length;
if ((length & (PAGE_SIZE - 1)) != 0) {
length += PAGE_SIZE - 1;
length &= ~(PAGE_SIZE - 1);
}
assert((length & (PAGE_SIZE - 1)) == 0);
uint64_t page_len = length / PAGE_SIZE;
assert(length >= origlen);
std::optional<ListEntry> found;
{
LockGuard l(regions_lock);
uint64_t page_len = length / PAGE_SIZE;
if (v_addr) {
found = regions.find((uintptr_t) v_addr)->data;
} else {
for (auto &n: regions) {
if (n.data.available && n.data.length >= length) {
found = n.data;
break;
}
}
}
if (!found) return nullptr;
regions.erase(found->begin);
regions.add(found->begin + length, {found->begin + length, found->length - length, true});
regions.add(found->begin, {found->begin, length, false});
}
//
ListEntry *found = get_entry(reinterpret_cast<uintptr_t>(v_addr), length);
if (!found) return nullptr;
for (int i = 0; i < page_len; i++) {
void *p = get4k();
@@ -77,3 +104,14 @@ void *VMA::mmap_mem(void *v_addr, size_t length, int prot, int flags) {
int VMA::munmap(void *addr, size_t length) {
return 0;
}
VMA::~VMA() {
for (const auto &e: regions) {
if (e.data.type == EntryType::ANON) {
assert((e.data.length & (PAGE_SIZE - 1)) == 0);
uint64_t page_len = e.data.length / PAGE_SIZE;
for (int i = 0; i < page_len; i++) {
free4k((void *) HHDM_P2V(space->virt2real(reinterpret_cast<void *>(e.data.begin + i * PAGE_SIZE))));
}
}
}
}

View File

@@ -16,8 +16,13 @@ class AddressSpace;
class VMA {
public:
VMA(AddressSpace *space);
~VMA();
VMA(const VMA &) = delete;
VMA(VMA &&) = delete;
VMA &operator=(const VMA &) = delete;
VMA &operator=(VMA &&) = delete;
void mark_taken(void *addr, size_t length);
/// Map all higher-half pages into the address space
/// By linking them to same entries as kernel
@@ -30,12 +35,21 @@ private:
AddressSpace *space = nullptr;
Mutex space_lock;
enum class EntryType {
FREE,
PHYS,
ANON
};
struct ListEntry {
uintptr_t begin;
uint64_t length;
bool available;
EntryType type = EntryType::FREE;
};
ListEntry *get_entry(uintptr_t v_addr, size_t length);
//
SkipList<uintptr_t, ListEntry> regions;
Mutex regions_lock;
};

View File

@@ -20,6 +20,10 @@ __attribute__((unused)) void _start() {
}
putchar('\n');
sleep(100);
execve("/hello2", 0, 0);
while (1) {
// putchar('h');
// putchar('i');
@@ -27,6 +31,7 @@ __attribute__((unused)) void _start() {
char read = readchar();
if (read == 'm') print_mem();
if (read == 't') print_tasks();
if (read == 'h') execve("/hello2", 0, 0);
putchar('\n');
putchar(read);
// sleep(100000);

View File

@@ -33,6 +33,8 @@ extern "C" {
#define SYSCALL_MKDIR_ID 12
#define SYSCALL_UNLINK_ID 13
#define SYSCALL_EXECVE_ID 50
#define SYSCALL_PRINT_MEM 1000
#define SYSCALL_PRINT_TASKS 1001

View File

@@ -52,6 +52,10 @@ uint64_t lseek(uint64_t fd, uint64_t off, uint64_t whence) {
return do_syscall(SYSCALL_LSEEK_ID, fd, off, whence);
}
uint64_t execve(const char *pathname, char *const argv[], char *const envp[]) {
return do_syscall(SYSCALL_EXECVE_ID, (uint64_t) pathname, (uint64_t) argv, (uint64_t) envp);
}
void print_mem() {
do_syscall(SYSCALL_PRINT_MEM, 0, 0, 0);
}

View File

@@ -29,6 +29,8 @@ uint64_t read(uint64_t fd, char *buf, uint64_t len);
uint64_t write(uint64_t fd, const char *buf, uint64_t len);
uint64_t lseek(uint64_t fd, uint64_t off, uint64_t whence);
uint64_t execve(const char *pathname, char *const argv[], char *const envp[]);
void print_mem();
void print_tasks();