mirror of
https://github.com/usatiuk/ficus.git
synced 2025-10-29 00:27:52 +01:00
slightly leaking exec
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = ®ions.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 = ®ions.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))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user