summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/error.h3
-rw-r--r--api/init.h19
-rw-r--r--api/obj.h14
-rw-r--r--api/syscall.h129
-rw-r--r--arch/x86_64/hal/obj.c18
-rw-r--r--arch/x86_64/hal/paging.c105
-rw-r--r--arch/x86_64/hal/paging.h8
-rw-r--r--arch/x86_64/hal/process.c8
-rw-r--r--arch/x86_64/sys/syscall.c48
-rw-r--r--arch/x86_64/sys/syscall.h2
-rw-r--r--arch/x86_64/sys/syscall_serial.c (renamed from arch/x86_64/sys/serial.c)20
-rw-r--r--boot/limine/memorymap.c41
-rw-r--r--config.h2
-rw-r--r--config.mk1
-rw-r--r--doc/syscall.md264
-rw-r--r--hal/memory.h10
-rw-r--r--hal/process.h2
-rw-r--r--sys/link.c56
-rw-r--r--sys/link.h24
-rw-r--r--sys/lockstack.c30
-rw-r--r--sys/lockstack.h18
-rw-r--r--sys/syscall.c105
-rw-r--r--sys/syscall.h45
-rw-r--r--sys/syscall_objdir.c19
-rw-r--r--sys/syscall_pagedir.c170
-rw-r--r--sys/syscall_untyped.c68
-rw-r--r--sys/syscall_vtt.c20
27 files changed, 870 insertions, 379 deletions
diff --git a/api/error.h b/api/error.h
index 5e0e936..de7d4b2 100644
--- a/api/error.h
+++ b/api/error.h
@@ -15,5 +15,8 @@
#define EBUSY 12
#define EEMPTY 13
#define EFULL 14
+#define EOVERFLOW 15
+#define EBADCALL 16
+#define EPERM 17
#endif
diff --git a/api/init.h b/api/init.h
index 73b19e4..e92c910 100644
--- a/api/init.h
+++ b/api/init.h
@@ -4,26 +4,33 @@
#include <stdint.h>
enum {
- ROOTDIR_DIR_I = 0,
+ ROOTDIR_NULL_I = 0,
+ ROOTDIR_DIR_I,
ROOTDIR_PROCESSORS_I,
ROOTDIR_PAGEDIR_I,
ROOTDIR_UNTYPED_I,
ROOTDIR_HWMEMORY_I,
ROOTDIR_PCB_I,
- ROOTDIR_IOPB_I,
ROOTDIR_INTERRUPTS_I,
ROOTDIR_INITRD_I,
ROOTDIR_MESSAGE_I,
+ ROOTDIR_FRAMEBUFFER_I,
+ ROOTDIR_VIRTTERM_I,
+ _ROOTDIR_LAST_I
};
+#ifdef __x86_64__
+enum {
+ ROOTDIR_IOPB_I = _ROOTDIR_LAST_I,
+ ROOTDIR_SERIAL_COM_I,
+ _ROOTDIR_LAST_ARCH_I
+};
+#endif
+
struct init_payload
{
void *rsdp;
uintptr_t brk;
};
-#define ROOTDIR_SERIAL_COM_I 0x80
-#define ROOTDIR_FRAMEBUFFER_I 0x81
-#define ROOTDIR_VIRTTERM_I 0x82
-
#endif
diff --git a/api/obj.h b/api/obj.h
index 04513c1..6e9ddc6 100644
--- a/api/obj.h
+++ b/api/obj.h
@@ -10,9 +10,9 @@ enum
JOVE_OBJ_OBJDIR,
JOVE_OBJ_PAGEDIR,
JOVE_OBJ_PROCESSOR,
- JOVE_OBJ_HWMEMORY,
+ JOVE_OBJ_SHMEMORY,
JOVE_OBJ_INT_HANDLE,
- JOVE_OBJ_PROCESS,
+ JOVE_OBJ_PCB,
JOVE_OBJ_INITRD_FILE,
JOVE_OBJ_FRAMEBUFFER,
JOVE_OBJ_VIRTTERM,
@@ -20,6 +20,16 @@ enum
JOVE_OBJ_LINK,
};
+
+/*Link can read object states and map page frames as read only*/
+#define JOVE_PERM_READ 1
+/*Link can write object states and map page frames as writeable*/
+#define JOVE_PERM_WRITE 2
+/*Link can untype linked objects, split untyped memory, and retype untyped linked object.*/
+#define JOVE_PERM_MUTATE 4
+
+#define JOVE_PERM_ALL 7
+
#define OBJDIR_NUM_ENTRIES (0x1000 / sizeof(uintmax_t))
typedef uint16_t objpath_part_t;
diff --git a/api/syscall.h b/api/syscall.h
index 4bb2eb2..1cdc941 100644
--- a/api/syscall.h
+++ b/api/syscall.h
@@ -38,35 +38,21 @@ struct syscall_generic_objpath
objpath_part_t path[];
};
-/* The kernel will return the physical memory address of this untyped object. */
-#define SYSCALL_UNTYPED_ADDRESS 0
-/* The kernel will return the size of this untyped object. */
-#define SYSCALL_UNTYPED_SIZE 1
-
-/* If newtype is not a valid JOVE object, the kernel will return EBADARG.
- * If the untyped object is too small for this object, the kernel will return ETOOSMALL.
- * If the untyped object is too big for this object, the kernel will return ETOOBIG.
- * New objects will be initialized with default values.
- * */
-#define SYSCALL_UNTYPED_RETYPE 2
-struct syscall_untyped_retype
+enum
{
- uint16_t newtype;
+ _SYSCALL_UNTYPED_BADCALL = 0,
+ SYSCALL_UNTYPED_ADDRESS,
+ SYSCALL_UNTYPED_SIZE,
+ SYSCALL_UNTYPED_SPLIT,
+ SYSCALL_UNTYPED_MERGE,
+ SYSCALL_UNTYPED_RETYPE,
};
-/* Splits the tail of the untyped object into another untyped object with [bytes] length.
- * If bytes is less than JOVE_UNTYPED_MINSIZE, the kernel will return ETOOSMALL.
- * If the syscall message is too small for dest_path, the kernel will return ETOOSMALL.
- * If dest_path does not target a JOVE_OBJ_NONE object, the kernel will return EBADOBJ.
- * Destination path will be occupied by the untyped object created by the split.
- * */
-#define SYSCALL_UNTYPED_SPLIT 3
-/* Follows rules declared above syscall_generic_objpath.
- * If dest_path does not target a JOVE_OBJ_UNTYPED object, the kernel will return EBADPATH.
- * If the dest untyped object is not adjacent to the target object, the kernel will return EBADOBJ.
- * Destination path will be set to JOVE_OBJ_NONE and target untyped will grow to include the object.
- * */
-#define SYSCALL_UNTYPED_MERGE 4
+#define SYSCALL_PERM_UNTYPED_ADDRESS JOVE_PERM_READ
+#define SYSCALL_PERM_UNTYPED_SIZE JOVE_PERM_READ
+#define SYSCALL_PERM_UNTYPED_SPLIT (JOVE_PERM_WRITE | JOVE_PERM_MUTATE)
+#define SYSCALL_PERM_UNTYPED_MERGE (JOVE_PERM_WRITE | JOVE_PERM_MUTATE)
+
struct syscall_untyped_split
{
size_t bytes;
@@ -74,71 +60,56 @@ struct syscall_untyped_split
objpath_part_t dest_path[];
};
-/* Follows rules declared above syscall_generic_objpath.
- * Returns the object type at path.
- * */
-#define SYSCALL_OBJDIR_OBJTYPE 0
+enum
+{
+ _SYSCALL_OBJDIR_BADCALL = 0,
+ SYSCALL_OBJDIR_OBJTYPE,
+};
-/*
- * If virtual_address does not have a page table, the kernel will return ENOMAP.
- * If virtual_address already has a mapping, the kernel will return EEXIST.
- * Follows the rules defined above syscall_pagedir_map.
- * Maps the untyped page frame to the page table at virtual_address with the passed flags bits.
- * */
-#define SYSCALL_PAGEDIR_MAP_FRAME 0
+#define SYSCALL_PERM_OBJDIR_OBJTYPE JOVE_PERM_READ
+
+enum
+{
+ _SYSCALL_PAGEDIR_NONE = 0,
+ SYSCALL_PAGEDIR_MAP_FRAME,
+ SYSCALL_PAGEDIR_MAP_TABLE,
+ SYSCALL_PAGEDIR_MAP_SHMEM,
+ SYSCALL_PAGEDIR_UNMAP_FRAME,
+ SYSCALL_PAGEDIR_UNMAP_TABLE,
+ SYSCALL_PAGEDIR_UNMAP_SHMEM,
+};
+
+#define SYSCALL_PERM_PAGEDIR_MAP_FRAME (JOVE_PERM_READ | JOVE_PERM_WRITE)
+#define SYSCALL_PERM_PAGEDIR_MAP_TABLE (JOVE_PERM_READ | JOVE_PERM_WRITE)
+#define SYSCALL_PERM_PAGEDIR_MAP_SHMEM (JOVE_PERM_READ | JOVE_PERM_WRITE)
+#define SYSCALL_PERM_PAGEDIR_UNMAP_FRAME (JOVE_PERM_READ | JOVE_PERM_WRITE)
+#define SYSCALL_PERM_PAGEDIR_UNMAP_TABLE (JOVE_PERM_READ | JOVE_PERM_WRITE)
+#define SYSCALL_PERM_PAGEDIR_UNMAP_SHMEM (JOVE_PERM_READ | JOVE_PERM_WRITE)
-/* If virtual_address already has a page table, the kernel will return EHASMAP.
- * Follows the rules defined above syscall_pagedir_map.
- * Creates a page table using the untyped object for memory allocation at virtual_address.
- * Flags bits are always set to writeable and executable.
- * */
-#define SYSCALL_PAGEDIR_MAP_TABLE 1
-
-/* If virtual_address is above the JOVE_USER_MEMORY_LIMIT, the kernel will return EBADARG.
- * If the message is too small for untyped_path, the kernel will return ETOOSMALL.
- * If untyped_path does not point to a valid JOVE_OBJ_UNTYPED, the kernel will return EBADOBJ.
- * If the untyped object is not aligned to 0x1000, the kernel will return EALIGN.
- * If the untyped object is not sized to 0x1000, the kernel will return EBADSIZE.
- *
- * */
struct syscall_pagedir_flags
{
uint8_t writeable : 1;
uint8_t executable : 1;
uint8_t flg_unused : 6;
};
+
struct syscall_pagedir_map
{
- struct syscall_pagedir_flags flags;
- uintptr_t virtual_address;
+ struct syscall_pagedir_flags page_flags;
uint16_t untyped_pathlen;
+ uintptr_t virtual_address;
objpath_part_t untyped_path[];
};
-/**If a page frame is present at the virtual address, the kernel will:
- * mark the page frame as not present.
- * untype the page frame and move it to the none path.
- * return 0.
- * If a page frame is not present at the virtual address, the kernel will return EEMPTY.
- * Follows the rules defined by struct syscall_pagedir_unmap
- * */
-#define SYSCALL_PAGEDIR_UNMAP_FRAME 2
-
-/**If a page table is present at the virtual address, one of two things will happen:
- * If the page table has present entries, the kernel will return EBUSY.
- * Otherwise, the kernel will:
- * mark the page table as not present.
- * untype the page frame and move it to the none path.
- * return 0.
- * If a page table is not present at the virtual address, the kernel will return EEMPTY.
- * Follows the rules defined by the struct syscall_pagedir_unmap
- * */
-#define SYSCALL_PAGEDIR_UNMAP_TABLE 3
+struct syscall_pagedir_map_shmem
+{
+ struct syscall_pagedir_flags page_flags;
+ uint8_t page_offset;
+ uint16_t shmem_pathlen;
+ uintptr_t virtual_address;
+ objpath_part_t shmem_path[];
+};
-/**If the virtual address is above JOVE_USER_MEMORY_LIMIT, the kernel will return EBADARG.
- * If none_pathlen exceeds the length of the message, the kernel will return ETOOBIG.
- * If none_path does not point to a JOVE_OBJ_NONE object, the kernel will return EBADOBJ.
- * */
struct syscall_pagedir_unmap
{
uintptr_t virtual_address;
@@ -146,6 +117,10 @@ struct syscall_pagedir_unmap
objpath_part_t none_path[];
};
-#define SYSCALL_VTT_WRITE 0
+enum
+{
+ _SYSCALL_VTT_NONE = 0,
+ SYSCALL_VTT_WRITE
+};
#endif
diff --git a/arch/x86_64/hal/obj.c b/arch/x86_64/hal/obj.c
index cb0e13d..9844a54 100644
--- a/arch/x86_64/hal/obj.c
+++ b/arch/x86_64/hal/obj.c
@@ -79,7 +79,7 @@ objdir_peeklocal(
jove_owned_obj_t *objdir_obj,
uint16_t entry)
{
- if(obj_gettype_linked(objdir_obj) != JOVE_OBJ_OBJDIR) {
+ if(obj_gettype(objdir_obj) != JOVE_OBJ_OBJDIR) {
errno = EBADOBJ;
return (jove_obj_t) { 0 };
}
@@ -88,7 +88,7 @@ objdir_peeklocal(
return (jove_obj_t) { 0 };
}
- jove_objdir_t *objtab = obj_deref_linked(objdir_obj);
+ jove_objdir_t *objtab = obj_deref(objdir_obj);
return objtab->entries[entry];
}
@@ -97,14 +97,17 @@ objdir_getlocal(
jove_owned_obj_t *objdir_obj,
uint16_t entry)
{
- if(obj_gettype_linked(objdir_obj) != JOVE_OBJ_OBJDIR) {
+ while(obj_gettype(objdir_obj) == JOVE_OBJ_LINK) {
+ objdir_obj = link_deref(objdir_obj);
+ }
+ if(obj_gettype(objdir_obj) != JOVE_OBJ_OBJDIR) {
reterr(EBADOBJ);
}
if(entry >= JOVE_OBJDIR_ENTRIES) {
reterr(EBADPATH);
}
- jove_objdir_t *objtab = obj_deref_linked(objdir_obj);
+ jove_objdir_t *objtab = obj_deref(objdir_obj);
return obj_take(&objtab->entries[entry]);
}
@@ -113,14 +116,17 @@ objdir_trygetlocal(
jove_owned_obj_t *objdir_obj,
uint16_t entry)
{
- if(obj_gettype_linked(objdir_obj) != JOVE_OBJ_OBJDIR) {
+ while(obj_gettype(objdir_obj) == JOVE_OBJ_LINK) {
+ objdir_obj = link_deref(objdir_obj);
+ }
+ if(obj_gettype(objdir_obj) != JOVE_OBJ_OBJDIR) {
reterr(EBADOBJ);
}
if(entry >= JOVE_OBJDIR_ENTRIES) {
reterr(EBADPATH);
}
- jove_objdir_t *objtab = obj_deref_linked(objdir_obj);
+ jove_objdir_t *objtab = obj_deref(objdir_obj);
return obj_trytake(&objtab->entries[entry]);
}
diff --git a/arch/x86_64/hal/paging.c b/arch/x86_64/hal/paging.c
index 9947e9c..2fbf26c 100644
--- a/arch/x86_64/hal/paging.c
+++ b/arch/x86_64/hal/paging.c
@@ -106,7 +106,7 @@ s_pagedir_get_pml1(page_t *pml4, uintptr_t vptr)
}
int pagedir_map_frame(page_t *pml4,
- uintptr_t pptr, uintptr_t vptr,
+ uintptr_t pptr, uintptr_t vptr,
uintmax_t flg)
{
page_t *pml1 = s_pagedir_get_pml1(pml4, vptr);
@@ -121,41 +121,35 @@ int pagedir_map_frame(page_t *pml4,
return 0;
}
-int pagedir_map_untyped_frame(
- jove_owned_obj_t *tgt, jove_owned_obj_t *untyped_obj,
- uintptr_t vptr, struct syscall_pagedir_flags flg)
+int pagedir_map_shmem(page_t *pml4,
+ uintptr_t pptr, uintptr_t vptr,
+ struct syscall_pagedir_flags flg)
{
- page_t *pml4 = obj_deref(tgt);
- uintptr_t frame = obj_getvalue(untyped_obj);
-
- return pagedir_map_frame(pml4, frame, vptr,
- (flg.writeable ? PAGE_WRITEABLE : 0) |
- PAGE_USER |
- (flg.executable ? PAGE_XD : 0));
+ uintmax_t real_flg = PAGE_USER | PAGE_SHMEM;
+ if(flg.writeable) {
+ real_flg |= PAGE_WRITEABLE;
+ }
+ if(!flg.executable) {
+ real_flg |= PAGE_XD;
+ }
+ return pagedir_map_frame(pml4, pptr, vptr, real_flg);
}
-int pagedir_unmap_untyped_frame(
- jove_owned_obj_t *tgt, jove_owned_obj_t *dst, uintptr_t vptr)
+int pagedir_map_untyped_frame(
+ jove_owned_obj_t *tgt, jove_perm_obj_t *untyped,
+ uintptr_t vptr, struct syscall_pagedir_flags flg)
{
page_t *pml4 = obj_deref(tgt);
- size_t pml4i = PML4I(vptr);
- if(!pml4[pml4i].p) return ENOMAP;
-
- page_t *pml1 = s_pagedir_get_pml1(pml4, vptr);
- size_t pml1i = PML1I(vptr);
- if(!pml1[pml1i].p) return ENOMAP;
-
- uintptr_t untyped_pptr = (pml1[pml1i].paddr << 12);
-
- obj_settype(dst, JOVE_OBJ_UNTYPED);
- obj_setvalue(dst, untyped_pptr);
-
- jove_untyped_t *untyped_data = obj_deref(dst);
- untyped_data->limit = 0x1000;
- __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory");
+ if(flg.writeable && (untyped->permissions & JOVE_PERM_WRITE) == 0) {
+ kprintf("%s: Untyped object flagged for writeable mapping missing write permissions!\n", __func__);
+ return -EPERM;
+ }
- return 0;
+ uintptr_t frame = obj_getvalue(untyped->obj);
+ return pagedir_map_frame(pml4, frame, vptr, PAGE_USER |
+ (flg.writeable ? PAGE_WRITEABLE : 0) |
+ (flg.executable ? 0 : PAGE_XD));
}
int pagedir_map_table(page_t *pml4,
@@ -199,14 +193,63 @@ map_table:
}
int pagedir_map_untyped_table(
- jove_owned_obj_t *tgt, jove_owned_obj_t *untyped_obj, uintptr_t vptr)
+ jove_owned_obj_t *tgt, jove_perm_obj_t *untyped, uintptr_t vptr)
{
page_t *pml4 = obj_deref(tgt);
- uintptr_t frame = obj_getvalue(untyped_obj);
+
+ if((untyped->permissions & JOVE_PERM_WRITE) == 0) {
+ kprintf("%s: Untyped object flagged for table mapping missing write permissions!\n", __func__);
+ return -EPERM;
+ }
+ uintptr_t frame = obj_getvalue(untyped->obj);
return pagedir_map_table(pml4, frame, vptr);
}
+int pagedir_map_shmem_frame(
+ jove_owned_obj_t *tgt, jove_perm_obj_t *shmem, uint8_t page_offset,
+ uintptr_t vptr, struct syscall_pagedir_flags flg)
+{
+ page_t *pml4 = obj_deref(tgt);
+
+ if(flg.writeable && (shmem->permissions & JOVE_PERM_WRITE) != 0) {
+ kprintf("%s: Shared memory object flagged for writeable mapping missing write permissions!\n", __func__);
+ return -EPERM;
+ }
+
+ uintmax_t value = obj_getvalue(shmem->obj);
+ uintptr_t frame = value & ~0xFF;
+ frame += (uintmax_t)page_offset << 12;
+
+ return pagedir_map_frame(pml4, frame, vptr, PAGE_USER |
+ (flg.writeable ? PAGE_WRITEABLE : 0) |
+ (flg.executable ? 0 : PAGE_XD));
+}
+
+int pagedir_unmap_untyped_frame(
+ jove_owned_obj_t *tgt, jove_owned_obj_t *dst, uintptr_t vptr)
+{
+ page_t *pml4 = obj_deref(tgt);
+
+ size_t pml4i = PML4I(vptr);
+ if(!pml4[pml4i].p) return ENOMAP;
+
+ page_t *pml1 = s_pagedir_get_pml1(pml4, vptr);
+ size_t pml1i = PML1I(vptr);
+ if(!pml1[pml1i].p) return ENOMAP;
+
+ uintptr_t untyped_pptr = (pml1[pml1i].paddr << 12);
+
+ obj_settype(dst, JOVE_OBJ_UNTYPED);
+ obj_setvalue(dst, untyped_pptr);
+
+ jove_untyped_t *untyped_data = obj_deref(dst);
+ untyped_data->limit = 0x1000;
+ __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory");
+
+ return 0;
+}
+
int pagedir_unmap_untyped_table(
jove_owned_obj_t *tgt, jove_owned_obj_t *dst, uintptr_t vptr)
{
diff --git a/arch/x86_64/hal/paging.h b/arch/x86_64/hal/paging.h
index 5b7260c..becf353 100644
--- a/arch/x86_64/hal/paging.h
+++ b/arch/x86_64/hal/paging.h
@@ -17,7 +17,8 @@ typedef union page_table_entry
uint8_t d : 1;
uint8_t ps : 1;
uint8_t g : 1;
- uint8_t ign_0 : 2;
+ uint8_t shm : 1;
+ uint8_t ign_0 : 1;
uint8_t r : 1;
uint64_t paddr : 35;
uint8_t ign_1 : 4;
@@ -35,8 +36,9 @@ typedef union page_table_entry
#define PAGE_ACCESSED 0b100000
#define PAGE_DIRTY 0b1000000
#define PAGE_PS 0b10000000
-#define PAGE_GLOBAL 0b000000000
-#define PAGE_XD (0ULL << 63)
+#define PAGE_GLOBAL 0b100000000
+#define PAGE_SHMEM 0b1000000000
+#define PAGE_XD (1ULL << 63)
extern void *_kernel_physptr;
diff --git a/arch/x86_64/hal/process.c b/arch/x86_64/hal/process.c
index f30d703..aa51f45 100644
--- a/arch/x86_64/hal/process.c
+++ b/arch/x86_64/hal/process.c
@@ -22,7 +22,7 @@ process_current(void)
pcb_t*
pcb_from_obj(jove_owned_obj_t *obj)
{
- if(obj_gettype(obj) != JOVE_OBJ_PROCESS) {
+ if(obj_gettype(obj) != JOVE_OBJ_PCB) {
reterr(EBADOBJ);
}
return obj_deref(obj);
@@ -34,10 +34,10 @@ pcb_pid(pcb_t *pcb)
return pcb->pid;
}
-jove_owned_obj_t*
+jove_obj_t*
pcb_rootdir(pcb_t *pcb)
{
- return obj_take(pcb->rootdir);
+ return pcb->rootdir;
}
void
@@ -62,7 +62,7 @@ processing_setup(void (*process_main))
{
jove_owned_obj_t *process_obj = objdir_getlocal(_rootdir_obj, ROOTDIR_PCB_I);
- obj_settype(process_obj, JOVE_OBJ_PROCESS);
+ obj_settype(process_obj, JOVE_OBJ_PCB);
obj_setvalue(process_obj, (uintptr_t)s_init_pcb);
proc->pcb_obj = obj_release(process_obj);
diff --git a/arch/x86_64/sys/syscall.c b/arch/x86_64/sys/syscall.c
index 53351e7..a694674 100644
--- a/arch/x86_64/sys/syscall.c
+++ b/arch/x86_64/sys/syscall.c
@@ -10,24 +10,17 @@ syscall_handle_t s_arch_handles[128] = {
};
int
-_syscall_handle_arch(
- jove_owned_obj_t *pcb_obj,
- jove_owned_obj_t *objdir,
- jove_owned_obj_t *message_obj,
- jove_owned_obj_t *target_obj,
- struct syscall_header *header,
- size_t bytes_left,
- void *payload)
+_syscall_handle_arch(syscall_context_t *ctx)
{
- uint8_t target_type = obj_gettype(target_obj) - 0x80;
+ uint8_t target_type = obj_gettype(ctx->target.obj) - 0x80;
syscall_handle_t call_handle = s_arch_handles[target_type];
if(call_handle == NULL) {
kprintf("syscall: Process %i tried to call syscall on object %P which doesn't support syscalls!\n",
- pcb_pid(obj_deref(pcb_obj)), header->path, header->pathlen);
- return EBADOBJ;
+ pcb_pid(obj_deref(ctx->pcb)), ctx->header->path, ctx->header->pathlen);
+ return -EBADOBJ;
}
- return call_handle(pcb_obj, objdir, message_obj, target_obj, header, bytes_left, payload);
+ return call_handle(ctx);
}
__attribute__((naked))
@@ -38,32 +31,29 @@ void _syscall_entry(void)
movq %%gs:%c[pcb], %%rax; \
movq %%rsp, %%rdx; \
movq %c[ksp](%%rax), %%rsp; \
+ pushq %%rcx; \
pushq %%rdx; \
pushq %%r11; \
- pushq %%rbx; \
- pushq %%rcx; \
pushq %%rbp; \
- pushq %%r12; \
- pushq %%r13; \
- pushq %%r14; \
- pushq %%r15; \
callq syscall_handler; \
swapgs; \
- popq %%r15; \
- popq %%r14; \
- popq %%r13; \
- popq %%r12; \
- popq %%rbp; \
- popq %%rcx; \
- popq %%rbx; \
- xorq %%rdx, %%rdx; \
+ xorq %%r15, %%r15; \
+ xorq %%r14, %%r14; \
+ xorq %%r13, %%r13; \
+ xorq %%r12, %%r12; \
+ xorq %%r10, %%r10; \
+ xorq %%r9, %%r9; \
+ xorq %%r8, %%r8; \
xorq %%rsi, %%rsi; \
xorq %%rdi, %%rdi; \
- xorq %%r8, %%r8; \
- xorq %%r9, %%r9; \
- xorq %%r10, %%r10; \
+ xorq %%rbp, %%rbp; \
+ xorq %%rdx, %%rdx; \
+ xorq %%rcx, %%rcx; \
+ xorq %%rbx, %%rbx; \
+ popq %%rbp; \
popq %%r11; \
popq %%rsp; \
+ popq %%rcx; \
sysretq;"
::
[pcb] "i"(offsetof(processor_t, pcb)),
diff --git a/arch/x86_64/sys/syscall.h b/arch/x86_64/sys/syscall.h
index 868ce0b..34f6a2a 100644
--- a/arch/x86_64/sys/syscall.h
+++ b/arch/x86_64/sys/syscall.h
@@ -3,7 +3,7 @@
#include "sys/syscall.h"
-int _syscall_handle_serial(SYSCALL_FUNCTION_ARGS);
+int _syscall_handle_serial(syscall_context_t *ctx);
#define SYSCALL_SERIAL_COM_WRITE 0
diff --git a/arch/x86_64/sys/serial.c b/arch/x86_64/sys/syscall_serial.c
index 12db6fd..786a78b 100644
--- a/arch/x86_64/sys/serial.c
+++ b/arch/x86_64/sys/syscall_serial.c
@@ -1,5 +1,6 @@
#include "jove.h"
#include "lib/printf.h"
+#include "sys/syscall.h"
#include "syscall.h"
#include "arch/x86_64/hal/serial_com.h"
@@ -20,20 +21,13 @@ s_syscall_serial_write(
}
int
-_syscall_handle_serial(
- jove_owned_obj_t *pcb_obj,
- jove_owned_obj_t *objdir,
- jove_owned_obj_t *message_obj,
- jove_owned_obj_t *target_obj,
- struct syscall_header *header,
- size_t bytes_left,
- void *payload_data)
+_syscall_handle_serial(syscall_context_t *ctx)
{
- switch(header->callid) {
- case 0:
- return s_syscall_serial_write(target_obj, bytes_left, payload_data);
+ switch(ctx->header->callid) {
+ case SYSCALL_SERIAL_COM_WRITE:
+ return s_syscall_serial_write(ctx->target.obj, ctx->bytes_left, ctx->payload);
default:
- kprintf("syscall_serial: serial com object does not support syscall %i\n", header->callid);
- return EOOB;
+ kprintf("syscall_serial: serial com object does not support syscall %i\n", ctx->header->callid);
+ return -EBADCALL;
}
}
diff --git a/boot/limine/memorymap.c b/boot/limine/memorymap.c
index 25dcc61..a8841e2 100644
--- a/boot/limine/memorymap.c
+++ b/boot/limine/memorymap.c
@@ -49,13 +49,17 @@ mem_setup_untyped(void)
uintptr_t highest_phys = 0;
for(size_t i = 0; i < _limine_memmap_resp->entry_count; i++) {
struct limine_memmap_entry *entry = _limine_memmap_resp->entries[i];
- kprintf("Limine: %p : %p %s\n", entry->base, entry->length, limine_mmap_entry_type_str[entry->type]);
if(entry->type == LIMINE_MEMMAP_USABLE ||
entry->type == LIMINE_MEMMAP_ACPI_RECLAIMABLE ||
entry->type == LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE)
{
-
+ if(untyped_i > JOVE_OBJDIR_ENTRIES){
+ kprintf("%s: Provided memory map exceeds kernel limits. Some memory may not be accessable.", __func__);
+ break;
+ }
+
+ klogf("%p : %p %s\n", entry->base, entry->length, limine_mmap_entry_type_str[entry->type]);
if(entry->base == 0) continue;
if(entry->base + entry->length > highest_phys) highest_phys = entry->base + entry->length;
@@ -68,27 +72,30 @@ mem_setup_untyped(void)
untyped_data->limit = entry->length;
obj_release(untyped_obj);
}
-
- if(untyped_i > MEMMAP_MAX_ENTRIES){
- kprintf("!!!Provided memory map exceeds kernel limits. Some memory may not be accessable!!!");
- break;
- }
}
if(entry->type == LIMINE_MEMMAP_RESERVED |
entry->type == LIMINE_MEMMAP_ACPI_NVS |
entry->type == LIMINE_MEMMAP_ACPI_TABLES)
{
- size_t hw_pages = entry->length >> 12;
- if(hw_pages > 4095) {
- klogf("HW memory page is too big!\n", "");
+ intmax_t hw_pages = entry->length >> 12;
+ uintptr_t base = entry->base;
+ while(hw_pages > 0) {
+ if(hwmem_i >= JOVE_OBJDIR_ENTRIES) {
+ kprintf("%s: Reserved memory region exceeds indexing limits!\n", __func__);
+ break;
+ }
+
+ size_t pages = hw_pages > 4095 ? 4095 : hw_pages;
+ klogf("%p : %p RESERVED\n", base, ((pages + 1) << 12));
+
+ jove_owned_obj_t *hwmem_obj = obj_take(&s_hwmemory_objdir.entries[hwmem_i++]);
+ obj_settype(hwmem_obj, JOVE_OBJ_SHMEMORY);
+ obj_setvalue(hwmem_obj, entry->base | (entry->length >> 12));
+
+ obj_release(hwmem_obj);
+ hw_pages -= 4096;
+ base += (4096ULL << 12);
}
-
- jove_owned_obj_t *hwmem_obj = obj_take(&s_hwmemory_objdir.entries[hwmem_i++]);
- obj_settype(hwmem_obj, JOVE_OBJ_HWMEMORY);
- obj_setvalue(hwmem_obj, entry->base | (entry->length >> 12));
-
- obj_release(hwmem_obj);
}
}
- kprintf("Highest physical address: %p\n", highest_phys);
}
diff --git a/config.h b/config.h
index 02c4243..50f35c1 100644
--- a/config.h
+++ b/config.h
@@ -14,4 +14,6 @@
#define INIT_PROGRAM_PAGES_MAX 32
#define INIT_STACK_PAGES 2
+#define LOCKSTACK_MAX 64
+
#endif
diff --git a/config.mk b/config.mk
index 760d264..7416c4e 100644
--- a/config.mk
+++ b/config.mk
@@ -5,6 +5,7 @@ CFLAGS = \
-fno-pic \
-g \
-MD \
+ -mno-sse \
-D__$(TARGET_MACHINE)__ \
-D__$(TARGET_BOOTLOADER)__ \
-Iinclude \
diff --git a/doc/syscall.md b/doc/syscall.md
new file mode 100644
index 0000000..9304785
--- /dev/null
+++ b/doc/syscall.md
@@ -0,0 +1,264 @@
+## Jove syscalls
+
+Every syscall in Jove is passed to the kernel via a `JOVE_OBJ_MESSAGE` object.
+
+To pass a message object to the kernel, the message object must be close to the root directory of the calling PCB.
+
+To resolve the message object, the kernel requires an object path and a path length encoded in argument registers.
+
+On x86_64, the encoding is as follows:
+
+| | Message Path | Message Path Length |
+|----------|--------------|---------------------|
+| Register | rdi | rsi |
+
+If the message path exceeds the width of the message path register, the kernel will return `-EBADPATH`.
+
+If the message path does not point to a `JOVE_OBJ_MESSAGE` object, the kernel will return `-EBADOBJ`.
+
+If the message path points to an object locked by a mutex, the kernel will return `-EBUSY`.
+
+
+### Syscall header
+
+| Size (bytes) | 2 | 2 | path_len * 2 |
+|--------------|---------|------------------------|--------------|
+| Data | Call ID | Path length (path_len) | Target path |
+
+All system calls must start with these bytes at the start of the passed message object.
+
+1. `Call ID`: ID of the system call to invoke.
+2. `Path length`: Length of the target path.
+3. `Object path`: Path to the target object starting from the PCB's root directory.
+
+If the target path length exceeds the width of the message object, the kernel will return `-ETOOSMALL`.
+
+If the target path points to a `JOVE_OBJ_NONE` object, the kernel will return `-EBADOBJ`.
+
+If the target object does not support the call id, the kernel will return `-EBADCALL`.
+
+Further behavior is specified by the target syscall specification.
+
+Target syscalls may have further required bytes in the message.
+
+If the syscall does not have the correct permissions for the syscall, the kernel will return `-ENOPERM`.
+
+
+### JOVE_OBJ_UNTYPED
+
+| Syscall | Permissions Required |
+|-------------------------|-----------------------------------|
+| SYSCALL_UNTYPED_ADDRESS | JOVE_PERM_READ |
+| SYSCALL_UNTYPED_SIZE | JOVE_PERM_READ |
+| SYSCALL_UNTYPED_SPLIT | JOVE_PERM_WRITE, JOVE_PERM_MUTATE |
+| SYSCALL_UNTYPED_MERGE | JOVE_PERM_WRITE, JOVE_PERM_MUTATE |
+| SYSCALL_UNTYPED_RETYPE | JOVE_PERM_WRITE, JOVE_PERM_MUTATE |
+
+#### SYSCALL_UNTYPED_ADDRESS
+
+Returns the physical address of the untyped memory span.
+
+#### SYSCALL_UNTYPED_SIZE
+
+Returns the size of the untyped memory span.
+
+#### SYSCALL_UNTYPED_SPLIT
+
+Splits the untyped memory span into the destination path sized by the split size.
+
+| Data | Split size | Destination Path Length | Destination Path |
+|--------------|----------------|-------------------------|------------------|
+| Size (bytes) | sizeof(size_t) | 2 | path_len * 2 |
+
+
+If the split size exceeds the size of the target untyped, the kernel will return `-ETOOBIG`.
+
+If the split size is less than `JOVE_UNTYPED_MINSIZE`, the kernel will return `-ETOOSMALL`.
+
+If the destination path length exceeds the size of the message, the kernel will return `-EBADPATH`.
+
+If the destination path does not point to a `JOVE_OBJ_NONE` object, the kernel will return `-EBADOBJ`.
+
+#### SYSCALL_UNTYPED_MERGE
+
+Merges two adjacent untyped memory spans into one untyped memory span at the first untyped object.
+
+| Data | Untyped Path Length | Untyped Path |
+|--------------|---------------------|--------------|
+| Size (bytes) | 2 | path_len * 2 |
+
+
+If the untyped path length exceeds the size of the message, the kernel will return `-EBADPATH`.
+
+If the untyped path does not point to a `JOVE_OBJ_NONE` object, the kernel will return `-EBADOBJ`.
+
+
+### JOVE_OBJ_OBJDIR
+
+| Syscall | Permissions Required |
+|------------------------|----------------------|
+| SYSCALL_OBJDIR_OBJTYPE | JOVE_PERM_READ |
+
+#### SYSCALL_OBJDIR_OBJTYPE
+
+Returns the object type at the given entry index.
+
+| Data | Entry Index |
+|--------------|-------------|
+| Size (bytes) | 2 |
+
+If the message is too small to hold the payload, the kernel will return `-ETOOSMALL`.
+
+If the entry index exceeds `JOVE_OBJDIR_ENTRIES`, the kernel returns `-EOOB`.
+
+
+### JOVE_OBJ_PAGEDIR
+
+| Syscall | Target Permissions | Subject Permissions | Subject Conditional Permissions |
+|-----------------------------|:-------------------------------:|:-------------------------------------------------:|:-------------------------------:|
+| SYSCALL_PAGEDIR_MAP_FRAME | JOVE_PERM_READ, JOVE_PERM_WRITE | JOVE_PERM_MUTATE | JOVE_PERM_READ, JOVE_PERM_WRITE |
+| SYSCALL_PAGEDIR_MAP_TABLE | JOVE_PERM_READ, JOVE_PERM_WRITE | JOVE_PERM_READ, JOVE_PERM_WRITE, JOVE_PERM_MUTATE | |
+| SYSCALL_PAGEDIR_MAP_SHMEM | JOVE_PERM_READ, JOVE_PERM_WRITE | | JOVE_PERM_READ, JOVE_PERM_WRITE |
+| SYSCALL_PAGEDIR_UNMAP_FRAME | JOVE_PERM_READ, JOVE_PERM_WRITE | | |
+| SYSCALL_PAGEDIR_UNMAP_TABLE | JOVE_PERM_READ, JOVE_PERM_WRITE | | |
+| SYSCALL_PAGEDIR_UNMAP_SHMEM | JOVE_PERM_READ, JOVE_PERM_WRITE | | |
+
+
+#### SYSCALL_PAGEDIR_MAP_FRAME
+
+Attempts to map a given untyped memory span to the given virtual address with passed permissions.
+
+| Data | Page flags | Untyped Path Length | Virtual address | Untyped Path |
+|--------------|------------|---------------------|-------------------|--------------|
+| Size (bytes) | 1 | 2 | sizeof(void*) | path_len * 2 |
+
+If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`.
+
+If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`.
+
+If the untyped path does not point to a `JOVE_OBJ_UNTYPED` object, the kernel will return `-EBADOBJ`.
+
+If the untyped object is not aligned to `0x1000` bytes, the kernel will return `-EALIGN`.
+
+If the untyped object is not exactly `0x1000` bytes wide, the kernel will return `-EBADSIZE`.
+
+If the untyped object does not have `JOVE_PERM_MUTATE` and `JOVE_PERM_READ`, the kernel will return `-ENOPERM`.
+
+If the untyped object does not have `JOVE_PERM_WRITE` and the passed flags include the writeable bit, the kernel will return `-ENOPERM.`.
+
+If the virtual address does not have enough page table structures to support the page mapping, the kernel will return `-ENOMAP`.
+
+If the virtual address already has a page mapping, the kernel will return `-EHASMAP`.
+
+Successful mapping replaces the untyped object with a `JOVE_OBJ_NONE` object and returns `0`.
+
+
+#### SYSCALL_PAGEDIR_MAP_TABLE
+
+Attempts to map a given untyped memory span as a table for mapping further page frames onto `virtual address`.
+
+| Data | Virtual address | Untyped Path Length | Untyped Path |
+|--------------|-----------------|---------------------|--------------|
+| Size (bytes) | sizeof(void*) | 2 | path_len * 2 |
+
+If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`.
+
+If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`.
+
+If the untyped path does not point to a `JOVE_OBJ_UNTYPED` object, the kernel will return `-EBADOBJ`.
+
+If the untyped object is not aligned to `0x1000` bytes, the kernel will return `-EALIGN`.
+
+If the untyped object is not exactly `0x1000` bytes wide, the kernel will return `-EBADSIZE`.
+
+If the untyped object does not have `JOVE_PERM_MUTATE`, `JOVE_PERM_READ`, and `JOVE_PERM_WRITE`, the kernel will return `-ENOPERM`.
+
+If the virtual address already has enough tables to allocate a page frame onto them, the kernel will return `-EHASMAP`.
+
+Successful mapping replaces the untyped object with a `JOVE_OBJ_NONE` object and returns `0`.
+
+
+#### SYSCALL_PAGEDIR_MAP_SHMEM
+
+Attempts to map a shared memory page at `virtual address`. Does not consume the shared memory object.
+
+| Data | Page flags | Page offset | Shared Memory Path Length | Virtual address | Shared Memory Path |
+|--------------|------------|-------------|---------------------------|-----------------|--------------------|
+| Size (bytes) | 1 | 1 | 2 | sizeof(void*) | path_len * 2 |
+
+If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`.
+
+If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`.
+
+If the shmem path does not point to a `JOVE_OBJ_SHMEMORY` object, the kernel will return `-EBADOBJ`.
+
+If the shmem object does not have `JOVE_PERM_READ`, the kernel will return `-ENOPERM`.
+
+If the shmem object does not have `JOVE_PERM_WRITE` and the passed flags include the writeable bit, the kernel will return `-ENOPERM.`.
+
+If the virtual address does not have enough page table structures to support the page mapping, the kernel will return `-ENOMAP`.
+
+If the virtual address already has a page mapping, the kernel will return `-EHASMAP`.
+
+Successful mapping returns `0`.
+
+
+#### SYSCALL_PAGEDIR_UNMAP_FRAME
+
+Attempts to remove an untyped memory mapping from the page table at `virtual address`.
+
+| Data | Virtual address | Destination Path Length | Destination Path |
+|--------------|-----------------|-------------------------|------------------|
+| Size (bytes) | sizeof(void*) | 2 | path_len * 2 |
+
+If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`.
+
+If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`.
+
+If the destination path does not point to a `JOVE_OBJ_NONE` object, the kernel will return `-EFULL`.
+
+If the virtual address does not have a page mapping, the kernel will return `-ENOMAP`.
+
+If the virtual address does not map to an untyped page frame, the kernel will return `-EBADARG`.
+
+Successful unmapping fills the destination path with a page-sized `JOVE_OBJ_UNTYPED` object with correct permissions and return 0.
+
+
+#### SYSCALL_PAGEDIR_UNMAP_TABLE
+
+Attempts to remove a page table mapping from the page directory heirarchy at `virtual address`
+
+| Data | Virtual address | Destination Path Length | Destination Path |
+|--------------|-----------------|-------------------------|------------------|
+| Size (bytes) | sizeof(void*) | 2 | path_len * 2 |
+
+If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`.
+
+If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`.
+
+If the destination path does not point to a `JOVE_OBJ_NONE` object, the kernel will return `-EFULL`.
+
+If the table mapping the virtual address has any occupied entries, the kernel will return `-EHASMAP`.
+
+If no table mapping exists for this virtual address, the kernel will return `-ENOMAP`.
+
+Successful unmapping fills the destination path with a page-sized `JOVE_OBJ_UNTYPED` object with correct permissions and return 0.
+
+
+#### SYSCALL_PAGEDIR_UNMAP_SHMEM
+
+Attempts to unmap a shared memory page at `virtual address`.
+
+| Data | Virtual address |
+|--------------|-----------------|
+| Size (bytes) | sizeof(void*) |
+
+If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`.
+
+If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`.
+
+If the virtual address does not have a page frame associated with it, the kernel will return `-ENOMAP`.
+
+If the page frame pointed to by virtual address does not correspond to a shared memory frame, the kernel will return `-EBADOBJ`.
+
+Successful unmapping returns `0`.
diff --git a/hal/memory.h b/hal/memory.h
index 47dbf0a..6e685d6 100644
--- a/hal/memory.h
+++ b/hal/memory.h
@@ -1,3 +1,4 @@
+#include "sys/syscall.h"
#ifndef _JOVE_HAL_MEMORY_H
#define _JOVE_HAL_MEMORY_H 1
@@ -23,16 +24,21 @@ int untyped_merge(jove_owned_obj_t *a, jove_owned_obj_t *b);
int untyped_retype(jove_owned_obj_t *tgt, uint8_t newtype);
int pagedir_map_untyped_frame(
- jove_owned_obj_t *tgt, jove_owned_obj_t *untyped_obj,
+ jove_owned_obj_t *tgt, jove_perm_obj_t *untyped_obj,
uintptr_t vptr, struct syscall_pagedir_flags flg);
int pagedir_map_untyped_table(
- jove_owned_obj_t *tgt, jove_owned_obj_t *untyped_obj,
+ jove_owned_obj_t *tgt, jove_perm_obj_t *untyped_obj,
uintptr_t vptr);
+int pagedir_map_shmem_frame(
+ jove_owned_obj_t *tgt, jove_perm_obj_t *shmem_obj, uint8_t page_offset,
+ uintptr_t vptr, struct syscall_pagedir_flags flg);
int pagedir_unmap_untyped_frame(
jove_owned_obj_t *tgt, jove_owned_obj_t *dst, uintptr_t vptr);
int pagedir_unmap_untyped_table(
jove_owned_obj_t *tgt, jove_owned_obj_t *dst, uintptr_t vptr);
+int pagedir_unmap_shmem_frame(
+ jove_owned_obj_t *tgt, uintptr_t vptr);
#endif
diff --git a/hal/process.h b/hal/process.h
index 63c800f..da3e050 100644
--- a/hal/process.h
+++ b/hal/process.h
@@ -24,6 +24,6 @@ jove_owned_obj_t *process_current(void);
pid_t pcb_pid(pcb_t *pcb);
/*Returns the root kernel object directory of this PCB. */
-jove_owned_obj_t *pcb_rootdir(pcb_t *pcb);
+jove_obj_t *pcb_rootdir(pcb_t *pcb);
#endif
diff --git a/sys/link.c b/sys/link.c
index 5be9457..592fe8f 100644
--- a/sys/link.c
+++ b/sys/link.c
@@ -2,31 +2,23 @@
#include "arch/x86_64/hal/obj.h"
#include "hal/memory.h"
-void*
-obj_deref_linked(jove_owned_obj_t *obj)
+uint8_t
+link_gettype(jove_owned_obj_t *obj)
{
- switch(obj_gettype(obj)) {
- case JOVE_OBJ_LINK: return obj_deref_linked(link_deref(obj));
- default: return obj_deref(obj);
- }
+ return obj_gettype(link_deref(obj));
}
uint8_t
-obj_gettype_linked(jove_owned_obj_t *obj)
+link_getperm(jove_owned_obj_t *link)
{
- switch(obj_gettype(obj)) {
- case JOVE_OBJ_LINK: return obj_gettype_linked(link_deref(obj));
- default: return obj_gettype(obj);
- }
+ struct obj_link *linkval = obj_deref(link);
+ return linkval->permissions;
}
uint64_t
-obj_getvalue_linked(jove_owned_obj_t *obj)
+link_getvalue(jove_owned_obj_t *obj)
{
- switch(obj_gettype(obj)) {
- case JOVE_OBJ_LINK: return obj_getvalue_linked(link_deref(obj));
- default: return obj_getvalue(obj);
- }
+ return obj_getvalue(link_deref(obj));
}
jove_owned_obj_t*
@@ -36,11 +28,41 @@ link_deref(jove_owned_obj_t *link)
return obj_take(&linkval->obj);
}
-jove_owned_obj_t *link_new(jove_obj_t *tgt, jove_owned_obj_t *dst)
+jove_owned_obj_t*
+link_try_deref(jove_owned_obj_t *link)
+{
+ struct obj_link *linkval = obj_deref(link);
+ return obj_trytake(&linkval->obj);
+}
+
+jove_perm_obj_t
+link_traverse(jove_owned_obj_t *link, lockstack_t *lockstack)
+{
+ jove_perm_obj_t perm_obj = { .obj = link, .permissions = JOVE_PERM_ALL };
+ while(obj_gettype(perm_obj.obj) == JOVE_OBJ_LINK) {
+ perm_obj.permissions &= link_getperm(perm_obj.obj);
+ perm_obj.obj = lockstack_push(lockstack, link_deref(perm_obj.obj));
+ }
+ return perm_obj;
+}
+
+jove_perm_obj_t
+link_try_traverse(jove_owned_obj_t *link, lockstack_t *lockstack)
+{
+ jove_perm_obj_t perm_obj = { .obj = link, .permissions = JOVE_PERM_ALL };
+ while(perm_obj.obj != NULL && obj_gettype(perm_obj.obj) == JOVE_OBJ_LINK) {
+ perm_obj.permissions &= link_getperm(perm_obj.obj);
+ perm_obj.obj = lockstack_push(lockstack, link_deref(perm_obj.obj));
+ }
+ return perm_obj;
+}
+
+jove_owned_obj_t *link_new(jove_obj_t *tgt, jove_owned_obj_t *dst, uint16_t permissions)
{
struct obj_link *linkval = obj_deref(dst);
linkval->obj = *tgt;
linkval->refcount = 2;
+ linkval->permissions = permissions;
{
jove_owned_obj_t *tgt_owned = obj_take(tgt);
diff --git a/sys/link.h b/sys/link.h
index 37fa1e8..3f7331f 100644
--- a/sys/link.h
+++ b/sys/link.h
@@ -1,3 +1,4 @@
+#include "sys/lockstack.h"
#ifndef _JOVE_SYS_LINK_HPP
#define _JOVE_SYS_LINK_HPP 1
@@ -5,17 +6,28 @@
struct obj_link
{
- size_t refcount;
jove_obj_t obj;
+ uint16_t refcount;
+ uint8_t permissions;
};
-void *obj_deref_linked(jove_owned_obj_t *obj);
-uint8_t obj_gettype_linked(jove_owned_obj_t *obj);
-uint64_t obj_getvalue_linked(jove_owned_obj_t *obj);
+typedef struct obj_perm_group
+{
+ jove_owned_obj_t *obj;
+ uint8_t permissions;
+} jove_perm_obj_t;
+
+uint8_t link_gettype(jove_owned_obj_t *obj);
+uint8_t link_getperm(jove_owned_obj_t *link);
+uint64_t link_getvalue(jove_owned_obj_t *obj);
jove_owned_obj_t *link_deref(jove_owned_obj_t *link);
-jove_obj_t link_unlink(jove_owned_obj_t *link);
+jove_owned_obj_t *link_try_deref(jove_owned_obj_t *link);
-jove_owned_obj_t *link_new(jove_obj_t *tgt, jove_owned_obj_t *dst);
+jove_perm_obj_t link_traverse(jove_owned_obj_t *link, lockstack_t *lockstack);
+jove_perm_obj_t link_try_traverse(jove_owned_obj_t *link, lockstack_t *lockstack);
+
+jove_obj_t link_unlink(jove_owned_obj_t *link);
+jove_owned_obj_t *link_new(jove_obj_t *tgt, jove_owned_obj_t *dst, uint16_t permissions);
#endif
diff --git a/sys/lockstack.c b/sys/lockstack.c
new file mode 100644
index 0000000..7a419ac
--- /dev/null
+++ b/sys/lockstack.c
@@ -0,0 +1,30 @@
+#include "lockstack.h"
+#include "lib/printf.h"
+
+jove_owned_obj_t*
+lockstack_push(lockstack_t *stack, jove_owned_obj_t *obj)
+{
+ if(stack->depth == LOCKSTACK_MAX) {
+ klogf("lock stack exceeds %i entries\n", LOCKSTACK_MAX);
+ return NULL;
+ }
+ if(obj == NULL) return obj;
+
+ stack->stack[stack->depth++] = obj;
+ return obj;
+}
+
+jove_obj_t*
+lockstack_pop(lockstack_t *stack)
+{
+ return obj_release(stack->stack[--stack->depth]);
+}
+
+void
+lockstack_popall(lockstack_t *stack)
+{
+ for(size_t i = 0; i < stack->depth; i++)
+ obj_release(stack->stack[i]);
+ stack->depth = 0;
+}
+
diff --git a/sys/lockstack.h b/sys/lockstack.h
new file mode 100644
index 0000000..f41f9dc
--- /dev/null
+++ b/sys/lockstack.h
@@ -0,0 +1,18 @@
+#ifndef _JOVE_SYS_LOCKSTACK_H
+#define _JOVE_SYS_LOCKSTACK_H 1
+
+#include <stddef.h>
+#include "hal/obj.h"
+#include "config.h"
+
+typedef struct lockstack
+{
+ size_t depth;
+ jove_owned_obj_t *stack[LOCKSTACK_MAX];
+} lockstack_t;
+
+jove_owned_obj_t *lockstack_push(lockstack_t *stack, jove_owned_obj_t *obj);
+jove_obj_t *lockstack_pop(lockstack_t *stack);
+void lockstack_popall(lockstack_t *stack);
+
+#endif
diff --git a/sys/syscall.c b/sys/syscall.c
index 457b820..0da3475 100644
--- a/sys/syscall.c
+++ b/sys/syscall.c
@@ -24,28 +24,20 @@ int __syscall_generic_objpath(jove_owned_obj_t *objdir, size_t payload_bytes, vo
}
int
-_syscall_handle_generic(
- jove_owned_obj_t *pcb_obj,
- jove_owned_obj_t *objdir,
- jove_owned_obj_t *message_obj,
- jove_owned_obj_t *target_obj,
- struct syscall_header *header,
- size_t bytes_left,
- void *payload)
+_syscall_handle_generic(syscall_context_t *ctx)
{
- pcb_t *pcb = obj_deref(pcb_obj);
- klogf("Process %i encountered stub syscall on object %P\n", pcb_pid(pcb), header->path, header->pathlen);
- return EBADOBJ;
+ pcb_t *pcb = obj_deref(ctx->pcb);
+ klogf("Process %i encountered stub syscall on object %P\n", pcb_pid(pcb), ctx->header->path, ctx->header->pathlen);
+ return -EBADOBJ;
}
static const syscall_handle_t s_syscall_handles[128] = {
- [JOVE_OBJ_NONE] = NULL,
[JOVE_OBJ_UNTYPED] = _syscall_handle_untyped,
[JOVE_OBJ_OBJDIR] = _syscall_handle_objdir,
[JOVE_OBJ_PAGEDIR] = _syscall_handle_pagedir,
[JOVE_OBJ_PROCESSOR] = _syscall_handle_generic,
- [JOVE_OBJ_HWMEMORY] = _syscall_handle_generic,
- [JOVE_OBJ_PROCESS] = _syscall_handle_generic,
+ [JOVE_OBJ_SHMEMORY] = _syscall_handle_generic,
+ [JOVE_OBJ_PCB] = _syscall_handle_generic,
[JOVE_OBJ_INT_HANDLE] = _syscall_handle_generic,
[JOVE_OBJ_INITRD_FILE] = _syscall_handle_generic,
[JOVE_OBJ_FRAMEBUFFER] = _syscall_handle_generic,
@@ -55,36 +47,63 @@ static const syscall_handle_t s_syscall_handles[128] = {
};
int
+_syscall_handle_switch(syscall_context_t *ctx)
+{
+ uint8_t target_type = obj_gettype(ctx->target.obj);
+ if(target_type > 0x7F) {
+ return _syscall_handle_arch(ctx);
+ }
+ else {
+ syscall_handle_t call_handle = s_syscall_handles[target_type];
+ if(call_handle == NULL) {
+ klogf("Tried to call syscall on object %P which doesn't support syscalls!\n",
+ ctx->header->path, ctx->header->pathlen);
+ return -EBADOBJ;
+ }
+ else {
+ return call_handle(ctx);
+ }
+ }
+}
+
+int
syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen)
{
uint16_t *message_path = (uint16_t*)&message_path_raw;
if(message_pathlen > sizeof(uintmax_t) >> 1) {
- return EBADPATH;
+ return -EBADPATH;
}
- jove_owned_obj_t *pcb_obj = process_current();
- pcb_t *pcb = obj_deref(pcb_obj);
- jove_owned_obj_t *objdir = pcb_rootdir(pcb);
- jove_owned_obj_t *message_obj = objdir_trygetobj(objdir, message_path, message_pathlen);
+ syscall_context_t ctx;
+ ctx.lockstack.depth = 0;
int sysret = 0;
- if(message_obj == NULL) {
- klogf("Process %i tried to call syscall with bad message %P : %s\n",
+ ctx.pcb = lockstack_push(&ctx.lockstack, process_current());
+ pcb_t *pcb = obj_deref(ctx.pcb);
+ ctx.objdir = lockstack_push(&ctx.lockstack, obj_take(pcb_rootdir(pcb)));
+
+ ctx.message = link_try_traverse(
+ lockstack_push(&ctx.lockstack, objdir_trygetobj(
+ ctx.objdir, message_path, message_pathlen)),
+ &ctx.lockstack);
+
+ if(ctx.message.obj == NULL) {
+ klogf("Process %i failed to get message %P : %s\n",
pcb_pid(pcb), message_path, message_pathlen, errstr(errno));
sysret = -errno;
- goto release_premsg;
+ goto release_return;
}
- if(obj_gettype_linked(message_obj) != JOVE_OBJ_MESSAGE) {
+ if(obj_gettype(ctx.message.obj) != JOVE_OBJ_MESSAGE) {
klogf("Process %i tried to call syscall with invalid object %P\n",
pcb_pid(pcb), message_path, message_pathlen);
sysret = -EBADOBJ;
goto release_return;
}
- size_t messagelen = message_len(message_obj);
- void *messagedata = message_data(message_obj);
+ size_t messagelen = message_len(ctx.message.obj);
+ void *messagedata = message_data(ctx.message.obj);
struct syscall_header *header = messagedata;
size_t bytes_needed = sizeof(struct syscall_header) + header->pathlen * 2;
@@ -94,8 +113,14 @@ syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen)
sysret = -ETOOSMALL;
goto release_return;
}
- jove_owned_obj_t *target = objdir_trygetobj(objdir, header->path, header->pathlen);
- if(target == 0) {
+
+ ctx.header = header;
+ ctx.bytes_left = messagelen - bytes_needed;
+ ctx.payload = (void*)((uintptr_t)header + bytes_needed);
+
+ ctx.target.obj = lockstack_push(&ctx.lockstack,
+ objdir_trygetobj(ctx.objdir, header->path, header->pathlen));
+ if(ctx.target.obj == 0) {
//Could not find payload target in pcb rootdir.
klogf("Process %i tried to call syscall with bad target path %P : %s\n",
pcb_pid(pcb), header->path, header->pathlen, errstr(errno));
@@ -103,28 +128,10 @@ syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen)
goto release_return;
}
- uint8_t target_type = obj_gettype(target);
- size_t bytes_left = messagelen - bytes_needed;
- if(target_type > 0x7F) {
- sysret = _syscall_handle_arch(
- pcb_obj, objdir, message_obj, target,
- header, bytes_left, messagedata + bytes_needed);
- }else{
- syscall_handle_t call_handle = s_syscall_handles[obj_gettype(target)];
- if(call_handle == NULL) {
- klogf("Process %i tried to call syscall on object %P which doesn't support syscalls!\n",
- pcb_pid(pcb), header->path, header->pathlen);
- sysret = -EBADOBJ;
- }else
- sysret = call_handle(
- pcb_obj, objdir, message_obj, target,
- header, bytes_left, messagedata + bytes_needed);
- }
- obj_release(target);
+ ctx.target.permissions = JOVE_PERM_ALL;
+ sysret = _syscall_handle_switch(&ctx);
+
release_return:
- obj_release(message_obj);
-release_premsg:
- obj_release(objdir);
- obj_release(pcb_obj);
+ lockstack_popall(&ctx.lockstack);
return sysret;
}
diff --git a/sys/syscall.h b/sys/syscall.h
index 9f56447..e6358cb 100644
--- a/sys/syscall.h
+++ b/sys/syscall.h
@@ -1,8 +1,11 @@
#ifndef _JOVE_SYS_SYSCALL_H
#define _JOVE_SYS_SYSCALL_H 1
+#include "config.h"
#include "api/syscall.h"
#include "hal/obj.h"
+#include "lockstack.h"
+#include "link.h"
#include <stdint.h>
#define CHECK_TOOSMALL(required, present, fail_msg) \
@@ -20,29 +23,39 @@ do { if(obj == NULL) { \
#define CHECK_OBJTYPE(obj, type, fail_msg) \
do { if(obj_gettype(obj) != type) { \
kprintf("%s: %s\n", __func__, fail_msg); \
- obj_release(obj); \
return -EBADOBJ; \
} } while(0)
-#define SYSCALL_FUNCTION_ARGS \
- jove_owned_obj_t*, /*PCB object*/ \
- jove_owned_obj_t*, /*Objdir object*/ \
- jove_owned_obj_t*, /*Message object*/ \
- jove_owned_obj_t*, /*Target object*/ \
- struct syscall_header*, /*Syscall header*/ \
- size_t, /*How many bytes are left in the message*/ \
- void* /*The bytes left in the message.*/
+#define CHECK_OBJPERM(obj, perms, fail_msg) \
+ do { if((obj.permissions & perms) == 0) { \
+ kprintf("%s: %s\n", __func__, fail_msg); \
+ return -EPERM; \
+ } } while(0)
-typedef int (*syscall_handle_t)(SYSCALL_FUNCTION_ARGS);
+typedef struct syscall_state
+{
+ lockstack_t lockstack;
+ jove_owned_obj_t *pcb;
+ jove_owned_obj_t *objdir;
+ jove_perm_obj_t message;
+ jove_perm_obj_t target;
+ struct syscall_header *header;
+ size_t bytes_left;
+ void *payload;
+} syscall_context_t;
+
+typedef int (*syscall_handle_t)(syscall_context_t*);
int __syscall_generic_objpath(jove_owned_obj_t *objdir, size_t bytes_left, void *payload_data, jove_owned_obj_t **retobj);
-int _syscall_handle_generic(SYSCALL_FUNCTION_ARGS);
-int _syscall_handle_arch(SYSCALL_FUNCTION_ARGS);
+int _syscall_handle_switch(syscall_context_t *ctx);
+
+int _syscall_handle_generic(syscall_context_t *ctx);
+int _syscall_handle_arch(syscall_context_t *ctx);
-int _syscall_handle_vtt(SYSCALL_FUNCTION_ARGS);
-int _syscall_handle_objdir(SYSCALL_FUNCTION_ARGS);
-int _syscall_handle_untyped(SYSCALL_FUNCTION_ARGS);
-int _syscall_handle_pagedir(SYSCALL_FUNCTION_ARGS);
+int _syscall_handle_vtt(syscall_context_t *ctx);
+int _syscall_handle_objdir(syscall_context_t *ctx);
+int _syscall_handle_untyped(syscall_context_t *ctx);
+int _syscall_handle_pagedir(syscall_context_t *ctx);
#endif
diff --git a/sys/syscall_objdir.c b/sys/syscall_objdir.c
index 277639f..5a6786d 100644
--- a/sys/syscall_objdir.c
+++ b/sys/syscall_objdir.c
@@ -25,20 +25,15 @@ s_syscall_objdir_objtype(
}
int
-_syscall_handle_objdir(
- jove_owned_obj_t *pcb_obj,
- jove_owned_obj_t *objdir,
- jove_owned_obj_t *message_obj,
- jove_owned_obj_t *target_obj,
- struct syscall_header *header,
- size_t bytes_left,
- void *payload)
+_syscall_handle_objdir(syscall_context_t *ctx)
{
- switch(header->callid) {
+ switch(ctx->header->callid) {
case SYSCALL_OBJDIR_OBJTYPE:
- return s_syscall_objdir_objtype(objdir, target_obj, bytes_left, payload);
+ if(ctx->target.permissions & SYSCALL_PERM_OBJDIR_OBJTYPE)
+ return s_syscall_objdir_objtype(
+ ctx->objdir, ctx->target.obj, ctx->bytes_left, ctx->payload);
+ return -EPERM;
default:
- kprintf("syscall_handle_objdir: Objdir does not support syscall %i\n", header->callid);
- return EBADARG;
+ return -EBADCALL;
}
}
diff --git a/sys/syscall_pagedir.c b/sys/syscall_pagedir.c
index 33acc87..961c477 100644
--- a/sys/syscall_pagedir.c
+++ b/sys/syscall_pagedir.c
@@ -5,12 +5,13 @@
#include "syscall.h"
static int
-s_syscall_pagedir_map(
+s_get_untyped(
+ lockstack_t *lockstack,
jove_owned_obj_t *objdir,
- jove_owned_obj_t *target_obj,
+ jove_owned_obj_t *pml4,
size_t payload_bytes,
void *payload_data,
- jove_owned_obj_t **untyped_ret)
+ jove_perm_obj_t *untyped_ret)
{
size_t bytes_needed = sizeof(struct syscall_pagedir_map);
CHECK_TOOSMALL(bytes_needed, payload_bytes,
@@ -27,40 +28,44 @@ s_syscall_pagedir_map(
"Message too small for untyped path.");
errno = 0;
- jove_owned_obj_t *untyped_obj = objdir_trygetobj(objdir,
- payload->untyped_path, payload->untyped_pathlen);
+ jove_perm_obj_t untyped = link_try_traverse(
+ lockstack_push(lockstack, objdir_trygetobj(
+ objdir, payload->untyped_path, payload->untyped_pathlen)),
+ lockstack);
if(errno) {
kprintf("%s: Untyped obj failed for the reason: %s\n", __func__, errstr(errno));
return errno;
}
- CHECK_OBJTYPE(untyped_obj, JOVE_OBJ_UNTYPED,
+ CHECK_OBJTYPE(untyped.obj, JOVE_OBJ_UNTYPED,
"Untyped path does not point to an untyped object.");
- jove_untyped_t *untyped_data = obj_deref(untyped_obj);
+ CHECK_OBJPERM(untyped, JOVE_PERM_MUTATE,
+ "Untyped object does not have MUTATE permission.");
+
+ jove_untyped_t *untyped_data = obj_deref(untyped.obj);
if((uintptr_t)untyped_data & 0xFFF) {
kprintf("%s: Untyped object is not page aligned.\n", __func__);
- obj_release(untyped_obj);
return EALIGN;
}
if(untyped_data->limit != 0x1000) {
kprintf("%s: Untyped object is not page sized. (expected 0x1000 got 0x%X)\n", __func__,
untyped_data->limit);
- obj_release(untyped_obj);
return EBADSIZE;
}
- *untyped_ret = untyped_obj;
+ *untyped_ret = untyped;
return 0;
}
static int
s_syscall_pagedir_unmap(
+ lockstack_t *lockstack,
jove_owned_obj_t *objdir,
- jove_owned_obj_t *target_obj,
+ jove_owned_obj_t *pagedir,
size_t payload_bytes,
void *payload_data,
- jove_owned_obj_t **none_ret)
+ jove_perm_obj_t *none_ret)
{
size_t bytes_needed = sizeof(struct syscall_pagedir_unmap);
CHECK_TOOSMALL(bytes_needed, payload_bytes,
@@ -76,117 +81,186 @@ s_syscall_pagedir_unmap(
CHECK_TOOSMALL(bytes_needed, payload_bytes,
"Message too small for none path");
- jove_owned_obj_t *none_obj = objdir_trygetobj(objdir,
- payload->none_path, payload->none_pathlen);
+ jove_perm_obj_t none = link_try_traverse(
+ lockstack_push(lockstack, objdir_trygetobj(
+ objdir, payload->none_path, payload->none_pathlen)),
+ lockstack);
if(errno) {
kprintf("%s: None obj retrieval failed for the reason: %s\n",
__func__, errstr(errno));
return errno;
}
- CHECK_OBJTYPE(none_obj, JOVE_OBJ_NONE,
+ CHECK_OBJTYPE(none.obj, JOVE_OBJ_NONE,
"None path does not point to none object.");
- *none_ret = none_obj;
+ *none_ret = none;
return 0;
}
static int
s_syscall_pagedir_map_frame(
+ lockstack_t *lockstack,
jove_owned_obj_t *objdir,
- jove_owned_obj_t *target_obj,
+ jove_owned_obj_t *pagedir,
size_t payload_bytes,
void *payload_data)
{
- jove_owned_obj_t *untyped_obj = NULL;
- int sysret = s_syscall_pagedir_map(objdir, target_obj, payload_bytes, payload_data, &untyped_obj);
+ jove_perm_obj_t untyped = { .obj = NULL, .permissions = 0 };
+ int sysret = s_get_untyped(lockstack, objdir, pagedir, payload_bytes, payload_data, &untyped);
if(sysret != 0) {
return sysret;
}
struct syscall_pagedir_map *payload = payload_data;
- sysret = pagedir_map_untyped_frame(target_obj, untyped_obj, payload->virtual_address, payload->flags);
+ sysret = pagedir_map_untyped_frame(pagedir, &untyped, payload->virtual_address, payload->page_flags);
if(sysret == 0)
- obj_settype(untyped_obj, JOVE_OBJ_NONE);
+ obj_settype(untyped.obj, JOVE_OBJ_NONE);
- obj_release(untyped_obj);
return sysret;
}
static int
s_syscall_pagedir_map_table(
+ lockstack_t *lockstack,
jove_owned_obj_t *objdir,
- jove_owned_obj_t *target_obj,
+ jove_owned_obj_t *pagedir,
size_t payload_bytes,
void *payload_data)
{
- jove_owned_obj_t *untyped_obj = NULL;
- int sysret = s_syscall_pagedir_map(objdir, target_obj, payload_bytes, payload_data, &untyped_obj);
+ jove_perm_obj_t untyped = { .obj = NULL, .permissions = 0 };
+ int sysret = s_get_untyped(lockstack, objdir, pagedir, payload_bytes, payload_data, &untyped);
if(sysret != 0) {
return sysret;
}
struct syscall_pagedir_map *payload = payload_data;
- sysret = pagedir_map_untyped_table(target_obj, untyped_obj, payload->virtual_address);
+ sysret = pagedir_map_untyped_table(pagedir, &untyped, payload->virtual_address);
if(sysret == 0)
- obj_settype(untyped_obj, JOVE_OBJ_NONE);
+ obj_settype(untyped.obj, JOVE_OBJ_NONE);
- obj_release(untyped_obj);
return sysret;
}
static int
+s_syscall_pagedir_map_shmem(
+ lockstack_t *lockstack,
+ jove_owned_obj_t *objdir,
+ jove_owned_obj_t *pagedir,
+ size_t payload_bytes,
+ void *payload_data)
+{
+ size_t bytes_needed = sizeof(struct syscall_pagedir_map_shmem);
+ CHECK_TOOSMALL(bytes_needed, payload_bytes,
+ "Message too small for payload.");
+
+ struct syscall_pagedir_map_shmem *payload = payload_data;
+ if(payload->virtual_address > 0xFFFF800000000000ULL) {
+ kprintf("%s: Virtual address is above user limit.\n", __func__);
+ return EBADARG;
+ }
+
+ bytes_needed += payload->shmem_pathlen << 1;
+ CHECK_TOOSMALL(bytes_needed, payload_bytes,
+ "Message too small for untyped path.");
+
+ errno = 0;
+ jove_perm_obj_t shmem = link_try_traverse(
+ lockstack_push(lockstack, objdir_trygetobj(
+ objdir, payload->shmem_path, payload->shmem_pathlen)),
+ lockstack);
+ if(errno) {
+ klogf("Shared memory obj failed for the reason: %s\n", errstr(errno));
+ return errno;
+ }
+
+ CHECK_OBJTYPE(shmem.obj, JOVE_OBJ_SHMEMORY,
+ "Shared memory path does not point to a shared memory object.");
+
+ uintmax_t shmem_value = obj_getvalue(shmem.obj);
+ uint8_t shmem_pages = shmem_value & 0xFF;
+
+ if(payload->page_offset >= shmem_pages) {
+ klogf("Page offset goes beyond size of shared memory object: (%i >= %i)\n",
+ payload->page_offset, shmem_pages);
+ return -EOOB;
+ }
+
+ return pagedir_map_shmem_frame(pagedir, &shmem, payload->page_offset,
+ payload->virtual_address, payload->page_flags);
+}
+
+static int
s_syscall_pagedir_unmap_frame(
+ lockstack_t *lockstack,
jove_owned_obj_t *objdir,
- jove_owned_obj_t *target_obj,
+ jove_owned_obj_t *pagedir,
size_t payload_bytes,
void *payload_data)
{
- jove_owned_obj_t *none_obj;
- int sysret = s_syscall_pagedir_unmap(objdir, target_obj, payload_bytes, payload_data, &none_obj);
+ jove_perm_obj_t none;
+ int sysret = s_syscall_pagedir_unmap(lockstack, objdir, pagedir, payload_bytes, payload_data, &none);
if(!sysret) return sysret;
struct syscall_pagedir_unmap *payload = payload_data;
- return pagedir_unmap_untyped_frame(target_obj, none_obj, payload->virtual_address);
+ return pagedir_unmap_untyped_frame(pagedir, none.obj, payload->virtual_address);
}
static int
s_syscall_pagedir_unmap_table(
+ lockstack_t *lockstack,
jove_owned_obj_t *objdir,
- jove_owned_obj_t *target_obj,
+ jove_owned_obj_t *pagedir,
size_t payload_bytes,
void *payload_data)
{
- jove_owned_obj_t *none_obj;
- int sysret = s_syscall_pagedir_unmap(objdir, target_obj, payload_bytes, payload_data, &none_obj);
+ jove_perm_obj_t none;
+ int sysret = s_syscall_pagedir_unmap(lockstack, objdir, pagedir, payload_bytes, payload_data, &none);
if(!sysret) return sysret;
struct syscall_pagedir_unmap *payload = payload_data;
- return pagedir_unmap_untyped_table(target_obj, none_obj, payload->virtual_address);
+ return pagedir_unmap_untyped_table(pagedir, none.obj, payload->virtual_address);
}
int
-_syscall_handle_pagedir(
- jove_owned_obj_t *pcb_obj,
- jove_owned_obj_t *objdir,
- jove_owned_obj_t *message_obj,
- jove_owned_obj_t *target_obj,
- struct syscall_header *header,
- size_t bytes_left,
- void *payload)
+_syscall_handle_pagedir(syscall_context_t *ctx)
{
+ lockstack_t *lockstack = &ctx->lockstack;
+ struct syscall_header *header = ctx->header;
+ jove_owned_obj_t *objdir = ctx->objdir;
+ jove_perm_obj_t *target = &ctx->target;
+ size_t bytes_left = ctx->bytes_left;
+ void *payload = ctx->payload;
+
switch(header->callid) {
case SYSCALL_PAGEDIR_MAP_FRAME:
- return s_syscall_pagedir_map_frame(objdir, target_obj, bytes_left, payload);
+ if(target->permissions & SYSCALL_PERM_PAGEDIR_MAP_FRAME)
+ return s_syscall_pagedir_map_frame(lockstack, objdir, target->obj, bytes_left, payload);
+ return -EPERM;
+
case SYSCALL_PAGEDIR_MAP_TABLE:
- return s_syscall_pagedir_map_table(objdir, target_obj, bytes_left, payload);
+ if(target->permissions & SYSCALL_PERM_PAGEDIR_MAP_TABLE)
+ return s_syscall_pagedir_map_table(lockstack, objdir, target->obj, bytes_left, payload);
+ return -EPERM;
+
+ case SYSCALL_PAGEDIR_MAP_SHMEM:
+ if(target->permissions & SYSCALL_PERM_PAGEDIR_MAP_SHMEM)
+ return s_syscall_pagedir_map_shmem(lockstack, objdir, target->obj, bytes_left, payload);
+ return -EPERM;
+
case SYSCALL_PAGEDIR_UNMAP_FRAME:
- return s_syscall_pagedir_unmap_frame(objdir, target_obj, bytes_left, payload);
+ if(target->permissions & SYSCALL_PERM_PAGEDIR_UNMAP_FRAME)
+ return s_syscall_pagedir_unmap_frame(lockstack, objdir, target->obj, bytes_left, payload);
+ return -EPERM;
+
case SYSCALL_PAGEDIR_UNMAP_TABLE:
- return s_syscall_pagedir_unmap_table(objdir, target_obj, bytes_left, payload);
+ if(target->permissions & SYSCALL_PERM_PAGEDIR_UNMAP_TABLE)
+ return s_syscall_pagedir_unmap_table(lockstack, objdir, target->obj, bytes_left, payload);
+ return -EPERM;
+
default:
kprintf("syscall_handle_pagedir: Pagedir does not support syscall %i\n", header->callid);
return EBADARG;
diff --git a/sys/syscall_untyped.c b/sys/syscall_untyped.c
index a5659a6..a117387 100644
--- a/sys/syscall_untyped.c
+++ b/sys/syscall_untyped.c
@@ -6,6 +6,7 @@
static int
s_syscall_untyped_split(
+ lockstack_t *lockstack,
jove_owned_obj_t *objdir,
jove_owned_obj_t *target_obj,
size_t payload_bytes,
@@ -18,19 +19,24 @@ s_syscall_untyped_split(
bytes_needed += payload->dest_pathlen * 2;
CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for destination path!");
- jove_owned_obj_t *dst_obj = objdir_getobj(objdir, payload->dest_path, payload->dest_pathlen);
- CHECK_OBJTYPE(dst_obj, JOVE_OBJ_NONE, "Destination path is occupied!");
+ jove_perm_obj_t dest = link_try_traverse(
+ lockstack_push(lockstack,
+ objdir_trygetobj(objdir, payload->dest_path, payload->dest_pathlen)),
+ lockstack);
+
+ CHECK_OBJTYPE(dest.obj, JOVE_OBJ_NONE, "Destination path is occupied!");
if(payload->bytes < JOVE_UNTYPED_MINSIZE) {
klogf("Destination untyped would be too small. (%X < %X)\n",
payload->bytes, JOVE_UNTYPED_MINSIZE);
- return EBADARG;
+ return -ETOOBIG;
}
- return untyped_split(target_obj, dst_obj, payload->bytes);
+ return untyped_split(target_obj, dest.obj, payload->bytes);
}
static int
s_syscall_untyped_merge(
+ lockstack_t *lockstack,
jove_owned_obj_t *objdir,
jove_owned_obj_t *target_obj,
size_t payload_bytes,
@@ -43,41 +49,51 @@ s_syscall_untyped_merge(
bytes_needed += payload->pathlen * 2;
CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for second path!");
- jove_owned_obj_t *snd_obj = objdir_getobj(objdir, payload->path, payload->pathlen);
- CHECK_OBJTYPE(snd_obj, JOVE_OBJ_UNTYPED, "Second object is not an untyped!");
+ jove_perm_obj_t untyped = link_try_traverse(
+ lockstack_push(lockstack,
+ objdir_getobj(objdir, payload->path, payload->pathlen)),
+ lockstack);
+ CHECK_OBJTYPE(untyped.obj, JOVE_OBJ_UNTYPED, "Second object is not an untyped!");
+ CHECK_OBJPERM(untyped, SYSCALL_PERM_UNTYPED_MERGE, "Second untyped does not have permission to merge!");
- int sysret = untyped_merge(target_obj, snd_obj);
- if(obj_gettype(snd_obj) == JOVE_OBJ_UNTYPED) {
+ int sysret = untyped_merge(target_obj, untyped.obj);
+ if(obj_gettype(untyped.obj) == JOVE_OBJ_UNTYPED) {
//Untyped merged into second object. We need to switch objects.
obj_settype(target_obj, JOVE_OBJ_UNTYPED);
- obj_setvalue(target_obj, obj_getvalue(snd_obj));
- obj_settype(snd_obj, JOVE_OBJ_NONE);
+ obj_setvalue(target_obj, obj_getvalue(untyped.obj));
+ obj_settype(untyped.obj, JOVE_OBJ_NONE);
}
return sysret;
}
-int _syscall_handle_untyped(
- jove_owned_obj_t* pcb_obj,
- jove_owned_obj_t* objdir,
- jove_owned_obj_t* message_obj,
- jove_owned_obj_t* target_obj,
- struct syscall_header* header,
- size_t payload_bytes,
- void* payload)
+int _syscall_handle_untyped(syscall_context_t *ctx)
{
- switch(header->callid) {
- case SYSCALL_UNTYPED_ADDRESS:
- return untyped_address(target_obj);
+ switch(ctx->header->callid) {
+ case SYSCALL_UNTYPED_ADDRESS:
+ if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_ADDRESS)
+ return untyped_address(ctx->target.obj);
+ return -EPERM;
+
case SYSCALL_UNTYPED_SIZE:
- return untyped_size(target_obj);
+ if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_SIZE)
+ return untyped_size(ctx->target.obj);
+ return -EPERM;
+
case SYSCALL_UNTYPED_SPLIT:
- return s_syscall_untyped_split(objdir, target_obj, payload_bytes, payload);
+ if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_SPLIT)
+ return s_syscall_untyped_split(
+ &ctx->lockstack, ctx->objdir, ctx->target.obj, ctx->bytes_left, ctx->payload);
+ return -EPERM;
+
case SYSCALL_UNTYPED_MERGE:
- return s_syscall_untyped_merge(objdir, target_obj, payload_bytes, payload);
+ if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_MERGE)
+ return s_syscall_untyped_merge(
+ &ctx->lockstack, ctx->objdir, ctx->target.obj, ctx->bytes_left, ctx->payload);
+ return -EPERM;
+
default:
- kprintf("syscall_untyped: Untyped object does not support syscall %i\n", header->callid);
- return -EBADARG;
+ return -EBADCALL;
}
return 0;
}
diff --git a/sys/syscall_vtt.c b/sys/syscall_vtt.c
index 4dadd6c..dad05ba 100644
--- a/sys/syscall_vtt.c
+++ b/sys/syscall_vtt.c
@@ -20,20 +20,14 @@ s_syscall_vtt_write(
}
int
-_syscall_handle_vtt(
- jove_owned_obj_t *pcb_obj,
- jove_owned_obj_t *objdir,
- jove_owned_obj_t *message_obj,
- jove_owned_obj_t *target_obj,
- struct syscall_header *header,
- size_t bytes_left,
- void *payload_data)
+_syscall_handle_vtt(syscall_context_t *ctx)
{
- switch(header->callid) {
- case 0:
- return s_syscall_vtt_write(target_obj, bytes_left, payload_data);
+
+ switch(ctx->header->callid) {
+ case SYSCALL_VTT_WRITE:
+ return s_syscall_vtt_write(ctx->target.obj, ctx->bytes_left, ctx->payload);
default:
- kprintf("syscall_vtt: vtt object does not support syscall %i\n", header->callid);
- return EOOB;
+ klogf("vtt object does not support syscall %i\n", ctx->header->callid);
+ return -EBADCALL;
}
}