From 1f50072f5eb98d88a5483f1ddc7ad723c4a9abe8 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Wed, 5 Nov 2025 10:44:08 -0500 Subject: [PATCH 01/96] extfs: Optimize inode reads --- src/drivers/generic/extfs/helper.c | 122 ++++++++++++++++++++++---- src/drivers/generic/extfs/interface.c | 23 ++--- 2 files changed, 117 insertions(+), 28 deletions(-) diff --git a/src/drivers/generic/extfs/helper.c b/src/drivers/generic/extfs/helper.c index caa19c38..8a109c34 100644 --- a/src/drivers/generic/extfs/helper.c +++ b/src/drivers/generic/extfs/helper.c @@ -213,8 +213,7 @@ void ext_ino_foreach_block(ext_cache* cache, } struct read_block_packet { - void* buffer; - size_t buffer_offset; + uint32_t* blocks; size_t count; size_t start_offset; size_t current_offset; @@ -233,18 +232,7 @@ static iterate_decision read_cb(ext_cache* cache, ext_inode* inode, uint32_t *bl decision = ITERATE_DECISION_STOP; goto out1; } - void* const buff = (void*)((uintptr_t)packet->buffer + packet->buffer_offset); - if (!block) - memzero(buff, cache->block_size); // sparse block - else - { - page* pg = nullptr; - void* data = ext_read_block(cache, *block, &pg); - MmH_RefPage(pg); - memcpy(buff, data, OBOS_MIN(packet->count - packet->buffer_offset, cache->block_size)); - MmH_DerefPage(pg); - } - packet->buffer_offset += cache->block_size; + packet->blocks[(packet->current_offset - packet->start_offset) / cache->block_size] = block ? *block : UINT32_MAX; out1: packet->current_offset += cache->block_size; @@ -262,11 +250,97 @@ obos_status ext_ino_read_blocks(ext_cache* cache, uint32_t ino, size_t offset, s return OBOS_STATUS_INVALID_ARGUMENT; if ((offset + count) > inode->blocks*512) count = (offset + count) - inode->blocks*512; - struct read_block_packet userdata = {.buffer=buffer,.start_offset=offset,.count=count,.buffer_offset=0}; + uint32_t nBlocks = count /= cache->block_size; + uint32_t* blocks = ZeroAllocate(OBOS_KernelAllocator, nBlocks, sizeof(uint32_t), nullptr); + struct read_block_packet userdata = {.blocks=blocks,.start_offset=offset,.count=count}; ext_ino_foreach_block(cache, ino, read_cb, &userdata); MmH_DerefPage(pg); + uint32_t current_block_base = 0; + uint32_t current_block_index = 0; + uint32_t current_block_count = 0; + bool read_current = false; + irp** irps = nullptr; + size_t nIrps = 0; + bool refresh_next = true; + for (uint32_t i = 0; i < nBlocks; i++) + { + if (blocks[i] == UINT32_MAX) + { + // TODO: Make that asynchronous? + memzero((void*)((uintptr_t)buffer + i*cache->block_size), cache->block_size); + refresh_next = true; + continue; + } + if (refresh_next) + { + read_current = false; + refresh_next = false; + current_block_base = blocks[i]; + ++current_block_count; + current_block_index = i; + continue; + } + if (blocks[i] == (current_block_base + current_block_count)) + { + read_current = false; + ++current_block_count; + continue; + } + irp* req = VfsH_IRPAllocate(); + VfsH_IRPBytesToBlockCount(cache->vn, current_block_count*cache->block_size, &req->blkCount); + VfsH_IRPBytesToBlockCount(cache->vn, current_block_base*cache->block_size, &req->blkOffset); + req->vn = cache->vn; + req->buff = (void*)((uintptr_t)buffer + current_block_index*cache->block_size); + req->op = IRP_READ; + VfsH_IRPSubmit(req, nullptr); + read_current = true; + if (req->evnt && !Core_EventGetState(req->evnt)) + { + size_t oldsize = nIrps*sizeof(irp*); + nIrps++; + irps = Reallocate(OBOS_KernelAllocator, irps, nIrps*sizeof(irp*), oldsize, nullptr); + irps[nIrps-1] = req; + } + if (blocks[i] == UINT32_MAX) + continue; + current_block_index = i; + current_block_base = blocks[i]; + current_block_count++; + } + if (!read_current) + { + irp* req = VfsH_IRPAllocate(); + VfsH_IRPBytesToBlockCount(cache->vn, current_block_count*cache->block_size, &req->blkCount); + VfsH_IRPBytesToBlockCount(cache->vn, current_block_base*cache->block_size, &req->blkOffset); + req->vn = cache->vn; + req->buff = (void*)((uintptr_t)buffer + current_block_index*cache->block_size); + req->op = IRP_READ; + VfsH_IRPSubmit(req, nullptr); + read_current = true; + if (req->evnt && !Core_EventGetState(req->evnt)) + { + size_t oldsize = nIrps*sizeof(irp*); + nIrps++; + irps = Reallocate(OBOS_KernelAllocator, irps, nIrps*sizeof(irp*), oldsize, nullptr); + irps[nIrps-1] = req; + } + else + { + VfsH_IRPWait(req); + VfsH_IRPUnref(req); + } + } + for (size_t i = 0; i < nIrps; i++) + { + VfsH_IRPWait(irps[i]); + VfsH_IRPUnref(irps[i]); + irps[i] = nullptr; + } + Free(OBOS_KernelAllocator, irps, nIrps*sizeof(irp*)); + + Free(OBOS_KernelAllocator, blocks, nBlocks*sizeof(uint32_t)); if (nRead) - *nRead = userdata.buffer_offset; + *nRead = count; return userdata.status; } @@ -663,7 +737,13 @@ uint32_t allocate_bmp(ext_cache* cache, const uint32_t* block_group_ptr, int wha uint32_t ext_ino_allocate(ext_cache* cache, const uint32_t* block_group_ptr) { - return allocate_bmp(cache, block_group_ptr, ALLOC_INODE); + uint32_t ret = allocate_bmp(cache, block_group_ptr, ALLOC_INODE); + ext_bgd* bgd = &cache->bgdt[ext_ino_get_block_group(cache, ret)]; + bgd->free_inodes--; + cache->superblock.free_inode_count--; + ext_writeback_sb(cache); + ext_writeback_bgd(cache, ext_ino_get_block_group(cache, ret)); + return ret; } void ext_ino_free(ext_cache* cache, uint32_t ino) @@ -706,7 +786,13 @@ void ext_ino_free(ext_cache* cache, uint32_t ino) uint32_t ext_blk_allocate(ext_cache* cache, const uint32_t* block_group_ptr) { - return allocate_bmp(cache, block_group_ptr, ALLOC_BLOCK); + uint32_t blk = allocate_bmp(cache, block_group_ptr, ALLOC_BLOCK); + ext_bgd* bgd = &cache->bgdt[blk/cache->blocks_per_group]; + bgd->free_blocks--; + cache->superblock.free_block_count--; + ext_writeback_sb(cache); + ext_writeback_bgd(cache, blk/cache->blocks_per_group); + return blk; } void ext_blk_free(ext_cache* cache, uint32_t blk) diff --git a/src/drivers/generic/extfs/interface.c b/src/drivers/generic/extfs/interface.c index f3a453e0..6b5d232b 100644 --- a/src/drivers/generic/extfs/interface.c +++ b/src/drivers/generic/extfs/interface.c @@ -210,6 +210,7 @@ obos_status vnode_search(void** vn_found, dev_desc desc, void* dev_vn) ext_inode_handle* hnd = (void*)desc; cache = hnd->cache; ino = hnd->ino; + OBOS_ENSURE(cache); } *vn_found = ext_make_vnode(cache, ino, nullptr); @@ -322,11 +323,14 @@ static void on_match(ext_inode** const inode, ext_cache* const cache) { uint32_t ino = dent->ino; - size_t old_size = *nToRead; - *nToRead = le32_to_host((*inode)->blocks) * 512; - *buffer = Reallocate(EXT_Allocator, *buffer, *nToRead, old_size, nullptr); - ext_ino_read_blocks(cache, ino, 0, *nToRead, *buffer, nullptr); - *offset = 0; + if (dent->file_type == EXT2_FT_DIR) + { + size_t old_size = *nToRead; + *nToRead = le32_to_host((*inode)->blocks) * 512; + *buffer = Reallocate(EXT_Allocator, *buffer, *nToRead, old_size, nullptr); + ext_ino_read_blocks(cache, ino, 0, *nToRead, *buffer, nullptr); + *offset = 0; + } MmH_DerefPage(*pg); *inode = ext_read_inode_pg(cache, ino, pg); MmH_RefPage(*pg); @@ -334,7 +338,7 @@ static void on_match(ext_inode** const inode, obos_status path_search(dev_desc* found, void* vn, const char* path, dev_desc parent) { - if (!found || !vn || !path) + if (!found || (!vn && parent == UINTPTR_MAX) || !path) return OBOS_STATUS_INVALID_ARGUMENT; uint32_t parent_ino = 0; @@ -410,7 +414,10 @@ obos_status path_search(dev_desc* found, void* vn, const char* path, dev_desc pa { get_next_tok(); if (tok == (path + path_len)) + { *found = get_desc(cache, ent->ino); + break; + } on_match(&inode, &pg, &buffer, @@ -418,10 +425,6 @@ obos_status path_search(dev_desc* found, void* vn, const char* path, dev_desc pa &offset, ent, cache); - if (!(*found)) - continue; - else - break; } } From 10a1ea46e828ed9414a028de4ae6a592b3bf651b Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Wed, 5 Nov 2025 10:45:17 -0500 Subject: [PATCH 02/96] vfs: Fix bugs with dirent lookups over different mount points --- src/oboskrnl/vfs/dirent.c | 22 +++++++++++++++++----- src/oboskrnl/vfs/mount.c | 3 +++ src/oboskrnl/vfs/mount.h | 1 + src/oboskrnl/vfs/pagecache.h | 2 ++ src/oboskrnl/vfs/pipe.c | 2 +- 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/oboskrnl/vfs/dirent.c b/src/oboskrnl/vfs/dirent.c index 4c110ce8..88fcfe7e 100644 --- a/src/oboskrnl/vfs/dirent.c +++ b/src/oboskrnl/vfs/dirent.c @@ -42,6 +42,7 @@ static vnode* create_vnode(mount* mountpoint, dev_desc desc, file_type* t) obos_status status = mountpoint->fs_driver->driver->header.ftable.vnode_search((void**)&vn, desc, mountpoint->fs_driver); if (obos_is_success(status)) { + OBOS_ENSURE(vn); vn->mount_point = mountpoint; if (t) { @@ -303,6 +304,7 @@ static dirent* lookup(const char* path, dirent* root_par, bool only_cache) if (!last) break; mountpoint = last->vnode->flags & VFLAGS_MOUNTPOINT ? last->vnode->un.mounted : last->vnode->mount_point; + fs_driver = mountpoint->fs_driver; currentPath = VfsH_DirentPath(last, mountpoint->root); currentPathLen = strlen(currentPath); if (currentPath[currentPathLen-1] != '/') @@ -312,6 +314,11 @@ static dirent* lookup(const char* path, dirent* root_par, bool only_cache) currentPath[++currentPathLen] = 0; } } + else + { + mountpoint = last->vnode->flags & VFLAGS_MOUNTPOINT ? last->vnode->un.mounted : last->vnode->mount_point; + fs_driver = mountpoint->fs_driver; + } tok += str_search(tok, '/'); size_t currentPathLen2 = strlen(tok)-1; @@ -512,7 +519,8 @@ static iterate_decision populate_cb(dev_desc desc, size_t blkSize, size_t blkCou child = child->d_next_child; } - mount* point = dent->vnode->mount_point ? dent->vnode->mount_point : dent->vnode->un.mounted; + + mount* point = Vfs_GetVnodeMount(dent->vnode); vnode* vn = create_vnode(point, desc, nullptr); dirent* new = Vfs_Calloc(1, sizeof(dirent)); OBOS_StringSetAllocator(&new->name, Vfs_Allocator); @@ -525,12 +533,16 @@ static iterate_decision populate_cb(dev_desc desc, size_t blkSize, size_t blkCou void Vfs_PopulateDirectory(dirent* dent) { - mount* point = dent->vnode->mount_point ? dent->vnode->mount_point : dent->vnode->un.mounted; - const driver_header* driver = &point->fs_driver->driver->header; + mount* point = Vfs_GetVnodeMount(dent->vnode); + driver_header* driver = Vfs_GetVnodeDriver(dent->vnode); if (dent->vnode->vtype != VNODE_TYPE_DIR) return; if (driver->ftable.list_dir) - OBOS_ENSURE(obos_is_success(driver->ftable.list_dir(dent->vnode->desc, point->device, populate_cb, dent))); + { + obos_status status = driver->ftable.list_dir(dent->vnode->flags & VFLAGS_MOUNTPOINT ? UINTPTR_MAX : dent->vnode->desc, point->device, populate_cb, dent); + if (obos_is_error(status)) + OBOS_Error("list_dir returned %d!\n", status); + } else OBOS_Error("driver->ftable.list_dir == nullptr!\n"); } @@ -785,5 +797,5 @@ mount* Vfs_GetVnodeMount(vnode* vn) return nullptr; if (vn->vtype == VNODE_TYPE_FIFO || vn->vtype == VNODE_TYPE_SOCK) return nullptr; - return vn->mount_point ? vn->mount_point : vn->un.mounted; + return vn->flags & VFLAGS_MOUNTPOINT ? vn->un.mounted : vn->mount_point; } diff --git a/src/oboskrnl/vfs/mount.c b/src/oboskrnl/vfs/mount.c index c269bc88..297b7634 100644 --- a/src/oboskrnl/vfs/mount.c +++ b/src/oboskrnl/vfs/mount.c @@ -183,6 +183,8 @@ obos_status Vfs_Mount(const char* at_, vnode* on, vdev* fs_driver, mount** pMoun at->vnode->un.mounted = mountpoint; // at->vnode->mount_point = mountpoint; at->vnode->flags |= VFLAGS_MOUNTPOINT; + mountpoint->old_root_desc = at->vnode->desc; + at->vnode->desc = UINTPTR_MAX; mountpoint->root = at; mountpoint->lock = MUTEX_INITIALIZE(); // uintptr_t udata[3] = { @@ -313,6 +315,7 @@ obos_status Vfs_Unmount(mount* what) Vfs_Root->vnode->mount_point = nullptr; Vfs_Root->vnode->un.mounted = nullptr; } + what->root->vnode->desc = what->old_root_desc; what->awaitingFree = true; if (!what->nWaiting) Vfs_Free(what); diff --git a/src/oboskrnl/vfs/mount.h b/src/oboskrnl/vfs/mount.h index 0c0bb862..5de4f51b 100644 --- a/src/oboskrnl/vfs/mount.h +++ b/src/oboskrnl/vfs/mount.h @@ -23,6 +23,7 @@ typedef struct mount LIST_NODE(mount_list, struct mount) node; mutex lock; dirent* root; + dev_desc old_root_desc; vdev* fs_driver; vnode* device; // the block device the filesystem is situated on. vnode* mounted_on; diff --git a/src/oboskrnl/vfs/pagecache.h b/src/oboskrnl/vfs/pagecache.h index a962f489..c842d741 100644 --- a/src/oboskrnl/vfs/pagecache.h +++ b/src/oboskrnl/vfs/pagecache.h @@ -31,6 +31,8 @@ static inline page* VfsH_PageCacheCreateEntry(vnode* vn, size_t offset) page* phys = MmH_PgAllocatePhysical(false, false); phys->backing_vn = vn; phys->file_offset = offset; + phys->file_offset -= (phys->file_offset % OBOS_PAGE_SIZE); + phys->end_offset = phys->file_offset + OBOS_PAGE_SIZE; RB_INSERT(pagecache_tree, &vn->cache, phys); driver_header* driver = Vfs_GetVnodeDriver(vn); if (!driver) return nullptr; diff --git a/src/oboskrnl/vfs/pipe.c b/src/oboskrnl/vfs/pipe.c index 34e27764..de6ded4e 100644 --- a/src/oboskrnl/vfs/pipe.c +++ b/src/oboskrnl/vfs/pipe.c @@ -148,7 +148,7 @@ static obos_status write_sync(dev_desc desc, const void* buf, size_t blkCount, s else { OBOS_Kill(Core_GetCurrentThread(), Core_GetCurrentThread(), SIGPIPE); - return OBOS_STATUS_SUCCESS; + return OBOS_STATUS_PIPE_CLOSED; } } From fc3927101290e15a19f89a43fe34293923464da9 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Wed, 5 Nov 2025 10:45:26 -0500 Subject: [PATCH 03/96] vfs: Fix TTY bug --- src/oboskrnl/vfs/tty.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/oboskrnl/vfs/tty.c b/src/oboskrnl/vfs/tty.c index b8c20cbb..b269ca0f 100644 --- a/src/oboskrnl/vfs/tty.c +++ b/src/oboskrnl/vfs/tty.c @@ -290,19 +290,19 @@ static obos_status tty_ioctl(dev_desc what, uint32_t request, void *argp) } case TTY_IOCTL_FLOW: switch (*(uint32_t*)argp) { - case TCION: + case TCOON: tty->paused = true; break; - case TCIOFF: + case TCOOFF: tty->paused = false; break; - case TCOOFF: + case TCIOFF: { char ch = tty->termios.iflag & IXON ? tty->termios.cc[VSTOP] : '\023' /* assume it is this */; tty->interface.write(tty, &ch, 1); break; } - case TCOON: + case TCION: { char ch = tty->termios.iflag & IXON ? tty->termios.cc[VSTART] : '\021' /* assume it is this */; tty->interface.write(tty, &ch, 1); @@ -641,7 +641,7 @@ static void poll_keyboard(struct screen_tty* data) while (1) { while (data->input_paused) - OBOSS_SpinlockHint(); + Core_Yield(); size_t nReady = 1; irp* req = VfsH_IRPAllocate(); req->vn = data->keyboard.vn; From 1d40319a91ccf61e1542020c0ac3f82da8866259 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 15 Nov 2025 17:09:41 -0500 Subject: [PATCH 04/96] ahci: Prefault pages before adding them to a PRDT --- src/drivers/generic/ahci/interface.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/drivers/generic/ahci/interface.c b/src/drivers/generic/ahci/interface.c index 08c6996c..cdd9513b 100644 --- a/src/drivers/generic/ahci/interface.c +++ b/src/drivers/generic/ahci/interface.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -85,8 +86,12 @@ static obos_status populate_physical_regions(uintptr_t base, size_t size, struct return OBOS_STATUS_INTERNAL_ERROR; page_info info = {}; MmS_QueryPageInfo(ctx->pt, addr, &info, nullptr); + if (!info.prot.present) + Mm_HandlePageFault(ctx, addr, (data->direction == COMMAND_DIRECTION_READ ? 0 : PF_EC_RW) | (ctx == &Mm_KernelContext ? 0 : PF_EC_UM)); page key = {.phys=info.phys}; page* pg = RB_FIND(phys_page_tree, &Mm_PhysicalPages, &key); + if (pg->cow_type != COW_DISABLED) + Mm_HandlePageFault(ctx, addr, PF_EC_PRESENT | (data->direction == COMMAND_DIRECTION_READ ? 0 : PF_EC_RW) | (ctx == &Mm_KernelContext ? 0 : PF_EC_UM)); MmH_RefPage(pg); if ((lastPhys + pgSize) != info.phys) { From 518d28f8d214df4cb9f0dd111de5646c70cd59e5 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 15 Nov 2025 17:09:56 -0500 Subject: [PATCH 05/96] mm: Change signature of Mm_VirtualMemoryLock --- src/oboskrnl/mm/alloc.h | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/oboskrnl/mm/alloc.h b/src/oboskrnl/mm/alloc.h index 521ac3ee..f305f429 100644 --- a/src/oboskrnl/mm/alloc.h +++ b/src/oboskrnl/mm/alloc.h @@ -90,21 +90,10 @@ OBOS_EXPORT obos_status Mm_VirtualMemoryProtect(context* ctx, void* base, size_t // NOTE: The returned address is not aligned down to the page size. OBOS_EXPORT void* Mm_MapViewOfUserMemory(context* const user_context, void* ubase, void* kbase, size_t nBytes, prot_flags protection, bool respectUserProtection, obos_status* status); -typedef enum unmap_behavior { - // Default behavior. - // Allow the pages to be unmapped from the address space, but do not unlock the backing memory. - UNMAP_FLAGS_ALLOW = 0, - // Defers the unmap until the pages are unlocked manually. - UNMAP_FLAGS_DEFER, - // Unlocks the pages on unmap, then unmaps them. - UNMAP_FLAGS_UNLOCK, -} unmap_behavior; - // Locks pages from base to base+sz in the working-set. // If space is not avaliable in the working-set, pages are removed until space can be satisified. // If the working-set's capacity is too small, then it can be inflated until the pages are unlocked. -// The unmap_ -OBOS_EXPORT obos_status Mm_VirtualMemoryLock(context* ctx, void* base, size_t sz, unmap_behavior unmap_action); +OBOS_EXPORT obos_status Mm_VirtualMemoryLock(context* ctx, void* base, size_t sz); // Unlocks pages from base to base+sz from the working-set. // If the pages caused the working-set capacity to be inflated, then it is deflated once again. OBOS_EXPORT obos_status Mm_VirtualMemoryUnlock(context* ctx, void* base, size_t sz); From 280d7d697ba0d193d6f9ef8766c3163412717b1a Mon Sep 17 00:00:00 2001 From: oberrow <72581470+oberrow@users.noreply.github.com> Date: Wed, 5 Nov 2025 10:47:38 -0500 Subject: [PATCH 06/96] docs: Update README --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index e7c12566..d92e49b5 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ # OBOS OBOS uses ***✨ state of the art technology ✨*** to do ***✨ almost nothing ✨*** ## Downloads -- ISO Downloads can currently be found at http://obos-dev.ddns.net/images/ -- An XBPS binary package repository exists at http://obos-dev.ddns.net/current for x86_64-obos **only**. +- The obos file server can be found at http://obos-dev.ddns.net/ ## Building ### Prerequisites - (For an x86-64 build) NASM From 766a855d7450301b9b5522843bb947a4e625e3fa Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Thu, 6 Nov 2025 18:29:10 -0500 Subject: [PATCH 07/96] misc: Update uACPI --- dependencies/uacpi.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/uacpi.cmake b/dependencies/uacpi.cmake index 7a026d32..88627c79 100644 --- a/dependencies/uacpi.cmake +++ b/dependencies/uacpi.cmake @@ -9,7 +9,7 @@ if (OBOS_REFRESH_DEPENDENCIES) # In honor of the old uACPI link #GIT_REPOSITORY https://github.com/UltraOS/uACPI.git GIT_REPOSITORY https://github.com/uACPI/uACPI.git - GIT_TAG 3.0.0 + GIT_TAG 3.2.0 SOURCE_DIR ${CMAKE_SOURCE_DIR}/dependencies/uACPI ) FetchContent_MakeAvailable(uACPI) From b0e58dc37c60bbfd8fa737ea1948c9dbdb193f72 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sun, 9 Nov 2025 13:36:49 -0500 Subject: [PATCH 08/96] sys: Add Sys_ThreadGetStack --- src/oboskrnl/arch/m68k/syscall.c | 1 + src/oboskrnl/arch/x86_64/syscall.c | 1 + src/oboskrnl/syscall.c | 34 ++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/src/oboskrnl/arch/m68k/syscall.c b/src/oboskrnl/arch/m68k/syscall.c index 4ce9df1c..0f04dc88 100644 --- a/src/oboskrnl/arch/m68k/syscall.c +++ b/src/oboskrnl/arch/m68k/syscall.c @@ -160,6 +160,7 @@ const char *syscall_to_string[] = { "Sys_UMask", "Sys_RenameAt", "Sys_UTimeNSAt", + "Sys_ThreadGetStack", }; const char* status_to_string[] = { diff --git a/src/oboskrnl/arch/x86_64/syscall.c b/src/oboskrnl/arch/x86_64/syscall.c index b4bc586d..58f16c48 100644 --- a/src/oboskrnl/arch/x86_64/syscall.c +++ b/src/oboskrnl/arch/x86_64/syscall.c @@ -245,6 +245,7 @@ const char* syscall_to_string[] = { "Sys_UMask", "Sys_RenameAt", "Sys_UTimeNSAt", + "Sys_ThreadGetStack", }; const char* status_to_string[] = { diff --git a/src/oboskrnl/syscall.c b/src/oboskrnl/syscall.c index 98eed26a..09012e18 100644 --- a/src/oboskrnl/syscall.c +++ b/src/oboskrnl/syscall.c @@ -285,6 +285,39 @@ obos_status Sys_IsATTY(handle desc) return OBOS_STATUS_SUCCESS; } +obos_status Sys_ThreadGetStack(handle thr, void** stack_base, size_t *stack_size) +{ + thread* thread = HANDLE_TYPE(thr) == HANDLE_TYPE_CURRENT ? Core_GetCurrentThread() : nullptr; + if (!thread) + { + obos_status status = OBOS_STATUS_SUCCESS; + handle_desc* hnd = OBOS_HandleLookup(OBOS_CurrentHandleTable(), thr, HANDLE_TYPE_THREAD, false, &status); + if (obos_is_error(status)) + { + OBOS_UnlockHandleTable(OBOS_CurrentHandleTable()); + return status; + } + OBOS_UnlockHandleTable(OBOS_CurrentHandleTable()); + thread = hnd->un.thread; + } + + if (!stack_base && !stack_size) + return OBOS_STATUS_SUCCESS; + + void* res_base = nullptr; + size_t res_size = 0; + + res_base = CoreS_GetThreadStack(&thread->context); + res_size = CoreS_GetThreadStackSize(&thread->context); + + if (stack_base) + memcpy_k_to_usr(stack_base, &res_base, sizeof(*stack_base)); + if (stack_base) + memcpy_k_to_usr(stack_base, &res_size, sizeof(*stack_size)); + + return OBOS_STATUS_SUCCESS; +} + uintptr_t OBOS_SyscallTable[SYSCALL_END-SYSCALL_BEGIN] = { (uintptr_t)Core_ExitCurrentThread, (uintptr_t)Core_Yield, @@ -422,6 +455,7 @@ uintptr_t OBOS_SyscallTable[SYSCALL_END-SYSCALL_BEGIN] = { (uintptr_t)Sys_UMask, (uintptr_t)Sys_RenameAt, (uintptr_t)Sys_UTimeNSAt, + (uintptr_t)Sys_ThreadGetStack, }; // Arch syscall table is defined per-arch From c91ae684673e9cd3af9c1e1edde1b1ac89c7076f Mon Sep 17 00:00:00 2001 From: oberrow <72581470+oberrow@users.noreply.github.com> Date: Fri, 14 Nov 2025 12:26:45 -0500 Subject: [PATCH 09/96] misc: Remove unnecessary text from README --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index d92e49b5..0a6c9d60 100644 --- a/README.md +++ b/README.md @@ -62,9 +62,6 @@ call launch_qemu.bat - x86_64-obos: Working, not all ported programs work - m68k-obos: Userspace is unstable, but the port works otherwise - For information on ported programs, go to the obos-pkgs repository -## Credits -- My friend [@LemurLord16](https://github.com/LemurLord16) (@sigsbeedrive on discord) for listening to me yap about new features. -- My cousin Ali because why not. ## License Notice Most code in this repository is licensed under the MIT license.
Any code from other projects that require a license notice will be put below. From d142976c3df8b38ef0e22e00b249b0bd3282be1a Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Fri, 21 Nov 2025 20:15:33 -0500 Subject: [PATCH 10/96] net/tcp: Fix bug --- src/oboskrnl/net/tcp.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/oboskrnl/net/tcp.c b/src/oboskrnl/net/tcp.c index da53f5ac..118c54c6 100644 --- a/src/oboskrnl/net/tcp.c +++ b/src/oboskrnl/net/tcp.c @@ -744,20 +744,20 @@ void Net_TCPPushReceivedData(tcp_connection* con, const void* buffer, size_t sz, return; } -static const char* state_strs[] = { - "INVALID", - "LISTEN", - "SYN_SENT", - "SYN_RECEIVED", - "ESTABLISHED", - "FIN_WAIT1", - "FIN_WAIT2", - "CLOSE_WAIT", - "CLOSING", - "LAST_ACK", - "TIME_WAIT", - "CLOSED", -}; +// static const char* state_strs[] = { +// "INVALID", +// "LISTEN", +// "SYN_SENT", +// "SYN_RECEIVED", +// "ESTABLISHED", +// "FIN_WAIT1", +// "FIN_WAIT2", +// "CLOSE_WAIT", +// "CLOSING", +// "LAST_ACK", +// "TIME_WAIT", +// "CLOSED", +// }; void Net_TCPChangeConnectionState(tcp_connection* con, int state) { @@ -1502,7 +1502,7 @@ static void irp_on_event_set(irp* req) if (req->dryOp) return; - if (req->socket_flags) + // if (req->socket_flags) // OBOS_Debug("TCP: Recv got 0x%p for flags\n", req->socket_flags); Core_MutexAcquire(&s->connection->recv_buffer.lock); From 28e54a4e19c7dcecb5c42280b6215744a51a8f70 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Fri, 21 Nov 2025 20:17:56 -0500 Subject: [PATCH 11/96] core: Fix compiler error with -Werror in release mode --- src/oboskrnl/locks/wait.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oboskrnl/locks/wait.c b/src/oboskrnl/locks/wait.c index bc725a1a..4644874b 100644 --- a/src/oboskrnl/locks/wait.c +++ b/src/oboskrnl/locks/wait.c @@ -24,7 +24,7 @@ #if OBOS_DEBUG # define assert_initialized() OBOS_ASSERT(obj->initialized == true) #else -# define assert_initialized() (true) +# define assert_initialized() (void)(true) #endif obos_status Core_WaitOnObject(struct waitable_header* obj) From e23b631198057e04f87ee6595ed6085e6aa08e79 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Fri, 21 Nov 2025 20:45:34 -0500 Subject: [PATCH 12/96] e1000: Fix bugs --- src/drivers/generic/freebsd-e1000/io.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/drivers/generic/freebsd-e1000/io.c b/src/drivers/generic/freebsd-e1000/io.c index feaba376..6b638990 100644 --- a/src/drivers/generic/freebsd-e1000/io.c +++ b/src/drivers/generic/freebsd-e1000/io.c @@ -300,7 +300,7 @@ void e1000_tx_reap(e1000_device* dev); event* e1000_tx_packet(e1000_device* dev, const void* buffer, size_t size, bool dry) { e1000_tx_reap(dev); - struct e1000_tx_desc* desc = &((struct e1000_tx_desc*)MmS_MapVirtFromPhys(dev->tx_ring))[dev->tx_index % TX_QUEUE_SIZE]; + volatile struct e1000_tx_desc* desc = &((volatile struct e1000_tx_desc*)MmS_MapVirtFromPhys(dev->tx_ring))[dev->tx_index % TX_QUEUE_SIZE]; if (dry) return nullptr; irql oldIrql = Core_RaiseIrql(IRQL_E1000); @@ -373,7 +373,7 @@ static void tx_event_set_dpc(dpc* d, void* udata) } void e1000_tx_reap(e1000_device* dev) { - struct e1000_tx_desc* desc = &((struct e1000_tx_desc*)MmS_MapVirtFromPhys(dev->tx_ring))[0]; + volatile struct e1000_tx_desc* desc = &((struct e1000_tx_desc*)MmS_MapVirtFromPhys(dev->tx_ring))[0]; size_t i = dev->tx_index; for (; ; ) { @@ -381,7 +381,8 @@ void e1000_tx_reap(e1000_device* dev) break; desc[i].upper.fields.status = 0; desc[i].lower.data = 0; - desc[i].buffer_addr = 0; + desc[i].buffer_addr = 0; + i++; } dev->tx_index = i; } From dc231ee4bc63e88abbb223e32234edcbc353f754 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Fri, 21 Nov 2025 21:08:49 -0500 Subject: [PATCH 13/96] sys: Fix bug with Sys_ProcessStart --- src/oboskrnl/scheduler/sched_sys.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/oboskrnl/scheduler/sched_sys.c b/src/oboskrnl/scheduler/sched_sys.c index cdcd7053..8c56f1a2 100644 --- a/src/oboskrnl/scheduler/sched_sys.c +++ b/src/oboskrnl/scheduler/sched_sys.c @@ -472,6 +472,7 @@ handle Sys_ProcessStart(handle mainThread, handle vmmContext, bool is_fork) OBOS_LockHandleTable(OBOS_CurrentHandleTable()); handle_desc* desc = nullptr; + new->refcount++; handle hnd = OBOS_HandleAllocate(OBOS_CurrentHandleTable(), HANDLE_TYPE_PROCESS, &desc); desc->un.process = new; OBOS_UnlockHandleTable(OBOS_CurrentHandleTable()); From b6f94f943531f5d225ef178b762693731e8e3b39 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Fri, 21 Nov 2025 21:09:18 -0500 Subject: [PATCH 14/96] core: Count processes in a PGRP as a reference --- src/oboskrnl/scheduler/process.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/oboskrnl/scheduler/process.c b/src/oboskrnl/scheduler/process.c index 1601acef..89ddf881 100644 --- a/src/oboskrnl/scheduler/process.c +++ b/src/oboskrnl/scheduler/process.c @@ -324,6 +324,7 @@ void Core_ExitProcessGroup() Core_MutexRelease(&Core_ProcessGroupTreeLock); } Core_MutexRelease(&pgrp->lock); + proc->refcount--; } obos_status Core_SetProcessGroup(process* proc, uint32_t pgid) @@ -363,6 +364,7 @@ obos_status Core_SetProcessGroup(process* proc, uint32_t pgid) Core_MutexAcquire(&pgrp->lock); LIST_APPEND(process_list, &pgrp->processes, proc); + proc->refcount++; proc->pgrp = pgrp; Core_MutexRelease(&pgrp->lock); From 16efa041652843f2787eb86f22e1b950542878e8 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Fri, 21 Nov 2025 21:09:48 -0500 Subject: [PATCH 15/96] x86_64: Fix a bug with the syscall trap handler --- src/oboskrnl/arch/x86_64/syscall.asm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/oboskrnl/arch/x86_64/syscall.asm b/src/oboskrnl/arch/x86_64/syscall.asm index d125c255..6b1e0e8a 100644 --- a/src/oboskrnl/arch/x86_64/syscall.asm +++ b/src/oboskrnl/arch/x86_64/syscall.asm @@ -119,6 +119,7 @@ Arch_SyscallTrapHandler: pop rcx mov cr3, r9 + cli mov rsp, r10 swapgs o64 sysret From 51d50cae9fd7884346f3e99ea8c93257274de7aa Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 22 Nov 2025 15:11:25 -0500 Subject: [PATCH 16/96] boot: Allow use of either Hyper or Limine to boot the kernel --- .gitignore | 4 +- CMakeLists.txt | 12 ++ config/limine.conf | 18 ++ dependencies/limine.cmake | 24 +++ scripts/launch_qemu.tcg.sh | 27 +++ src/isogen/isogen.cmake | 47 +++-- src/oboskrnl/arch/x86_64/boot_info.h | 20 ++- src/oboskrnl/arch/x86_64/entry.asm | 2 + src/oboskrnl/arch/x86_64/entry.c | 256 ++++++++++++++++++++------- src/oboskrnl/arch/x86_64/ioapic.c | 2 +- src/oboskrnl/arch/x86_64/map.c | 12 ++ src/oboskrnl/arch/x86_64/pmm.c | 27 +++ src/oboskrnl/arch/x86_64/pmm.h | 16 ++ src/oboskrnl/arch/x86_64/smp.c | 2 +- src/oboskrnl/arch/x86_64/timer.c | 2 +- src/oboskrnl/arch/x86_64/wake.c | 24 ++- src/uACPI/kernel_api.c | 2 +- 17 files changed, 412 insertions(+), 85 deletions(-) create mode 100644 config/limine.conf create mode 100644 dependencies/limine.cmake create mode 100755 scripts/launch_qemu.tcg.sh diff --git a/.gitignore b/.gitignore index 02e2a916..b4dcf36d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,9 +8,9 @@ /dependencies/uACPI /dependencies/uHDA /dependencies/flanterm/ -/dependencies/freebsd-e1000/ -/dependencies/include/ /dependencies/freebsd-e1000 +/dependencies/limine +/dependencies/include/ /dependencies/needs_download.cmake /qemu_log.txt /tar diff --git a/CMakeLists.txt b/CMakeLists.txt index a52ad865..f174ea18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ option (OBOS_LAZY_IRQL "Enables lazy IRQL. Recommended if the main target of the option (OBOS_USE_OBOS_GCC "Uses arch-obos-gcc instead of obos-elf-gcc. Ignored if OBOS_USE_CLANG is true.") option (OBOS_COMPILE_USER_UTILS "Compiles user examples" ${OBOS_USE_OBOS_GCC}) option (OBOS_ONLY_COMPILE_USER_UTILS "Only compile user utilities" OFF) +option (OBOS_USE_LIMINE "Use Limine instead of Hyper on supported architectures" OFF) option (OBOS_ENABLE_UHDA "Whether to include uHDA" ON) set (OBOS_LAZY_IRQL OFF) @@ -87,6 +88,10 @@ if (OBOS_REFRESH_DEPENDENCIES) message("Fetching Hyper.") include("dependencies/hyper.cmake") endif() + if (OBOS_USE_LIMINE) + message("Fetching Limine.") + include("dependencies/limine.cmake") + endif() message("Fetching uACPI.") include ("dependencies/uacpi.cmake") message("Fetching flanterm.") @@ -129,7 +134,14 @@ if (OBOS_LAZY_IRQL) else() set (OBOS_LAZY_IRQL "0") endif() + add_compile_definitions(OBOS_LAZY_IRQL=${OBOS_LAZY_IRQL}) +if (OBOS_USE_LIMINE) + set (OBOS_USE_LIMINE "1") +else() + set (OBOS_USE_LIMINE "0") +endif() +add_compile_definitions(OBOS_USE_LIMINE=${OBOS_USE_LIMINE}) if (OBOS_ENABLE_LOCK_PROFILING) set (OBOS_ENABLE_LOCK_PROFILING "1") diff --git a/config/limine.conf b/config/limine.conf new file mode 100644 index 00000000..c13ffcc3 --- /dev/null +++ b/config/limine.conf @@ -0,0 +1,18 @@ +# Timeout in seconds that Limine will use before automatically booting. +timeout: 5 + +# The entry name that will be displayed in the boot menu. +/OBOS + # We use the Limine boot protocol. + protocol: limine + comment: OBOS + + paging_mode: 4level + module_path: boot():/obos/initrd.tar + module_string: initrd + module_path: boot():/obos/initrd + module_string: initrd_driver + module_path: boot():/obos/flanterm_buff + module_string: FLANTERM_BUFF + path: boot():/obos/oboskrnl + cmdline: initrd-module=initrd initrd-driver-module=initrd_driver root-fs-partid initrd load-modules=/libps2,/extfs initial-swap-size=67108864 log-level=1 init-args /usr/bin/bash --login diff --git a/dependencies/limine.cmake b/dependencies/limine.cmake new file mode 100644 index 00000000..8d18c968 --- /dev/null +++ b/dependencies/limine.cmake @@ -0,0 +1,24 @@ +# dependencies/limine.cmake + +# Copyright (c) 2025 Omar Berrow + +include(FetchContent) + +FetchContent_Declare(Limine + GIT_REPOSITORY https://github.com/limine-bootloader/limine.git + GIT_TAG v10.3.0-binary + SOURCE_DIR ${CMAKE_SOURCE_DIR}/dependencies/limine +) +FetchContent_MakeAvailable(Limine) +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") +execute_process( + COMMAND "make" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/dependencies/limine + ) + set (limine_exe ${CMAKE_SOURCE_DIR}/dependencies/limine/limine CACHE INTERNAL "x") +# elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows" OR CMAKE_HOST_SYSTEM_NAME STREQUAL "MSYS") +# set (limine_exe ${CMAKE_SOURCE_DIR}/dependencies/limine/limine.exe CACHE INTERNAL "x") +else() + message(FATAL_ERROR "You must be on to compile OBOS with Limine.") +endif() +file (COPY_FILE "${CMAKE_SOURCE_DIR}/dependencies/limine/limine.h" "${CMAKE_SOURCE_DIR}/dependencies/include/limine.h") \ No newline at end of file diff --git a/scripts/launch_qemu.tcg.sh b/scripts/launch_qemu.tcg.sh new file mode 100755 index 00000000..f91864ac --- /dev/null +++ b/scripts/launch_qemu.tcg.sh @@ -0,0 +1,27 @@ +cd ../ + +rm qemu_log.txt + +echo $@ +qemu-system-x86_64 \ +-drive format=raw,file=out/obos.iso,media=disk,index=0 \ +-m 2G \ +-gdb tcp:0.0.0.0:1234 -S \ +-M q35 \ +-cpu Haswell \ +-accel tcg \ +-debugcon file:/dev/stdout \ +-monitor stdio \ +-serial tcp:0.0.0.0:1534,server,nowait \ +-smp cores=1,threads=1,sockets=1 \ +-d int \ +-D qemu_log.txt "$@" + +# -nographic +# -enable-kvm \ +# -M smm=off \ +# -no-reboot +# -enable-kvm \ +# -no-shutdown + +cd scripts diff --git a/src/isogen/isogen.cmake b/src/isogen/isogen.cmake index da04ffbe..85027121 100644 --- a/src/isogen/isogen.cmake +++ b/src/isogen/isogen.cmake @@ -14,9 +14,6 @@ endif() if (NOT EXISTS ${ISODIR}/obos) file (MAKE_DIRECTORY ${ISODIR}/obos) endif() -if (NOT EXISTS ${CMAKE_SOURCE_DIR}/config/hyper.cfg) - message(FATAL_ERROR "No hyper configuration file detected!") -endif() if (CMAKE_HOST_WIN32) set(SUPPRESS_OUTPUT > NUL 2>&1) @@ -24,24 +21,48 @@ elseif(CMAKE_HOST_LINUX) set(SUPPRESS_OUTPUT > /dev/null 2>&1) endif() +if (OBOS_USE_LIMINE) + set (LIMINE_ENABLED "true") + set (LIMINE_NOT_ENABLED "false") + set(BIOS_INSTALL ${limine_exe} bios-install ${OUTPUT_DIR}/obos.iso ${SUPPRESS_OUTPUT}) + set(BIOS_PRE_XORRISO fallocate -l16M ${ISODIR}/obos/flanterm_buff && cmake -E make_directory ${ISODIR}/limine/ && cmake -E copy ${CMAKE_SOURCE_DIR}/dependencies/limine/limine-bios.sys ${ISODIR}/limine/) + set(BTLDR_CONF "limine.conf") + set(xorriso_bios_cd_path "dependencies/limine/limine-bios-cd.bin") + set(xorriso_uefi_cd_path "dependencies/limine/limine-uefi-cd.bin") + set(xorriso_uefi_cd_name "limine-uefi-cd.bin") + set(xorriso_bios_cd_name "limine-bios-cd.bin") +else() + set(BIOS_INSTALL ${hyper_install} ${OUTPUT_DIR}/obos.iso ${SUPPRESS_OUTPUT}) + set(BIOS_PRE_XORRISO true) + set(BTLDR_CONF "hyper.cfg") + set(xorriso_bios_cd_path "dependencies/hyper/hyper_iso_boot") + set(xorriso_uefi_cd_path "config/hyper_uefi_boot.bin") + set(xorriso_uefi_cd_name "hyper_uefi_boot.bin") + set(xorriso_bios_cd_name "hyper_iso_boot") +endif() + +if (NOT EXISTS ${CMAKE_SOURCE_DIR}/config/${BTLDR_CONF}) + message(FATAL_ERROR "No bootloader configuration file detected!") +endif() + add_custom_command(OUTPUT ${OUTPUT_DIR}/obos.iso COMMAND ${OBJCOPY} -g ${OUTPUT_DIR}/oboskrnl ${ISODIR}/obos/oboskrnl ${SUPPRESS_OUTPUT} - COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/config/hyper.cfg ${ISODIR}/ ${SUPPRESS_OUTPUT} - COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/dependencies/hyper/hyper_iso_boot ${ISODIR} ${SUPPRESS_OUTPUT} - COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/config/hyper_uefi_boot.bin ${ISODIR} ${SUPPRESS_OUTPUT} + COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/config/${BTLDR_CONF} ${ISODIR}/ ${SUPPRESS_OUTPUT} + COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/${xorriso_bios_cd_path} ${ISODIR} ${SUPPRESS_OUTPUT} + COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/${xorriso_uefi_cd_path} ${ISODIR} ${SUPPRESS_OUTPUT} COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/out/initrd ${ISODIR}/obos ${SUPPRESS_OUTPUT} COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/config/initrd.tar ${ISODIR}/obos ${SUPPRESS_OUTPUT} - COMMAND xorriso -as mkisofs -b hyper_iso_boot -no-emul-boot -boot-load-size 4 -boot-info-table --efi-boot hyper_uefi_boot.bin -efi-boot-part --efi-boot-image --protective-msdos-label out/isodir -o ${OUTPUT_DIR}/obos.iso ${SUPPRESS_OUTPUT} - COMMAND chmod +x ${hyper_install} - COMMAND ${hyper_install} ${OUTPUT_DIR}/obos.iso ${SUPPRESS_OUTPUT} - BYPRODUCTS ${ISODIR}/hyper.cfg - ${ISODIR}/hyper_iso_boot - ${ISODIR}/hyper_uefi_boot.bin + COMMAND ${BIOS_PRE_XORRISO} + COMMAND xorriso -as mkisofs -b ${xorriso_bios_cd_name} -no-emul-boot -boot-load-size 4 -boot-info-table --efi-boot ${xorriso_uefi_cd_name} -efi-boot-part --efi-boot-image --protective-msdos-label out/isodir -o ${OUTPUT_DIR}/obos.iso ${SUPPRESS_OUTPUT} + COMMAND ${BIOS_INSTALL} + BYPRODUCTS ${ISODIR}/${BTLDR_CONF} + ${ISODIR}/${xorriso_bios_cd_name} + ${ISODIR}/${xorriso_uefi_cd_name} ${ISODIR}/obos/oboskrnl ${ISODIR}/obos/initrd ${ISODIR}/obos/initrd.tar WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - DEPENDS ${CMAKE_SOURCE_DIR}/config/initrd.tar ${CMAKE_SOURCE_DIR}/config/hyper.cfg oboskrnl initrd + DEPENDS ${CMAKE_SOURCE_DIR}/config/initrd.tar ${CMAKE_SOURCE_DIR}/config/${BTLDR_CONF} oboskrnl initrd ) add_custom_target (isogen ALL DEPENDS oboskrnl initrd ${OUTPUT_DIR}/obos.iso diff --git a/src/oboskrnl/arch/x86_64/boot_info.h b/src/oboskrnl/arch/x86_64/boot_info.h index 4bc49dcd..5aa7aa6e 100644 --- a/src/oboskrnl/arch/x86_64/boot_info.h +++ b/src/oboskrnl/arch/x86_64/boot_info.h @@ -6,6 +6,8 @@ #pragma once +#if !OBOS_USE_LIMINE + #include extern volatile struct ultra_memory_map_attribute* Arch_MemoryMap; @@ -14,4 +16,20 @@ extern volatile struct ultra_kernel_info_attribute* Arch_KernelInfo; extern volatile struct ultra_module_info_attribute* Arch_KernelBinary; extern volatile struct ultra_module_info_attribute* Arch_InitialSwapBuffer; extern volatile struct ultra_framebuffer* Arch_Framebuffer; -extern volatile struct ultra_boot_context* Arch_BootContext; \ No newline at end of file +extern volatile struct ultra_boot_context* Arch_BootContext; +#else + +#include +#include + +extern volatile struct limine_framebuffer_request Arch_LimineFBRequest; +extern volatile struct limine_memmap_request Arch_LimineMemmapRequest; +extern volatile struct limine_module_request Arch_LimineModuleRequest; +extern volatile struct limine_hhdm_request Arch_LimineHHDMRequest; +extern volatile struct limine_executable_file_request Arch_LimineKernelInfoRequest; +extern volatile struct limine_executable_address_request Arch_LimineKernelAddressRequest; +extern volatile struct limine_executable_cmdline_request Arch_LimineKernelCmdlineRequest; +extern volatile struct ultra_framebuffer* Arch_Framebuffer; // Artificially created +extern struct limine_file* Arch_KernelBinary; +#endif +extern uintptr_t Arch_RSDPBase; \ No newline at end of file diff --git a/src/oboskrnl/arch/x86_64/entry.asm b/src/oboskrnl/arch/x86_64/entry.asm index 18a50d06..79176293 100644 --- a/src/oboskrnl/arch/x86_64/entry.asm +++ b/src/oboskrnl/arch/x86_64/entry.asm @@ -14,10 +14,12 @@ extern Arch_disablePIC extern Arch_KernelEntry global Arch_KernelEntryBootstrap:function hidden Arch_KernelEntryBootstrap: +%if !OBOS_USE_LIMINE cmp rsi, 0x554c5442 je .ok ; should triple fault on failure xor rax,rax jmp rax ; All hope is lost. +%endif .ok: push rdi push rsi diff --git a/src/oboskrnl/arch/x86_64/entry.c b/src/oboskrnl/arch/x86_64/entry.c index d5d7b948..0d484088 100644 --- a/src/oboskrnl/arch/x86_64/entry.c +++ b/src/oboskrnl/arch/x86_64/entry.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #define FLANTERM_IN_FLANTERM @@ -47,12 +49,14 @@ #include #include -#include "gdbstub/connection.h" -#include "gdbstub/gdb_udp_backend.h" -#include "gdbstub/debug.h" - #include +#include + +#if OBOS_USE_LIMINE +# include +#endif + extern void Arch_InitBootGDT(); static char thr_stack[0x4000]; @@ -168,15 +172,16 @@ static void init_flanterm_backend() OBOS_AddLogSource(&backend); } -static struct ultra_module_info_attribute* Arch_FlantermBumpAllocator; +static struct { + uintptr_t address; + uintptr_t size; +} Arch_FlantermBumpAllocator = {}; static void *flanterm_malloc(size_t sz) { - if (!Arch_FlantermBumpAllocator) - return nullptr; static size_t bump_off = 0; - if ((bump_off + sz) > Arch_FlantermBumpAllocator->size) + if ((bump_off + sz) > Arch_FlantermBumpAllocator.size) return nullptr; - void* ret = (void*)(Arch_FlantermBumpAllocator->address + bump_off); + void* ret = (void*)(Arch_FlantermBumpAllocator.address + bump_off); bump_off += sz; return ret; } @@ -186,7 +191,51 @@ static void flanterm_free(void* blk, size_t sz) return; } +#if OBOS_USE_LIMINE +volatile struct limine_framebuffer_request Arch_LimineFBRequest = { + .id = LIMINE_FRAMEBUFFER_REQUEST_ID, + .revision = 1, +}; +volatile struct limine_memmap_request Arch_LimineMemmapRequest = { + .id = LIMINE_MEMMAP_REQUEST_ID, + .revision = 0, +}; +volatile struct limine_module_request Arch_LimineModuleRequest = { + .id = LIMINE_MODULE_REQUEST_ID, + .revision = 1, +}; +volatile struct limine_hhdm_request Arch_LimineHHDMRequest = { + .id = LIMINE_HHDM_REQUEST_ID, + .revision = 0, +}; +volatile struct limine_executable_file_request Arch_LimineKernelInfoRequest = { + .id = LIMINE_EXECUTABLE_FILE_REQUEST_ID, + .revision = 0, +}; +volatile struct limine_executable_address_request Arch_LimineKernelAddressRequest = { + .id = LIMINE_EXECUTABLE_ADDRESS_REQUEST_ID, + .revision = 0, +}; +volatile struct limine_executable_cmdline_request Arch_LimineKernelCmdlineRequest = { + .id = LIMINE_EXECUTABLE_CMDLINE_REQUEST_ID, + .revision = 0, +}; +volatile struct limine_rsdp_request Arch_LimineRSDPRequest = { + .id = LIMINE_RSDP_REQUEST_ID, + .revision = 0, +}; +volatile struct ultra_framebuffer limine_fb0 = {}; +volatile struct ultra_framebuffer* Arch_Framebuffer = &limine_fb0; +struct limine_file* Arch_KernelBinary = nullptr; +#endif + +uintptr_t Arch_RSDPBase = 0; + +#if !OBOS_USE_LIMINE OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry(struct ultra_boot_context* bcontext) +#else +OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry() +#endif { bsp_cpu.id = 0; bsp_cpu.isBSP = true; @@ -200,18 +249,6 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry wrmsr(0xC0000101, (uintptr_t)&Core_CpuInfo[0]); - ParseBootContext(bcontext); - Arch_BootContext = bcontext; - OBOS_ParseCMDLine(); - asm("sti"); - - uint64_t log_level = OBOS_GetOPTD_Ex("log-level", LOG_LEVEL_LOG); - if (log_level > 4) - log_level = LOG_LEVEL_DEBUG; - OBOS_SetLogLevel(log_level); - extern uint64_t Arch_KernelCR3; - Arch_KernelCR3 = getCR3(); - #if !OBOS_ENABLE_PROFILING { uint32_t ecx = 0; @@ -225,30 +262,62 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry } #endif +#if !OBOS_USE_LIMINE + ParseBootContext(bcontext); + Arch_BootContext = bcontext; +#else + OBOS_KernelCmdLine = Arch_LimineKernelCmdlineRequest.response->cmdline; + Arch_KernelBinary = Arch_LimineKernelInfoRequest.response->executable_file; + Arch_RSDPBase = Arch_UnmapFromHHDM(Arch_LimineRSDPRequest.response->address); +#endif + + struct boot_module flanterm_buff = {}; + OBOSS_GetModule(&flanterm_buff, "FLANTERM_BUFF"); + if (!flanterm_buff.address) + OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "Could not find FLANTERM_BUFF kernel module\n"); + Arch_FlantermBumpAllocator.address = (uintptr_t)flanterm_buff.address; + Arch_FlantermBumpAllocator.size = flanterm_buff.size; + + OBOS_ParseCMDLine(); + asm("sti"); + + uint64_t log_level = OBOS_GetOPTD_Ex("log-level", LOG_LEVEL_LOG); + if (log_level > 4) + log_level = LOG_LEVEL_DEBUG; + OBOS_SetLogLevel(log_level); + extern uint64_t Arch_KernelCR3; + Arch_KernelCR3 = getCR3(); + #if 0 init_serial_log_backend(); #endif + static uint32_t ansi_colors[8] = { + __builtin_bswap32(0x000000) >> 8, + __builtin_bswap32(0xbb0000) >> 8, + __builtin_bswap32(0x00bb00) >> 8, + __builtin_bswap32(0xbbbb00) >> 8, + __builtin_bswap32(0x0000bb) >> 8, + __builtin_bswap32(0xbb00bb) >> 8, + __builtin_bswap32(0x00bbbb) >> 8, + __builtin_bswap32(0xbbbbbb) >> 8, + }; + static uint32_t ansi_bright_colors[8] = { + __builtin_bswap32(0x555555) >> 8, + __builtin_bswap32(0xff5555) >> 8, + __builtin_bswap32(0x55ff55) >> 8, + __builtin_bswap32(0xffff55) >> 8, + __builtin_bswap32(0x5555aa) >> 8, + __builtin_bswap32(0xff55ff) >> 8, + __builtin_bswap32(0x55ffff) >> 8, + __builtin_bswap32(0xffffff) >> 8, + + }; +#if !OBOS_USE_LIMINE if (!Arch_Framebuffer) OBOS_Warning("No framebuffer passed by the bootloader. All kernel logs will be on port 0xE9.\n"); else { - // OBOS_TextRendererState.fg_color = 0xffffffff; - // OBOS_TextRendererState.fb.base = Arch_MapToHHDM(Arch_Framebuffer->physical_address); - // OBOS_TextRendererState.fb.bpp = Arch_Framebuffer->bpp; - // OBOS_TextRendererState.fb.format = Arch_Framebuffer->format; - // OBOS_TextRendererState.fb.height = Arch_Framebuffer->height; - // OBOS_TextRendererState.fb.width = Arch_Framebuffer->width; - // OBOS_TextRendererState.fb.pitch = Arch_Framebuffer->pitch; - // for (size_t y = 0; y < Arch_Framebuffer->height; y++) - // for (size_t x = 0; x < Arch_Framebuffer->width; x++) - // OBOS_PlotPixel(OBOS_TEXT_BACKGROUND, &((uint8_t*)OBOS_TextRendererState.fb.base)[y*Arch_Framebuffer->pitch+x*Arch_Framebuffer->bpp/8], OBOS_TextRendererState.fb.format); - // OBOS_TextRendererState.column = 0; - // OBOS_TextRendererState.row = 0; - // OBOS_TextRendererState.font = font_bin; - // OBOS_AddLogSource(&OBOS_ConsoleOutputCallback); - // if (Arch_Framebuffer->format == ULTRA_FB_FORMAT_INVALID) - // return; uint8_t red_mask_size = 8, red_mask_shift = 0; uint8_t green_mask_size = 8, green_mask_shift = 0; uint8_t blue_mask_size = 8, blue_mask_shift = 0; @@ -276,29 +345,7 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry blue_mask_shift = 16; bg = bg >> 8; break; - } - static uint32_t ansi_colors[8] = { - __builtin_bswap32(0x000000) >> 8, - __builtin_bswap32(0xbb0000) >> 8, - __builtin_bswap32(0x00bb00) >> 8, - __builtin_bswap32(0xbbbb00) >> 8, - __builtin_bswap32(0x0000bb) >> 8, - __builtin_bswap32(0xbb00bb) >> 8, - __builtin_bswap32(0x00bbbb) >> 8, - __builtin_bswap32(0xbbbbbb) >> 8, - }; - static uint32_t ansi_bright_colors[8] = { - __builtin_bswap32(0x555555) >> 8, - __builtin_bswap32(0xff5555) >> 8, - __builtin_bswap32(0x55ff55) >> 8, - __builtin_bswap32(0xffff55) >> 8, - __builtin_bswap32(0x5555aa) >> 8, - __builtin_bswap32(0xff55ff) >> 8, - __builtin_bswap32(0x55ffff) >> 8, - __builtin_bswap32(0xffffff) >> 8, - - }; OBOS_FlantermContext = flanterm_fb_init( flanterm_malloc, flanterm_free, Arch_MapToHHDM(Arch_Framebuffer->physical_address), Arch_Framebuffer->width, Arch_Framebuffer->height, Arch_Framebuffer->pitch, @@ -318,6 +365,53 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry if (Arch_LdrPlatformInfo->page_table_depth != 4) OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "5-level paging is unsupported by oboskrnl.\n"); +#else + if (Arch_LimineFBRequest.response->framebuffer_count) + { + struct limine_framebuffer *fb = Arch_LimineFBRequest.response->framebuffers[0]; + OBOS_FlantermContext = flanterm_fb_init( + flanterm_malloc, flanterm_free, + fb->address, fb->width, fb->height, fb->pitch, + fb->red_mask_size, fb->red_mask_shift, + fb->green_mask_size, fb->green_mask_shift, + fb->blue_mask_size, fb->blue_mask_shift, + nullptr, ansi_colors, + ansi_bright_colors, nullptr, + nullptr, nullptr, + nullptr, + (void*)font_bin, 8, 16, 0, + 0,0, + 0); + init_flanterm_backend(); + limine_fb0.physical_address = Arch_UnmapFromHHDM(fb->address); + limine_fb0.bpp = fb->bpp; + limine_fb0.width = fb->width; + limine_fb0.height = fb->height; + limine_fb0.pitch = fb->pitch; + do { + if (limine_fb0.bpp == 24) + { + if (fb->blue_mask_shift == 0 && fb->green_mask_shift == 8 && fb->red_mask_shift == 16) + limine_fb0.format = ULTRA_FB_FORMAT_RGB888; + if (fb->red_mask_shift == 0 && fb->green_mask_shift == 8 && fb->blue_mask_shift == 16) + limine_fb0.format = ULTRA_FB_FORMAT_BGR888; + break; + } + else if (limine_fb0.bpp == 32) + { + uint8_t x_shift = 0; + if (fb->red_mask_shift == 16) x_shift = 24; + else if (fb->red_mask_shift == 24) x_shift = 0; + if (x_shift == 0 && fb->blue_mask_shift == 8 && fb->green_mask_shift == 16 && fb->red_mask_shift == 24) + limine_fb0.format = ULTRA_FB_FORMAT_RGBX8888; + if (fb->blue_mask_shift == 0 && fb->green_mask_shift == 8 && fb->red_mask_shift == 16 && x_shift == 24) + limine_fb0.format = ULTRA_FB_FORMAT_XRGB8888; + break; + } + } while(0); + } +#endif + #if OBOS_RELEASE OBOS_Log("Booting OBOS %s committed on %s. Build time: %s.\n", GIT_SHA1, GIT_DATE, __DATE__ " " __TIME__); @@ -391,6 +485,7 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry asm volatile("nop" : : :); } +#if !OBOS_USE_LIMINE volatile struct ultra_memory_map_attribute* Arch_MemoryMap; volatile struct ultra_platform_info_attribute* Arch_LdrPlatformInfo; volatile struct ultra_kernel_info_attribute* Arch_KernelInfo; @@ -437,8 +532,6 @@ static OBOS_PAGEABLE_FUNCTION OBOS_NO_KASAN OBOS_NO_UBSAN void ParseBootContext( struct ultra_module_info_attribute* module = (struct ultra_module_info_attribute*)header; if (strcmp(module->name, "__KERNEL__")) Arch_KernelBinary = module; - else if (strcmp(module->name, "FLANTERM_BUFF")) - Arch_FlantermBumpAllocator = module; break; } case ULTRA_ATTRIBUTE_INVALID: @@ -458,9 +551,9 @@ static OBOS_PAGEABLE_FUNCTION OBOS_NO_KASAN OBOS_NO_UBSAN void ParseBootContext( OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "Invalid partition type %d.\n", Arch_KernelInfo->partition_type); if (!Arch_KernelBinary) OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "Could not find the kernel module in boot context!\nDo you set kernel-as-module to true in the hyper.cfg?\n"); - if (!Arch_FlantermBumpAllocator) - OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "Could not find the FLANTERM_BUFF module in boot context!\nMake sure to pass a module named FLANTERM_BUFF with a size big enough for width*pitch?\n"); + Arch_RSDPBase = Arch_LdrPlatformInfo->acpi_rsdp_address; } +#endif extern obos_status Arch_InitializeKernelPageTable(); @@ -548,6 +641,7 @@ void OBOSS_InitializeSMP() Core_GetCurrentThread()->masterCPU = CoreS_GetCPULocalPtr(); } +#if !OBOS_USE_LIMINE static void ultra_module_to_boot_module(const struct ultra_module_info_attribute *ultra_module, struct boot_module* out_module) { if (!ultra_module || !out_module) @@ -572,6 +666,42 @@ void OBOSS_GetKernelModule(struct boot_module *module) { ultra_module_to_boot_module((void*)Arch_KernelBinary, module); } +#else +static void limine_file_to_boot_module(const struct limine_file *file, struct boot_module* out_module) +{ + if (!file || !out_module) + return; + out_module->address = file->address; + out_module->size = file->size; + out_module->name = file->string; + out_module->is_memory = false; + out_module->is_kernel = file == Arch_LimineKernelInfoRequest.response->executable_file; + return; +} +static struct limine_file* find_module(const char* name, size_t name_len) +{ + for (size_t i = 0; i < Arch_LimineModuleRequest.response->module_count; i++) + { + struct limine_file* cur = Arch_LimineModuleRequest.response->modules[i]; + if (strncmp(cur->string, name, name_len)) + return cur; + } + return nullptr; +} + +void OBOSS_GetModule(struct boot_module *module, const char* name) +{ + limine_file_to_boot_module(find_module(name, strlen(name)), module); +} +void OBOSS_GetModuleLen(struct boot_module *module, const char* name, size_t name_len) +{ + limine_file_to_boot_module(find_module(name, name_len), module); +} +void OBOSS_GetKernelModule(struct boot_module *module) +{ + limine_file_to_boot_module(Arch_LimineKernelInfoRequest.response->executable_file, module); +} +#endif void OBOSS_MakeTTY() { diff --git a/src/oboskrnl/arch/x86_64/ioapic.c b/src/oboskrnl/arch/x86_64/ioapic.c index f0149aaf..4c877898 100644 --- a/src/oboskrnl/arch/x86_64/ioapic.c +++ b/src/oboskrnl/arch/x86_64/ioapic.c @@ -32,7 +32,7 @@ size_t Arch_IOAPICCount; static OBOS_PAGEABLE_FUNCTION OBOS_NO_UBSAN obos_status ParseMADT() { // Find the MADT in the ACPI tables. - ACPIRSDPHeader* rsdp = (ACPIRSDPHeader*)Arch_MapToHHDM(Arch_LdrPlatformInfo->acpi_rsdp_address); + ACPIRSDPHeader* rsdp = (ACPIRSDPHeader*)Arch_MapToHHDM(Arch_RSDPBase); bool tables32 = rsdp->Revision < 2; ACPISDTHeader* xsdt = tables32 ? (ACPISDTHeader*)(uintptr_t)rsdp->RsdtAddress : (ACPISDTHeader*)rsdp->XsdtAddress; xsdt = (ACPISDTHeader*)Arch_MapToHHDM((uintptr_t)xsdt); diff --git a/src/oboskrnl/arch/x86_64/map.c b/src/oboskrnl/arch/x86_64/map.c index 93ef56d0..bc795802 100644 --- a/src/oboskrnl/arch/x86_64/map.c +++ b/src/oboskrnl/arch/x86_64/map.c @@ -373,6 +373,7 @@ obos_status Arch_InitializeKernelPageTable() Elf64_Ehdr* ehdr = (Elf64_Ehdr*)Arch_KernelBinary->address; Elf64_Phdr* phdrs = (Elf64_Phdr*)(Arch_KernelBinary->address + ehdr->e_phoff); size_t i = 0; + uintptr_t kernel_limit = 0; for (; i < ehdr->e_phnum; i++) { Elf64_Phdr* phdr = phdrs + i; @@ -386,8 +387,10 @@ obos_status Arch_InitializeKernelPageTable() if (phdr->p_flags & PF_W) flags |= 2; uintptr_t base = phdr->p_vaddr & ~0xfff; +#if !OBOS_USE_LIMINE if (base < Arch_KernelInfo->virtual_base) OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "Fatal error. Bootloader made a whoopsie! (line %d in file %s). Expression: base < Arch_KernelInfo->virtual_base.\n", __LINE__, __FILE__); +#endif uintptr_t limit = phdr->p_vaddr + phdr->p_memsz; if (limit & 0xfff) limit = (limit + 0xfff) & ~0xfff; @@ -397,6 +400,7 @@ obos_status Arch_InitializeKernelPageTable() OBOS_ASSERT(phys); Arch_MapPage(newCR3, (void*)virt, phys, flags, false); } + kernel_limit = kernel_limit > limit ? kernel_limit : limit; } OBOS_Debug("%s: Mapping HHDM.\n", __func__); for (uintptr_t off = 0; off < Mm_PhysicalMemoryBoundaries; off += 0x200000) @@ -406,8 +410,16 @@ obos_status Arch_InitializeKernelPageTable() uint32_t indices[4] = { 0,0,0,0 }; FreePageTables((uintptr_t*)oldCR3, 3, AddressToIndex(0xffff800000000000, 3), indices); Mm_FreePhysicalPages((uintptr_t)oldCR3, 1); +#if OBOS_USE_LIMINE + OBOSH_BasicMMAddRegion( + &kernel_region, + (void*)Arch_LimineKernelAddressRequest.response->virtual_base, + kernel_limit - Arch_LimineKernelAddressRequest.response->virtual_base); + OBOSH_BasicMMAddRegion(&hhdm_region, (void*)Arch_LimineHHDMRequest.response->offset, Mm_PhysicalMemoryBoundaries); +#else OBOSH_BasicMMAddRegion(&kernel_region, (void*)Arch_KernelInfo->virtual_base, Arch_KernelInfo->size); OBOSH_BasicMMAddRegion(&hhdm_region, (void*)Arch_LdrPlatformInfo->higher_half_base, Mm_PhysicalMemoryBoundaries); +#endif Arch_KernelCR3 = newCR3; return OBOS_STATUS_SUCCESS; } diff --git a/src/oboskrnl/arch/x86_64/pmm.c b/src/oboskrnl/arch/x86_64/pmm.c index 43108692..5654d4e1 100644 --- a/src/oboskrnl/arch/x86_64/pmm.c +++ b/src/oboskrnl/arch/x86_64/pmm.c @@ -11,6 +11,7 @@ #include +#if !OBOS_USE_LIMINE #include extern struct ultra_memory_map_attribute* Arch_MemoryMap; @@ -34,6 +35,32 @@ obos_pmem_map_entry* MmS_GetNextPMemMapEntry(obos_pmem_map_entry* current, uintp #define MAP_TO_HHDM(addr, type) ((type*)(Arch_LdrPlatformInfo->higher_half_base + (uintptr_t)(addr))) #define UNMAP_FROM_HHDM(addr) ((uintptr_t)(addr) - Arch_LdrPlatformInfo->higher_half_base) +#else + +#include + +obos_pmem_map_entry* MmS_GetFirstPMemMapEntry(uintptr_t* index) +{ + *index = 0; + return Arch_LimineMemmapRequest.response->entries[0]; +} +// returns nullptr at the end of the list. +obos_pmem_map_entry* MmS_GetNextPMemMapEntry(obos_pmem_map_entry* current, uintptr_t* index) +{ + OBOS_UNUSED(current); + size_t nEntries = Arch_LimineMemmapRequest.response->entry_count; + if (!nEntries) + OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "No memory map entries.\n"); + if ((*index) >= nEntries) + return nullptr; + return Arch_LimineMemmapRequest.response->entries[++(*index)]; +} + +#define MAP_TO_HHDM(addr, type) ((type*)(Arch_LimineHHDMRequest.response->offset + (uintptr_t)(addr))) +#define UNMAP_FROM_HHDM(addr) ((uintptr_t)(addr) - Arch_LimineHHDMRequest.response->offset) + +#endif + OBOS_NO_KASAN OBOS_NO_UBSAN __attribute__((no_instrument_function)) void* Arch_MapToHHDM(uintptr_t phys) { return MAP_TO_HHDM(phys, void); diff --git a/src/oboskrnl/arch/x86_64/pmm.h b/src/oboskrnl/arch/x86_64/pmm.h index cb767ca4..cec0032f 100644 --- a/src/oboskrnl/arch/x86_64/pmm.h +++ b/src/oboskrnl/arch/x86_64/pmm.h @@ -9,6 +9,8 @@ #include #include +#if !OBOS_USE_LIMINE + #include typedef struct ultra_memory_map_entry obos_pmem_map_entry; @@ -19,5 +21,19 @@ typedef struct ultra_memory_map_entry obos_pmem_map_entry; #define PHYSICAL_MEMORY_TYPE_RECLAIMABLE ULTRA_MEMORY_TYPE_RECLAIMABLE #define PHYSICAL_MEMORY_TYPE_LOADER_RECLAIMABLE ULTRA_MEMORY_TYPE_LOADER_RECLAIMABLE +#else + +#include + +typedef struct limine_memmap_entry obos_pmem_map_entry; +#define pmem_map_base base +#define pmem_map_size length +#define pmem_map_type type +#define PHYSICAL_MEMORY_TYPE_USABLE LIMINE_MEMMAP_USABLE +#define PHYSICAL_MEMORY_TYPE_RECLAIMABLE LIMINE_MEMMAP_ACPI_RECLAIMABLE +#define PHYSICAL_MEMORY_TYPE_LOADER_RECLAIMABLE LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE + +#endif + void* Arch_MapToHHDM(uintptr_t phys); uintptr_t Arch_UnmapFromHHDM(void* virt); \ No newline at end of file diff --git a/src/oboskrnl/arch/x86_64/smp.c b/src/oboskrnl/arch/x86_64/smp.c index ff71a8ca..0fb2868a 100644 --- a/src/oboskrnl/arch/x86_64/smp.c +++ b/src/oboskrnl/arch/x86_64/smp.c @@ -49,7 +49,7 @@ obos_status Arch_MapPage(uintptr_t cr3, void* at_, uintptr_t phys, uintptr_t fla static OBOS_NO_UBSAN void ParseMADT() { // Find the MADT in the ACPI tables. - ACPIRSDPHeader* rsdp = (ACPIRSDPHeader*)Arch_MapToHHDM(Arch_LdrPlatformInfo->acpi_rsdp_address); + ACPIRSDPHeader* rsdp = (ACPIRSDPHeader*)Arch_MapToHHDM(Arch_RSDPBase); bool tables32 = rsdp->Revision < 2; ACPISDTHeader* xsdt = tables32 ? (ACPISDTHeader*)(uintptr_t)rsdp->RsdtAddress : (ACPISDTHeader*)rsdp->XsdtAddress; xsdt = (ACPISDTHeader*)Arch_MapToHHDM((uintptr_t)xsdt); diff --git a/src/oboskrnl/arch/x86_64/timer.c b/src/oboskrnl/arch/x86_64/timer.c index c29235ff..5e9be3b4 100644 --- a/src/oboskrnl/arch/x86_64/timer.c +++ b/src/oboskrnl/arch/x86_64/timer.c @@ -80,7 +80,7 @@ static OBOS_PAGEABLE_FUNCTION OBOS_NO_UBSAN void InitializeHPET() { static basicmm_region hpet_region; hpet_region.mmioRange = true; - ACPIRSDPHeader* rsdp = (ACPIRSDPHeader*)Arch_MapToHHDM(Arch_LdrPlatformInfo->acpi_rsdp_address); + ACPIRSDPHeader* rsdp = (ACPIRSDPHeader*)Arch_MapToHHDM(Arch_RSDPBase); bool tables32 = rsdp->Revision < 2; ACPISDTHeader* xsdt = tables32 ? (ACPISDTHeader*)(uintptr_t)rsdp->RsdtAddress : (ACPISDTHeader*)rsdp->XsdtAddress; xsdt = (ACPISDTHeader*)Arch_MapToHHDM((uintptr_t)xsdt); diff --git a/src/oboskrnl/arch/x86_64/wake.c b/src/oboskrnl/arch/x86_64/wake.c index d38e55fa..744a9faa 100644 --- a/src/oboskrnl/arch/x86_64/wake.c +++ b/src/oboskrnl/arch/x86_64/wake.c @@ -41,6 +41,8 @@ #include +#include + struct { HPET_Timer timer0; uint64_t mainCounterValue; @@ -111,6 +113,23 @@ void OBOSS_SuspendSavePlatformState() index = 0; size_t nvs_index = 0; +# if OBOS_USE_LIMINE + for (obos_pmem_map_entry* entry = MmS_GetFirstPMemMapEntry(&index); entry; ) + { + if (entry->type == LIMINE_MEMMAP_ACPI_NVS) + { + saved_nvs[nvs_index].region_address = Arch_MapToHHDM(entry->base); + saved_nvs[nvs_index].size = entry->length; + saved_nvs[nvs_index].saved_region = Allocate(OBOS_NonPagedPoolAllocator, + saved_nvs[nvs_index].size, + nullptr); + memcpy(saved_nvs[nvs_index].saved_region, saved_nvs[nvs_index].region_address, saved_nvs[nvs_index].size); + nvs_index++; + } + + entry = MmS_GetNextPMemMapEntry(entry, &index); + } +# else for (obos_pmem_map_entry* entry = MmS_GetFirstPMemMapEntry(&index); entry; ) { if (entry->type == ULTRA_MEMORY_TYPE_NVS) @@ -118,14 +137,15 @@ void OBOSS_SuspendSavePlatformState() saved_nvs[nvs_index].region_address = Arch_MapToHHDM(entry->physical_address); saved_nvs[nvs_index].size = entry->size; saved_nvs[nvs_index].saved_region = Allocate(OBOS_NonPagedPoolAllocator, - saved_nvs[nvs_index].size, - nullptr); + saved_nvs[nvs_index].size, + nullptr); memcpy(saved_nvs[nvs_index].saved_region, saved_nvs[nvs_index].region_address, saved_nvs[nvs_index].size); nvs_index++; } entry = MmS_GetNextPMemMapEntry(entry, &index); } +# endif } #endif } diff --git a/src/uACPI/kernel_api.c b/src/uACPI/kernel_api.c index b8f77090..5f9a65c7 100644 --- a/src/uACPI/kernel_api.c +++ b/src/uACPI/kernel_api.c @@ -571,7 +571,7 @@ uacpi_status uacpi_kernel_get_rsdp(uacpi_phys_addr* out) { uintptr_t rsdp = 0; #ifdef __x86_64__ - rsdp = Arch_LdrPlatformInfo->acpi_rsdp_address; + rsdp = Arch_RSDPBase; #endif *out = rsdp; return UACPI_STATUS_OK; From 7bd385dc0ec08d1fd9b6506d0cff0181a161edb6 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 22 Nov 2025 15:15:10 -0500 Subject: [PATCH 17/96] misc: Fix compilation error --- src/oboskrnl/arch/x86_64/wake.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/oboskrnl/arch/x86_64/wake.c b/src/oboskrnl/arch/x86_64/wake.c index 744a9faa..a881fac0 100644 --- a/src/oboskrnl/arch/x86_64/wake.c +++ b/src/oboskrnl/arch/x86_64/wake.c @@ -41,7 +41,9 @@ #include -#include +#if OBOS_USE_LIMINE +# include +#endif struct { HPET_Timer timer0; From 932946d1a0ee5714171ae28540f46011f60602eb Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 22 Nov 2025 15:28:26 -0500 Subject: [PATCH 18/96] misc: Fix bug in build system --- CMakeLists.txt | 3 +++ dependencies/limine.cmake | 14 +++++++------- src/uACPI/CMakeLists.txt | 2 -- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f174ea18..478be4ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,6 +110,9 @@ else() if (NOT EXISTS hyper_install AND OBOS_ARCHITECTURE STREQUAL "x86_64") include("dependencies/hyper.cmake") endif() + if (OBOS_USE_LIMINE AND NOT EXISTS limine_exe) + include("dependencies/limine.cmake") + endif() if (NOT EXISTS uacpi_cmake_file) include("dependencies/uacpi.cmake") endif() diff --git a/dependencies/limine.cmake b/dependencies/limine.cmake index 8d18c968..1d0d4cee 100644 --- a/dependencies/limine.cmake +++ b/dependencies/limine.cmake @@ -11,13 +11,13 @@ FetchContent_Declare(Limine ) FetchContent_MakeAvailable(Limine) if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") -execute_process( - COMMAND "make" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/dependencies/limine - ) - set (limine_exe ${CMAKE_SOURCE_DIR}/dependencies/limine/limine CACHE INTERNAL "x") -# elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows" OR CMAKE_HOST_SYSTEM_NAME STREQUAL "MSYS") -# set (limine_exe ${CMAKE_SOURCE_DIR}/dependencies/limine/limine.exe CACHE INTERNAL "x") + execute_process( + COMMAND "make" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/dependencies/limine + ) + set (limine_exe ${CMAKE_SOURCE_DIR}/dependencies/limine/limine CACHE INTERNAL "x") + # elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows" OR CMAKE_HOST_SYSTEM_NAME STREQUAL "MSYS") + # set (limine_exe ${CMAKE_SOURCE_DIR}/dependencies/limine/limine.exe CACHE INTERNAL "x") else() message(FATAL_ERROR "You must be on to compile OBOS with Limine.") endif() diff --git a/src/uACPI/CMakeLists.txt b/src/uACPI/CMakeLists.txt index 72b4b86a..0657d2d7 100644 --- a/src/uACPI/CMakeLists.txt +++ b/src/uACPI/CMakeLists.txt @@ -26,8 +26,6 @@ endif() # All symbols exported, except for the kernel api of course. set_source_files_properties("kernel_api.c" PROPERTIES COMPILE_OPTIONS "-fvisibility=hidden") -message(${OBOSKRNL_EXTERNAL_INCLUDES}) - target_include_directories(uacpi PRIVATE "${CMAKE_SOURCE_DIR}/src/oboskrnl") target_include_directories(uacpi PRIVATE "${CMAKE_SOURCE_DIR}/src/sanitizers") target_include_directories(uacpi PRIVATE ${OBOSKRNL_EXTERNAL_INCLUDES}) From 32217f4c2901a12e5c0a358261591db71489fb10 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 22 Nov 2025 15:58:42 -0500 Subject: [PATCH 19/96] extfs: Check if inode is not null before blindly using it --- src/drivers/generic/extfs/probe.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/drivers/generic/extfs/probe.c b/src/drivers/generic/extfs/probe.c index f9cfcfa2..931add18 100644 --- a/src/drivers/generic/extfs/probe.c +++ b/src/drivers/generic/extfs/probe.c @@ -140,7 +140,10 @@ vnode* ext_make_vnode(ext_cache* cache, uint32_t ino, mount* mnt) } ext_inode* inode = ext_read_inode(cache, ino); - + OBOS_ASSERT(inode); + if (!inode) + return nullptr; + uint32_t vtype = 0; if (ext_ino_test_type(inode, EXT2_S_IFDIR)) vtype = VNODE_TYPE_DIR; From 43484f6f6ad2c5d77784504a3fe7e2257c9e41bd Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 22 Nov 2025 15:59:43 -0500 Subject: [PATCH 20/96] x86_64: Fix bug in early boot code --- src/oboskrnl/arch/x86_64/entry.asm | 51 ++++++++++++++++-------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/src/oboskrnl/arch/x86_64/entry.asm b/src/oboskrnl/arch/x86_64/entry.asm index 79176293..0f77a3bd 100644 --- a/src/oboskrnl/arch/x86_64/entry.asm +++ b/src/oboskrnl/arch/x86_64/entry.asm @@ -25,29 +25,34 @@ Arch_KernelEntryBootstrap: push rsi ; Get a hardware-generated random value. ; If both methods are unsupported, it will fallback to using the default value used. -.rdrand: - mov eax, 1 - xor ecx,ecx - cpuid - bt ecx, 30 - jnc .rdseed - rdrand rax - jnc .rdrand - jmp .move -.rdseed: - mov eax, 7 - xor ecx,ecx - cpuid - bt ebx, 18 - jnc .done - rdseed rax - jnc .rdseed -.move: - ; Move the (likely) random value into the stack guard variable. - mov [__stack_chk_guard], rax -.done: - call Arch_disablePIC - ; Turn on cr0.WP (write protect) + mov rcx, 10 + .rdrand: + mov eax, 1 + xor ecx,ecx + cpuid + bt ecx, 30 + jnc .rdseed + rdrand rax + jc .move + loop .rdrand + mov rcx, 10 + .rdseed: + mov eax, 7 + xor ecx,ecx + cpuid + bt ebx, 18 + jnc .done + rdseed rax + jc .move + loop .rdseed + test rcx, rcx + jz .done + .move: + ; Move the (likely) random value into the stack guard variable. + mov [__stack_chk_guard], rax + .done: + call Arch_disablePIC + ; Turn on cr0.WP (write protect) mov rax, cr0 or rax, (1<<16) ; WP mov cr0, rax From bed8b65a2f974df1772818fea16cff9651923834 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 22 Nov 2025 16:50:12 -0500 Subject: [PATCH 21/96] Revert 6b0be519151480050b19d9eef2c213bbc1becf96 --- src/oboskrnl/arch/x86_64/entry.asm | 51 ++++++++++++++---------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/src/oboskrnl/arch/x86_64/entry.asm b/src/oboskrnl/arch/x86_64/entry.asm index 0f77a3bd..79176293 100644 --- a/src/oboskrnl/arch/x86_64/entry.asm +++ b/src/oboskrnl/arch/x86_64/entry.asm @@ -25,34 +25,29 @@ Arch_KernelEntryBootstrap: push rsi ; Get a hardware-generated random value. ; If both methods are unsupported, it will fallback to using the default value used. - mov rcx, 10 - .rdrand: - mov eax, 1 - xor ecx,ecx - cpuid - bt ecx, 30 - jnc .rdseed - rdrand rax - jc .move - loop .rdrand - mov rcx, 10 - .rdseed: - mov eax, 7 - xor ecx,ecx - cpuid - bt ebx, 18 - jnc .done - rdseed rax - jc .move - loop .rdseed - test rcx, rcx - jz .done - .move: - ; Move the (likely) random value into the stack guard variable. - mov [__stack_chk_guard], rax - .done: - call Arch_disablePIC - ; Turn on cr0.WP (write protect) +.rdrand: + mov eax, 1 + xor ecx,ecx + cpuid + bt ecx, 30 + jnc .rdseed + rdrand rax + jnc .rdrand + jmp .move +.rdseed: + mov eax, 7 + xor ecx,ecx + cpuid + bt ebx, 18 + jnc .done + rdseed rax + jnc .rdseed +.move: + ; Move the (likely) random value into the stack guard variable. + mov [__stack_chk_guard], rax +.done: + call Arch_disablePIC + ; Turn on cr0.WP (write protect) mov rax, cr0 or rax, (1<<16) ; WP mov cr0, rax From 3cfedd59a2676b8a88999dfe6a00d23d83a6cefd Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 22 Nov 2025 20:37:24 -0500 Subject: [PATCH 22/96] e1000: Changes --- src/drivers/generic/freebsd-e1000/dev.h | 7 ++-- src/drivers/generic/freebsd-e1000/io.c | 23 +++++++++---- src/drivers/generic/freebsd-e1000/main.c | 44 ++++++++++++++++-------- 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/src/drivers/generic/freebsd-e1000/dev.h b/src/drivers/generic/freebsd-e1000/dev.h index 7ff1f103..c7b3f6f7 100644 --- a/src/drivers/generic/freebsd-e1000/dev.h +++ b/src/drivers/generic/freebsd-e1000/dev.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include @@ -19,7 +20,8 @@ #include #define RX_QUEUE_SIZE (32) -#define TX_QUEUE_SIZE (8) +#define TX_QUEUE_SIZE (32) +#define TX_BUFFER_PAGES (4) typedef struct e1000_frame { void* buff; @@ -51,6 +53,7 @@ typedef struct e1000_device { page* tx_ring_phys_pg; size_t tx_index; event tx_done_evnt; + uintptr_t tx_buffers[TX_QUEUE_SIZE]; size_t refs; @@ -80,7 +83,7 @@ typedef struct e1000_handle { void e1000_init_rx(e1000_device* dev); void e1000_init_tx(e1000_device* dev); -event* e1000_tx_packet(e1000_device* dev, const void* buffer, size_t size, bool dry); +event* e1000_tx_packet(e1000_device* dev, const void* buffer, size_t size, bool dry, obos_status* status); void e1000_irq_handler(struct irq* i, interrupt_frame* frame, void* userdata, irql oldIrql); bool e1000_check_irq_callback(struct irq* i, void* userdata); \ No newline at end of file diff --git a/src/drivers/generic/freebsd-e1000/io.c b/src/drivers/generic/freebsd-e1000/io.c index 6b638990..25b2d1d2 100644 --- a/src/drivers/generic/freebsd-e1000/io.c +++ b/src/drivers/generic/freebsd-e1000/io.c @@ -7,6 +7,7 @@ */ #include +#include #include @@ -17,6 +18,7 @@ #include #include +#include #include @@ -24,8 +26,11 @@ #include +#include + #include "dev.h" + LIST_GENERATE(e1000_frame_list, e1000_frame, node); #define EM_RADV 64 @@ -194,7 +199,8 @@ void e1000_init_tx(e1000_device* dev) struct e1000_tx_desc* desc = ((struct e1000_tx_desc*)MmS_MapVirtFromPhys(dev->tx_ring)); for (size_t i = 0; i < TX_QUEUE_SIZE; i++) { - desc[i].buffer_addr = 0; + dev->tx_buffers[i] = Mm_AllocatePhysicalPages(TX_BUFFER_PAGES, 1, nullptr); + desc[i].buffer_addr = dev->tx_buffers[i]; desc[i].lower.data = 0; desc[i].upper.fields.status = E1000_TXD_STAT_DD; } @@ -297,7 +303,7 @@ void e1000_init_tx(e1000_device* dev) void e1000_tx_reap(e1000_device* dev); -event* e1000_tx_packet(e1000_device* dev, const void* buffer, size_t size, bool dry) +event* e1000_tx_packet(e1000_device* dev, const void* buffer, size_t size, bool dry, obos_status* status) { e1000_tx_reap(dev); volatile struct e1000_tx_desc* desc = &((volatile struct e1000_tx_desc*)MmS_MapVirtFromPhys(dev->tx_ring))[dev->tx_index % TX_QUEUE_SIZE]; @@ -308,18 +314,23 @@ event* e1000_tx_packet(e1000_device* dev, const void* buffer, size_t size, bool size_t nPages = size / OBOS_PAGE_SIZE; if (size % OBOS_PAGE_SIZE) nPages++; - uintptr_t buff = Mm_AllocatePhysicalPages(nPages, 1, nullptr); + if (nPages > TX_BUFFER_PAGES) + return nullptr; + uintptr_t buff = dev->tx_buffers[dev->tx_index]; memcpy(MmS_MapVirtFromPhys(buff), buffer, size); desc->buffer_addr = buff; desc->upper.data = 0; desc->lower.data = size | E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS; E1000_WRITE_REG(&dev->hw, E1000_TDT(0), ++dev->tx_index % TX_QUEUE_SIZE); - while (~desc->upper.data & E1000_TXD_STAT_DD) - continue; // printf("ret from %s, upper.data=0x%x, lower.data=0x%x, buffer=0x%p\n", __func__, desc->upper.data, desc->lower.data, desc->buffer_addr); - Core_LowerIrql(oldIrql); + + uintptr_t deadline = CoreS_GetTimerTick() + CoreH_TimeFrameToTick(1*1000*1000); + while (~desc->upper.data & E1000_TXD_STAT_DD && CoreS_GetTimerTick() < deadline) + Core_Yield(); + if (~desc->upper.data & E1000_TXD_STAT_DD) + *status = OBOS_STATUS_TIMED_OUT; return nullptr; } diff --git a/src/drivers/generic/freebsd-e1000/main.c b/src/drivers/generic/freebsd-e1000/main.c index 6d531ee6..9c487faa 100644 --- a/src/drivers/generic/freebsd-e1000/main.c +++ b/src/drivers/generic/freebsd-e1000/main.c @@ -6,6 +6,7 @@ #include #include +#include #include @@ -29,6 +30,7 @@ #include #include "dev.h" +#include "e1000/e1000_defines.h" OBOS_PAGEABLE_FUNCTION obos_status get_blk_size(dev_desc desc, size_t* blkSize) { @@ -124,9 +126,11 @@ static void irp_on_tx_event_set(irp* req) e1000_handle* hnd = (void*)req->desc; if (req->evnt) Core_EventClear(req->evnt); - req->evnt = e1000_tx_packet(hnd->dev, req->cbuff,req->blkCount, req->dryOp); + req->status = OBOS_STATUS_SUCCESS; + req->evnt = e1000_tx_packet(hnd->dev, req->cbuff,req->blkCount, req->dryOp, &req->status); req->on_event_set = nullptr; - req->status = req->evnt ? OBOS_STATUS_IRP_RETRY : OBOS_STATUS_SUCCESS; + if (obos_is_success(req->status)) + req->status = req->evnt ? OBOS_STATUS_IRP_RETRY : OBOS_STATUS_SUCCESS; if (req->status) req->nBlkWritten = req->blkCount; } @@ -152,9 +156,9 @@ obos_status submit_irp(void* request) } else { - req->evnt = e1000_tx_packet(hnd->dev, req->cbuff, req->blkCount, req->dryOp); + req->status = OBOS_STATUS_SUCCESS; + req->evnt = e1000_tx_packet(hnd->dev, req->cbuff, req->blkCount, req->dryOp, &req->status); req->on_event_set = irp_on_tx_event_set; - req->status = req->evnt ? OBOS_STATUS_IRP_RETRY : OBOS_STATUS_SUCCESS; if (obos_is_success(req->status)) req->nBlkWritten = req->blkCount; } @@ -393,16 +397,6 @@ static void search_bus(pci_bus* bus) e1000_get_bus_info(&Devices[nDevices-1].hw); - if (e1000_reset_hw(&Devices[nDevices-1].hw) != E1000_SUCCESS) - { - Mm_VirtualMemoryFree(&Mm_KernelContext, (void*)Devices[nDevices-1].osdep.membase, bar0->bar->size); - nDevices--; - Devices = Reallocate(OBOS_NonPagedPoolAllocator, Devices, nDevices*sizeof(e1000_device), (nDevices+1)*sizeof(e1000_device), nullptr); - OBOS_Warning("%02x:%02x:%02x: Bogus E1000 PCI node.", dev->location.bus, dev->location.slot, dev->location.function); - dev = LIST_GET_NEXT(pci_device_list, &bus->devices, dev); - continue; - } - Devices[nDevices-1].hw.mac.autoneg = 1; Devices[nDevices-1].hw.phy.autoneg_wait_to_complete = false; Devices[nDevices-1].hw.phy.autoneg_advertised = (ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | ADVERTISE_100_FULL | ADVERTISE_1000_FULL); @@ -414,6 +408,26 @@ static void search_bus(pci_bus* bus) } Devices[nDevices-1].hw.mac.report_tx_early = true; + + if (e1000_reset_hw(&Devices[nDevices-1].hw) != E1000_SUCCESS) + { + Mm_VirtualMemoryFree(&Mm_KernelContext, (void*)Devices[nDevices-1].osdep.membase, bar0->bar->size); + nDevices--; + Devices = Reallocate(OBOS_NonPagedPoolAllocator, Devices, nDevices*sizeof(e1000_device), (nDevices+1)*sizeof(e1000_device), nullptr); + OBOS_Warning("%02x:%02x:%02x: Bogus E1000 PCI node.", dev->location.bus, dev->location.slot, dev->location.function); + dev = LIST_GET_NEXT(pci_device_list, &bus->devices, dev); + continue; + } + + if (e1000_validate_nvm_checksum(&Devices[nDevices-1].hw) != E1000_SUCCESS) + { + Mm_VirtualMemoryFree(&Mm_KernelContext, (void*)Devices[nDevices-1].osdep.membase, bar0->bar->size); + nDevices--; + Devices = Reallocate(OBOS_NonPagedPoolAllocator, Devices, nDevices*sizeof(e1000_device), (nDevices+1)*sizeof(e1000_device), nullptr); + OBOS_Warning("%02x:%02x:%02x: Bogus E1000 PCI node.", dev->location.bus, dev->location.slot, dev->location.function); + dev = LIST_GET_NEXT(pci_device_list, &bus->devices, dev); + continue; + } // if (e1000_init_hw(&Devices[nDevices-1].hw) != E1000_SUCCESS) // { @@ -444,8 +458,8 @@ static void search_bus(pci_bus* bus) Devices[nDevices-1].irq.irqCheckerUserdata = Devices + nDevices - 1; Devices[nDevices-1].irq.handlerUserdata = Devices + nDevices - 1; - e1000_init_tx(&Devices[nDevices-1]); e1000_init_rx(&Devices[nDevices-1]); + e1000_init_tx(&Devices[nDevices-1]); e1000_clear_hw_cntrs_base_generic(&Devices[nDevices-1].hw); E1000_WRITE_REG(&Devices[nDevices-1].hw, E1000_IMS, IMS_ENABLE_MASK); From d9b1b937ffa86214c84c0fc4bfd23faa26d902c6 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 22 Nov 2025 20:37:40 -0500 Subject: [PATCH 23/96] x86_64: Print bootloader on boot in release configurations --- src/oboskrnl/arch/x86_64/boot_info.h | 1 + src/oboskrnl/arch/x86_64/entry.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/oboskrnl/arch/x86_64/boot_info.h b/src/oboskrnl/arch/x86_64/boot_info.h index 5aa7aa6e..eebfe263 100644 --- a/src/oboskrnl/arch/x86_64/boot_info.h +++ b/src/oboskrnl/arch/x86_64/boot_info.h @@ -29,6 +29,7 @@ extern volatile struct limine_hhdm_request Arch_LimineHHDMRequest; extern volatile struct limine_executable_file_request Arch_LimineKernelInfoRequest; extern volatile struct limine_executable_address_request Arch_LimineKernelAddressRequest; extern volatile struct limine_executable_cmdline_request Arch_LimineKernelCmdlineRequest; +extern volatile struct limine_bootloader_info_request Arch_LimineBtldrInfoRequest; extern volatile struct ultra_framebuffer* Arch_Framebuffer; // Artificially created extern struct limine_file* Arch_KernelBinary; #endif diff --git a/src/oboskrnl/arch/x86_64/entry.c b/src/oboskrnl/arch/x86_64/entry.c index 0d484088..f3b5b01c 100644 --- a/src/oboskrnl/arch/x86_64/entry.c +++ b/src/oboskrnl/arch/x86_64/entry.c @@ -224,6 +224,10 @@ volatile struct limine_rsdp_request Arch_LimineRSDPRequest = { .id = LIMINE_RSDP_REQUEST_ID, .revision = 0, }; +volatile struct limine_bootloader_info_request Arch_LimineBtldrInfoRequest = { + .id = LIMINE_BOOTLOADER_INFO_REQUEST_ID, + .revision = 0, +}; volatile struct ultra_framebuffer limine_fb0 = {}; volatile struct ultra_framebuffer* Arch_Framebuffer = &limine_fb0; struct limine_file* Arch_KernelBinary = nullptr; @@ -427,8 +431,15 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry __cpuid__(0x80000003, 0, (uint32_t*)&brand_string[16], (uint32_t*)&brand_string[20], (uint32_t*)&brand_string[24], (uint32_t*)&brand_string[28]); __cpuid__(0x80000004, 0, (uint32_t*)&brand_string[32], (uint32_t*)&brand_string[36], (uint32_t*)&brand_string[40], (uint32_t*)&brand_string[44]); OBOS_Log("Running on a %s processor, cpu brand string, %s. We are currently %srunning on a hypervisor\n", cpu_vendor, brand_string, isHypervisor ? "" : "not "); + +#if OBOS_USE_LIMINE + OBOS_Log("Bootloader is %s-%s\n", Arch_LimineBtldrInfoRequest.response->name, Arch_LimineBtldrInfoRequest.response->version); +#else + OBOS_Log("Bootloader is %.32s\n", Arch_LdrPlatformInfo->loader_name, Arch_LdrPlatformInfo->loader_major, Arch_LdrPlatformInfo->loader_minor); #endif +#endif + OBOS_Debug("%s: Initializing the Boot GDT.\n", __func__); Arch_InitBootGDT(); From 8c0a299daf362ab56332dc326f776bbc3f1b97c7 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Mon, 24 Nov 2025 17:21:17 -0500 Subject: [PATCH 24/96] init: Only waitpid() on the handoff process --- src/init/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/init/main.c b/src/init/main.c index 339db47a..364330df 100644 --- a/src/init/main.c +++ b/src/init/main.c @@ -177,9 +177,9 @@ int main(int argc, char** argv) } int status; top: - waitpid(pid, &status, 0); + waitpid(pid, &status, pid); if (WIFSIGNALED(status)) - printf("Child exitted due to signal %d\n", WTERMSIG(status)); + printf("Handoff process exited due to signal %d\n", WTERMSIG(status)); if (!WIFEXITED(status) && !WIFSIGNALED(status)) goto top; sigchld_handler(SIGCHLD); From 6a777838cd5454cc1a67ce60758845c924b1fbfa Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Mon, 24 Nov 2025 17:22:02 -0500 Subject: [PATCH 25/96] misc: Handle Core_WaitOnObject(s) errors --- src/drivers/generic/ahci/command.c | 8 +++-- src/drivers/generic/ahci/interface.c | 14 ++++++-- src/drivers/generic/libps2/keyboard.c | 4 ++- src/drivers/generic/libps2/mouse.c | 4 ++- src/drivers/test_driver/fireworks.c | 2 +- src/oboskrnl/arch/m68k/gf_tty.c | 4 ++- src/oboskrnl/arch/x86_64/gdbstub/connection.c | 4 +-- .../arch/x86_64/gdbstub/gdb_udp_backend.c | 4 ++- src/oboskrnl/locks/pushlock.c | 5 ++- src/oboskrnl/locks/semaphore.c | 4 ++- src/oboskrnl/locks/wait.h | 6 ++-- src/oboskrnl/mm/swap.c | 7 ++-- src/oboskrnl/net/arp.c | 7 ++-- src/oboskrnl/net/route.c | 4 ++- src/oboskrnl/net/tcp.c | 36 +++++++++++-------- src/oboskrnl/net/udp.c | 7 +++- src/oboskrnl/signal.c | 3 +- src/oboskrnl/vfs/fd_sys.c | 16 +++++++-- src/oboskrnl/vfs/local_socket.c | 4 ++- src/oboskrnl/vfs/pipe.c | 4 ++- src/uHDA/hdadev.c | 3 +- 21 files changed, 108 insertions(+), 42 deletions(-) diff --git a/src/drivers/generic/ahci/command.c b/src/drivers/generic/ahci/command.c index 8796aaef..e5e0bd04 100644 --- a/src/drivers/generic/ahci/command.c +++ b/src/drivers/generic/ahci/command.c @@ -14,7 +14,8 @@ #include -#include "locks/wait.h" +#include + #include "structs.h" #include "command.h" @@ -159,6 +160,9 @@ void WaitForTranscations() Port* port = Ports + i; for (size_t j = 0; j < 32; j++) if (port->CommandBitmask & BIT(j) && port->PendingCommands[j]) - Core_WaitOnObject(WAITABLE_OBJECT(port->PendingCommands[j]->completionEvent)); + { + obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(port->PendingCommands[j]->completionEvent)); + OBOS_UNUSED(status); + } } } diff --git a/src/drivers/generic/ahci/interface.c b/src/drivers/generic/ahci/interface.c index cdd9513b..d94035e8 100644 --- a/src/drivers/generic/ahci/interface.c +++ b/src/drivers/generic/ahci/interface.c @@ -220,7 +220,12 @@ obos_status read_sync(dev_desc desc, void* buf, size_t blkCount, size_t blkOffse // irql oldIrql = Core_RaiseIrql(IRQL_AHCI); SendCommand(port, &data, blkOffset, 0x40, blkCount == 0x10000 ? 0 : blkCount); // Core_LowerIrql(oldIrql); - Core_WaitOnObject(WAITABLE_OBJECT(data.completionEvent)); + if (obos_is_error(status = Core_WaitOnObject(WAITABLE_OBJECT(data.completionEvent)))) + { + Core_SemaphoreRelease(&port->lock); + unpopulate_physical_regions((uintptr_t)buf, blkCount*port->sectorSize, &data); + break; + } Core_EventClear(&data.completionEvent); if (!port->works) { @@ -280,7 +285,12 @@ obos_status write_sync(dev_desc desc, const void* buf, size_t blkCount, size_t b { SendCommand(port, &data, blkOffset, 0x40, blkCount == 0x10000 ? 0 : blkCount); HBA->ghc |= BIT(1) /* GhcIE */; - Core_WaitOnObject(WAITABLE_OBJECT(data.completionEvent)); + if (obos_is_error(status = Core_WaitOnObject(WAITABLE_OBJECT(data.completionEvent)))) + { + Core_SemaphoreRelease(&port->lock); + unpopulate_physical_regions((uintptr_t)buf, blkCount*port->sectorSize, &data); + break; + } Core_EventClear(&data.completionEvent); if (!port->works) { diff --git a/src/drivers/generic/libps2/keyboard.c b/src/drivers/generic/libps2/keyboard.c index 02822840..8b0afb32 100644 --- a/src/drivers/generic/libps2/keyboard.c +++ b/src/drivers/generic/libps2/keyboard.c @@ -155,7 +155,9 @@ static obos_status read_code(void* handle, keycode* out, bool block) if (!Core_EventGetState(port->data_ready_event) && !block) return OBOS_STATUS_WOULD_BLOCK; - Core_WaitOnObject(WAITABLE_OBJECT(*port->data_ready_event)); + obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(*port->data_ready_event)); + if (obos_is_error(status)) + return status; } return PS2_RingbufferFetchKeycode(&data->input, &hnd->in_ptr, out); diff --git a/src/drivers/generic/libps2/mouse.c b/src/drivers/generic/libps2/mouse.c index 29b197a8..5c3768bc 100644 --- a/src/drivers/generic/libps2/mouse.c +++ b/src/drivers/generic/libps2/mouse.c @@ -36,7 +36,9 @@ static obos_status read_pckt(void* handle, mouse_packet* out, bool block) if (!Core_EventGetState(port->data_ready_event) && !block) return OBOS_STATUS_WOULD_BLOCK; - Core_WaitOnObject(WAITABLE_OBJECT(*port->data_ready_event)); + obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(*port->data_ready_event)); + if (obos_is_error(status)) + return status; } return PS2_RingbufferFetchMousePacket(&data->packets, &hnd->in_ptr, out); diff --git a/src/drivers/test_driver/fireworks.c b/src/drivers/test_driver/fireworks.c index ed3b4c1e..7e099a39 100644 --- a/src/drivers/test_driver/fireworks.c +++ b/src/drivers/test_driver/fireworks.c @@ -290,7 +290,7 @@ void particle_handler(void* udata) udata[3] = t.lastTimeTicked; if (obos_is_error(status)) goto die; - Core_WaitOnObject(WAITABLE_OBJECT(e)); + status = Core_WaitOnObject(WAITABLE_OBJECT(e)); goto die; } int t = 0; diff --git a/src/oboskrnl/arch/m68k/gf_tty.c b/src/oboskrnl/arch/m68k/gf_tty.c index c9783f97..8ba91c72 100644 --- a/src/oboskrnl/arch/m68k/gf_tty.c +++ b/src/oboskrnl/arch/m68k/gf_tty.c @@ -4,6 +4,7 @@ * Copyright (c) 2025 Omar Berrow */ +#include "error.h" #include #include @@ -92,7 +93,8 @@ static void poll_gf_tty(struct gf_tty_iface* iface) // struct gf_tty* dev = (void*)Arch_TTYBase; while (1) { - Core_WaitOnObject(WAITABLE_OBJECT(iface->data_ready_evnt)); + if (obos_is_error(Core_WaitOnObject(WAITABLE_OBJECT(iface->data_ready_evnt)))) + continue; irql oldIrql = Core_RaiseIrql(IRQL_DISPATCH); if (iface->data_ready) { diff --git a/src/oboskrnl/arch/x86_64/gdbstub/connection.c b/src/oboskrnl/arch/x86_64/gdbstub/connection.c index a3f7d15a..d2543deb 100644 --- a/src/oboskrnl/arch/x86_64/gdbstub/connection.c +++ b/src/oboskrnl/arch/x86_64/gdbstub/connection.c @@ -432,7 +432,5 @@ obos_status SysS_GDBStubStart() CoreH_ThreadInitialize(&gdb_thread, THREAD_PRIORITY_NORMAL, Core_DefaultThreadAffinity, &ctx); Core_ProcessAppendThread(OBOS_KernelProcess, &gdb_thread); CoreH_ThreadReady(&gdb_thread); - Core_WaitOnObject(WAITABLE_OBJECT(gdb_connected)); - - return OBOS_STATUS_SUCCESS; + return Core_WaitOnObject(WAITABLE_OBJECT(gdb_connected)); } \ No newline at end of file diff --git a/src/oboskrnl/arch/x86_64/gdbstub/gdb_udp_backend.c b/src/oboskrnl/arch/x86_64/gdbstub/gdb_udp_backend.c index 70ada517..f2a46ec0 100644 --- a/src/oboskrnl/arch/x86_64/gdbstub/gdb_udp_backend.c +++ b/src/oboskrnl/arch/x86_64/gdbstub/gdb_udp_backend.c @@ -79,7 +79,9 @@ static obos_status read_sync(dev_desc desc, void* buf, size_t blkCount, size_t b while (!hnd->curr_rx) { - Core_WaitOnObject(WAITABLE_OBJECT(hnd->bound_port->recv_event)); + obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(hnd->bound_port->recv_event)); + if (obos_is_error(status)) + return status; Core_EventClear(&hnd->bound_port->recv_event); udp_recv_packet* recv_packet = LIST_GET_HEAD(frame_queue, &hnd->bound_port->packets); if (!recv_packet) diff --git a/src/oboskrnl/locks/pushlock.c b/src/oboskrnl/locks/pushlock.c index cd11dca2..9ae44e0e 100644 --- a/src/oboskrnl/locks/pushlock.c +++ b/src/oboskrnl/locks/pushlock.c @@ -33,7 +33,10 @@ obos_status Core_PushlockAcquire(pushlock* lock, bool reader /* false: writer, t // Hopefully this is right. // maybe a possible race condition. try_again: - Core_WaitOnObject(&lock->hdr); + (void)0; + obos_status status = Core_WaitOnObject(&lock->hdr); + if (obos_is_error(status)) + return status; CoreH_ClearSignaledState(&lock->hdr); if (lock->nWaitingReaders) goto try_again; diff --git a/src/oboskrnl/locks/semaphore.c b/src/oboskrnl/locks/semaphore.c index a7f1b19a..8a9e7ca1 100644 --- a/src/oboskrnl/locks/semaphore.c +++ b/src/oboskrnl/locks/semaphore.c @@ -35,7 +35,9 @@ obos_status Core_SemaphoreAcquire(semaphore* sem) } Core_SpinlockRelease(&sem->lock, oldIrql); // Add the current thread to the waiting list. - Core_WaitOnObject(&sem->hdr); + obos_status status = Core_WaitOnObject(&sem->hdr); + if (obos_is_error(status)) + return status; oldIrql = Core_SpinlockAcquire(&sem->lock); sem->count--; Core_SpinlockRelease(&sem->lock, oldIrql); diff --git a/src/oboskrnl/locks/wait.h b/src/oboskrnl/locks/wait.h index 9598a069..0ad93c8a 100644 --- a/src/oboskrnl/locks/wait.h +++ b/src/oboskrnl/locks/wait.h @@ -35,9 +35,11 @@ struct waitable_header // otherwise, this will not work, and will corrupt stuff. #define WAITABLE_OBJECT(obj) (struct waitable_header*)(&(obj)) -OBOS_EXPORT obos_status Core_WaitOnObject(struct waitable_header* obj); +OBOS_EXPORT + OBOS_NODISCARD_REASON("Handle errors from Core_WaitOnObject") obos_status Core_WaitOnObject(struct waitable_header* obj); // Waits until at least one object is signaled. -OBOS_EXPORT obos_status Core_WaitOnObjects(size_t nObjects, struct waitable_header** objs, struct waitable_header** signaled); +OBOS_EXPORT + OBOS_NODISCARD_REASON("Handle errors from Core_WaitOnObjects") obos_status Core_WaitOnObjects(size_t nObjects, struct waitable_header** objs, struct waitable_header** signaled); OBOS_EXPORT obos_status CoreH_SignalWaitingThreads(struct waitable_header* obj, bool all, bool boostPriority); OBOS_EXPORT void CoreH_ClearSignaledState(struct waitable_header* obj); OBOS_EXPORT obos_status CoreH_AbortWaitingThreads(struct waitable_header* obj); \ No newline at end of file diff --git a/src/oboskrnl/mm/swap.c b/src/oboskrnl/mm/swap.c index 42404e52..617de82f 100644 --- a/src/oboskrnl/mm/swap.c +++ b/src/oboskrnl/mm/swap.c @@ -176,7 +176,8 @@ static __attribute__((no_instrument_function)) void page_writer() // const char* const This = "Page Writer"; while (1) { - Core_WaitOnObject(WAITABLE_OBJECT(page_writer_wake)); + obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(page_writer_wake)); + OBOS_ENSURE(obos_is_success(status)); Core_EventClear(&page_writer_done); if (!Mm_PageWriterOperation) Mm_PageWriterOperation = PAGE_WRITER_SYNC_ALL; @@ -365,8 +366,10 @@ void Mm_WakePageWriter(bool wait) { OBOS_ASSERT(page_writer_thread.status); Core_EventPulse(&page_writer_wake, true); + obos_status status = OBOS_STATUS_SUCCESS; if (wait) - Core_WaitOnObject(WAITABLE_OBJECT(page_writer_done)); + status = Core_WaitOnObject(WAITABLE_OBJECT(page_writer_done)); + OBOS_UNUSED(status); } irql Mm_TakeSwapLock() diff --git a/src/oboskrnl/net/arp.c b/src/oboskrnl/net/arp.c index 0e6226a7..29eac63a 100644 --- a/src/oboskrnl/net/arp.c +++ b/src/oboskrnl/net/arp.c @@ -47,9 +47,12 @@ obos_status NetH_ARPRequest(vnode* nic, ip_addr addr, mac_address* out, address_ address_table_entry* ent = RB_FIND(address_table, &nic->net_tables->arp_cache, &what); Core_PushlockRelease(&nic->net_tables->arp_cache_lock, true); + obos_status status = OBOS_STATUS_SUCCESS; if (ent) { - Core_WaitOnObject(WAITABLE_OBJECT(ent->sync)); + status = Core_WaitOnObject(WAITABLE_OBJECT(ent->sync)); + if (obos_is_error(status)) + return status; if (memcmp_b(ent->phys, 0, sizeof(mac_address))) { Core_PushlockAcquire(&nic->net_tables->arp_cache_lock, true); @@ -91,7 +94,7 @@ obos_status NetH_ARPRequest(vnode* nic, ip_addr addr, mac_address* out, address_ memzero(payload->target_mac, sizeof(payload->target_mac)); shared_ptr *eth = NetH_FormatEthernetPacket(nic, MAC_BROADCAST, hdr, sz_hdr, ETHERNET2_TYPE_ARP); - obos_status status = NetH_SendEthernetPacket(nic, OBOS_SharedPtrCopy(eth)); + status = NetH_SendEthernetPacket(nic, OBOS_SharedPtrCopy(eth)); if (obos_is_error(status)) { Core_PushlockAcquire(&nic->net_tables->table_lock, false); diff --git a/src/oboskrnl/net/route.c b/src/oboskrnl/net/route.c index 04c34689..1a8ffff9 100644 --- a/src/oboskrnl/net/route.c +++ b/src/oboskrnl/net/route.c @@ -262,7 +262,9 @@ obos_status NetH_AddressRoute(net_tables** interface, ip_table_entry** routing_e shared_ptr data = {}; OBOS_SharedPtrConstruct(&data, &hdr); NetH_SendIPv4Packet(curr->iface->interface, curr->ent, destination, 0x11, curr->ttl, 0, OBOS_SharedPtrCopy(&data)); - Core_WaitOnObject(WAITABLE_OBJECT(port->recv_event)); + obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(port->recv_event)); + if (obos_is_error(status)) + return status; icmp_header* icmp_hdr = port->icmp_header; shared_ptr* icmp_hdr_ptr = port->icmp_header_ptr; diff --git a/src/oboskrnl/net/tcp.c b/src/oboskrnl/net/tcp.c index 118c54c6..853b2e01 100644 --- a/src/oboskrnl/net/tcp.c +++ b/src/oboskrnl/net/tcp.c @@ -4,6 +4,7 @@ * Copyright (c) 2025 Omar Berrow */ +#include "error.h" #include #include #include @@ -1174,9 +1175,16 @@ static void internal_listen_thread(void* udata) objs[i] = WAITABLE_OBJECT(s->serv.bound_ports[i-1]->connection_event); while (1) { - Core_WaitOnObjects(s->serv.bound_port_count+1, objs, &signaled); + obos_status status = OBOS_STATUS_SUCCESS; + if (obos_is_error(status = Core_WaitOnObjects(s->serv.bound_port_count+1, objs, &signaled))) + { + NetError("Net: %s: Core_WaitOnObjects returned %d, aborting.\n", __func__, status); + break; + } + if (signaled == objs[0]) break; + for (size_t i = 0; i < s->serv.bound_port_count; i++) { if (signaled == WAITABLE_OBJECT(s->serv.bound_ports[i]->connection_event)) @@ -1387,8 +1395,8 @@ obos_status tcp_connect(socket_desc* socket, struct sockaddr* saddr, size_t addr while (s->connection->state.state != TCP_STATE_ESTABLISHED) { - Core_WaitOnObject(WAITABLE_OBJECT(s->connection->state.state_change_event)); - if (s->connection->reset) + status = Core_WaitOnObject(WAITABLE_OBJECT(s->connection->state.state_change_event)); + if (s->connection->reset || obos_is_error(status)) { Core_PushlockAcquire(&iface->tcp_connections_lock, false); RB_REMOVE(tcp_connection_tree, &iface->tcp_outgoing_connections, s->connection); @@ -1684,15 +1692,15 @@ socket_ops Net_TCPSocketBackend = { .proto_type.protocol = IPPROTO_TCP, .domain = AF_INET, .create = tcp_create, - .free = tcp_free, - .accept = tcp_accept, - .bind = tcp_bind, - .connect = tcp_connect, - .getpeername = tcp_getpeername, - .getsockname = tcp_getsockname, - .listen = tcp_listen, - .submit_irp = tcp_submit_irp, - .finalize_irp = tcp_finalize_irp, - .shutdown = tcp_shutdown, - .sockatmark = tcp_sockatmark + .free = tcp_free, + .accept = tcp_accept, + .bind = tcp_bind, + .connect = tcp_connect, + .getpeername = tcp_getpeername, + .getsockname = tcp_getsockname, + .listen = tcp_listen, + .submit_irp = tcp_submit_irp, + .finalize_irp = tcp_finalize_irp, + .shutdown = tcp_shutdown, + .sockatmark = tcp_sockatmark }; \ No newline at end of file diff --git a/src/oboskrnl/net/udp.c b/src/oboskrnl/net/udp.c index a7db1e39..ba6c3c33 100644 --- a/src/oboskrnl/net/udp.c +++ b/src/oboskrnl/net/udp.c @@ -231,7 +231,12 @@ static void internal_read_thread(void* userdata) while (!ports->read_closed) { struct waitable_header* signaled = nullptr; - Core_WaitOnObjects(1+ports->nPorts, events, &signaled); + obos_status status = Core_WaitOnObjects(1+ports->nPorts, events, &signaled); + if (obos_is_error(status)) + { + NetError("Net: %s: Core_WaitOnObjects returned %d, aborting.\n", __func__, status); + break; + } if (signaled == WAITABLE_OBJECT(ports->wake_read_thread)) break; for (size_t i = 0; i < ports->nPorts; i++) diff --git a/src/oboskrnl/signal.c b/src/oboskrnl/signal.c index 1631d02f..0cac45ff 100644 --- a/src/oboskrnl/signal.c +++ b/src/oboskrnl/signal.c @@ -120,7 +120,8 @@ obos_status OBOS_SigSuspend(sigset_t mask) Core_MutexAcquire(&Core_GetCurrentThread()->signal_info->lock); sigset_t old = Core_GetCurrentThread()->signal_info->mask; Core_GetCurrentThread()->signal_info->mask = mask; - Core_WaitOnObject(WAITABLE_OBJECT(Core_GetCurrentThread()->signal_info->event)); + obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(Core_GetCurrentThread()->signal_info->event)); + if (obos_is_error(status)) return status; Core_GetCurrentThread()->signal_info->mask = old; Core_MutexRelease(&Core_GetCurrentThread()->signal_info->lock); return OBOS_STATUS_SUCCESS; diff --git a/src/oboskrnl/vfs/fd_sys.c b/src/oboskrnl/vfs/fd_sys.c index 66f6e654..cbdbb8fa 100644 --- a/src/oboskrnl/vfs/fd_sys.c +++ b/src/oboskrnl/vfs/fd_sys.c @@ -1479,7 +1479,13 @@ obos_status Sys_PSelect(size_t nFds, uint8_t* uread_set, uint8_t *uwrite_set, ui waitable_list[unsignaledIRPIndex] = WAITABLE_OBJECT(tm_evnt); } - Core_WaitOnObjects(nWaitableObjects, waitable_list, nullptr); + status = Core_WaitOnObjects(nWaitableObjects, waitable_list, nullptr); + if (obos_is_error(status)) + { + Core_CancelTimer(&tm); + CoreH_FreeDPC(&tm.handler_dpc, false); + goto timeout; + } if (tm.mode == TIMER_EXPIRED) { // Just In Case @@ -1665,7 +1671,13 @@ obos_status Sys_PPoll(struct pollfd* ufds, size_t nFds, const uintptr_t* utimeou } struct waitable_header* signaled = nullptr; - Core_WaitOnObjects(n_waitable_objects, waitable_list, &signaled); + status = Core_WaitOnObjects(n_waitable_objects, waitable_list, &signaled); + if (obos_is_error(status)) + { + Core_CancelTimer(&tm); + CoreH_FreeDPC(&tm.handler_dpc, false); + goto out; + } if (signaled == WAITABLE_OBJECT(tm_evnt)) { Core_CancelTimer(&tm); diff --git a/src/oboskrnl/vfs/local_socket.c b/src/oboskrnl/vfs/local_socket.c index 872769f8..2091c18e 100644 --- a/src/oboskrnl/vfs/local_socket.c +++ b/src/oboskrnl/vfs/local_socket.c @@ -371,7 +371,9 @@ static obos_status stream_accept(socket_desc* socket, struct sockaddr* addr, siz if (!Core_EventGetState(&s->serv.doorbell) && nonblocking) return OBOS_STATUS_WOULD_BLOCK; - Core_WaitOnObject(WAITABLE_OBJECT(s->serv.doorbell)); + obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(s->serv.doorbell)); + if (obos_is_error(status)) + return status; Core_EventClear(&s->serv.doorbell); Core_MutexAcquire(&s->serv.lock); diff --git a/src/oboskrnl/vfs/pipe.c b/src/oboskrnl/vfs/pipe.c index de6ded4e..571a6b3d 100644 --- a/src/oboskrnl/vfs/pipe.c +++ b/src/oboskrnl/vfs/pipe.c @@ -171,7 +171,9 @@ static obos_status write_sync(dev_desc desc, const void* buf, size_t blkCount, s pipe_ready_count(pipe, &ready_count); if ((pipe->size - ready_count) >= blkCount) break; - Core_WaitOnObject(WAITABLE_OBJECT(pipe->write_evnt)); + obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(pipe->write_evnt)); + if (obos_is_error(status)) + return status; } pipe_write(pipe, buf, blkCount, nBlkWritten); diff --git a/src/uHDA/hdadev.c b/src/uHDA/hdadev.c index 060a6aa1..c0ce2efa 100644 --- a/src/uHDA/hdadev.c +++ b/src/uHDA/hdadev.c @@ -264,7 +264,8 @@ void fd_fill_worker(void* user) struct fd_fill_userdata *udata = user; while (!udata->request_thread_kill) { - Core_WaitOnObject(WAITABLE_OBJECT(udata->wake_thr)); + if (obos_is_error(Core_WaitOnObject(WAITABLE_OBJECT(udata->wake_thr)))) + break; Core_EventClear(&udata->wake_thr); if (udata->request_thread_kill) break; From 2ef3cfee57caf0ea934f7cd0541e692751f6d091 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Mon, 24 Nov 2025 17:44:31 -0500 Subject: [PATCH 26/96] init: Fix a bug in NM --- src/init/main.c | 2 +- src/init/nm.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/init/main.c b/src/init/main.c index 364330df..78954dda 100644 --- a/src/init/main.c +++ b/src/init/main.c @@ -177,7 +177,7 @@ int main(int argc, char** argv) } int status; top: - waitpid(pid, &status, pid); + waitpid(pid, &status, 0); if (WIFSIGNALED(status)) printf("Handoff process exited due to signal %d\n", WTERMSIG(status)); if (!WIFEXITED(status) && !WIFSIGNALED(status)) diff --git a/src/init/nm.c b/src/init/nm.c index 3b6ea998..d9442c6e 100644 --- a/src/init/nm.c +++ b/src/init/nm.c @@ -146,6 +146,8 @@ bool nm_initialize_interface(cJSON* top_level) pid_t pid = 0; if ((pid = fork()) == 0) { + setpgrp(); + tcsetpgrp(0, getpgrp()); char *argv[3] = { "obos_dhcpc", (char*)interface_name, From d2a8dee8aaf033af5b0d7b64dd0a75d6bfe91b84 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Mon, 24 Nov 2025 17:44:52 -0500 Subject: [PATCH 27/96] core: Add CoreS_ForceYieldOnSyscallReturn --- src/oboskrnl/arch/x86_64/gdbstub/connection.c | 5 +++- src/oboskrnl/arch/x86_64/smp.c | 14 ++++++++++ src/oboskrnl/locks/sys_futex.c | 2 ++ src/oboskrnl/scheduler/thread.h | 7 +++++ src/oboskrnl/syscall.c | 2 ++ src/oboskrnl/vfs/fd_sys.c | 26 ++++++++++++++++++- 6 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/oboskrnl/arch/x86_64/gdbstub/connection.c b/src/oboskrnl/arch/x86_64/gdbstub/connection.c index d2543deb..cedc56f9 100644 --- a/src/oboskrnl/arch/x86_64/gdbstub/connection.c +++ b/src/oboskrnl/arch/x86_64/gdbstub/connection.c @@ -432,5 +432,8 @@ obos_status SysS_GDBStubStart() CoreH_ThreadInitialize(&gdb_thread, THREAD_PRIORITY_NORMAL, Core_DefaultThreadAffinity, &ctx); Core_ProcessAppendThread(OBOS_KernelProcess, &gdb_thread); CoreH_ThreadReady(&gdb_thread); - return Core_WaitOnObject(WAITABLE_OBJECT(gdb_connected)); + obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(gdb_connected)); + if (CoreS_ForceYieldOnSyscallReturn) + CoreS_ForceYieldOnSyscallReturn(); + return status; } \ No newline at end of file diff --git a/src/oboskrnl/arch/x86_64/smp.c b/src/oboskrnl/arch/x86_64/smp.c index 0fb2868a..588d4122 100644 --- a/src/oboskrnl/arch/x86_64/smp.c +++ b/src/oboskrnl/arch/x86_64/smp.c @@ -353,3 +353,17 @@ void CoreS_SetKernelStack(void* stck) if (!stck) return; CoreS_GetCPULocalPtr()->arch_specific.tss.rsp0 = (uintptr_t)stck+0x10000; } + +void CoreS_ForceYieldOnSyscallReturn() +{ + ipi_vector_info vector = { + .deliveryMode = LAPIC_DELIVERY_MODE_FIXED, + .info.vector = Core_SchedulerIRQ->vector->id + 0x20 + }; + asm volatile ("cli"); + static ipi_lapic_info self = { + .isShorthand=true, + .info.shorthand=LAPIC_DESTINATION_SHORTHAND_SELF + }; + Arch_LAPICSendIPI(self, vector); +} \ No newline at end of file diff --git a/src/oboskrnl/locks/sys_futex.c b/src/oboskrnl/locks/sys_futex.c index 9661f9cc..e86d6acb 100644 --- a/src/oboskrnl/locks/sys_futex.c +++ b/src/oboskrnl/locks/sys_futex.c @@ -92,6 +92,8 @@ obos_status Sys_FutexWait(uint32_t *futex, uint32_t cmp_with, uint64_t timeout) // Mm_VirtualMemoryUnlock(CoreS_GetCPULocalPtr()->currentThread->proc->ctx, futex, sizeof(*futex)); obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(*obj)); deref_futex(obj); + if (CoreS_ForceYieldOnSyscallReturn) + CoreS_ForceYieldOnSyscallReturn(); return status; } diff --git a/src/oboskrnl/scheduler/thread.h b/src/oboskrnl/scheduler/thread.h index b115df02..0e2d7081 100644 --- a/src/oboskrnl/scheduler/thread.h +++ b/src/oboskrnl/scheduler/thread.h @@ -219,3 +219,10 @@ OBOS_EXPORT thread_affinity CoreH_CPUIdToAffinity(uint32_t cpuId); /// Exits the current thread. /// OBOS_NORETURN OBOS_EXPORT void Core_ExitCurrentThread(); + +/// +/// Forces a yield on syscall return. Should only be called before the syscall returns.
+/// This function exists so that blocking syscalls can give any signals a chance to run
+/// if it was interrupted by a signal. +///
+OBOS_WEAK void CoreS_ForceYieldOnSyscallReturn(); \ No newline at end of file diff --git a/src/oboskrnl/syscall.c b/src/oboskrnl/syscall.c index 09012e18..aeb2186a 100644 --- a/src/oboskrnl/syscall.c +++ b/src/oboskrnl/syscall.c @@ -165,6 +165,8 @@ obos_status Sys_SleepMS(uint64_t ms, uint64_t* uleft) timer_tick deadline = CoreS_GetTimerTick() + CoreH_TimeFrameToTick(ms*1000); while (deadline > CoreS_GetTimerTick()) OBOSS_SpinlockHint(); + if (CoreS_ForceYieldOnSyscallReturn) + CoreS_ForceYieldOnSyscallReturn(); return OBOS_STATUS_SUCCESS; } diff --git a/src/oboskrnl/vfs/fd_sys.c b/src/oboskrnl/vfs/fd_sys.c index cbdbb8fa..c198d6ac 100644 --- a/src/oboskrnl/vfs/fd_sys.c +++ b/src/oboskrnl/vfs/fd_sys.c @@ -287,6 +287,9 @@ obos_status Sys_FdWrite(handle desc, const void* buf, size_t nBytes, size_t* nWr Mm_VirtualMemoryFree(&Mm_KernelContext, kbuf, nBytes); + if (CoreS_ForceYieldOnSyscallReturn) + CoreS_ForceYieldOnSyscallReturn(); + return OBOS_STATUS_SUCCESS; } @@ -323,6 +326,9 @@ obos_status Sys_FdRead(handle desc, void* buf, size_t nBytes, size_t* nRead) Mm_VirtualMemoryFree(&Mm_KernelContext, kbuf, nBytes); + if (CoreS_ForceYieldOnSyscallReturn) + CoreS_ForceYieldOnSyscallReturn(); + return OBOS_STATUS_SUCCESS; } @@ -366,6 +372,9 @@ obos_status Sys_FdPWrite(handle desc, const void* buf, size_t nBytes, size_t* nW Mm_VirtualMemoryFree(&Mm_KernelContext, kbuf, nBytes); + if (CoreS_ForceYieldOnSyscallReturn) + CoreS_ForceYieldOnSyscallReturn(); + return OBOS_STATUS_SUCCESS; } @@ -399,7 +408,10 @@ obos_status Sys_FdPRead(handle desc, void* buf, size_t nBytes, size_t* nRead, si } Mm_VirtualMemoryFree(&Mm_KernelContext, kbuf, nBytes); - + + if (CoreS_ForceYieldOnSyscallReturn) + CoreS_ForceYieldOnSyscallReturn(); + return OBOS_STATUS_SUCCESS; } @@ -2478,6 +2490,9 @@ obos_status Sys_SendTo(handle desc, const void* buffer, size_t size, int flags, OBOS_MAYBE_UNUSED fail1: Mm_VirtualMemoryFree(&Mm_KernelContext, (void*)params, sizeof(*params)); + if (CoreS_ForceYieldOnSyscallReturn) + CoreS_ForceYieldOnSyscallReturn(); + return status; } @@ -2530,6 +2545,9 @@ obos_status Sys_RecvFrom(handle desc, void* buffer, size_t size, int flags, stru OBOS_MAYBE_UNUSED fail1: Mm_VirtualMemoryFree(&Mm_KernelContext, params, sizeof(*params)); + if (CoreS_ForceYieldOnSyscallReturn) + CoreS_ForceYieldOnSyscallReturn(); + return status; } @@ -2586,6 +2604,9 @@ obos_status Sys_Accept(handle desc, handle empty_fd, sockaddr* uaddr_ptr, size_t OBOS_MAYBE_UNUSED fail1: Free(OBOS_KernelAllocator, buf, addr_length); + if (CoreS_ForceYieldOnSyscallReturn) + CoreS_ForceYieldOnSyscallReturn(); + return status; } @@ -2638,6 +2659,9 @@ obos_status Sys_Connect(handle desc, const sockaddr *uaddr, size_t addr_length) OBOS_MAYBE_UNUSED fail1: Free(OBOS_KernelAllocator, buf, addr_length); + if (CoreS_ForceYieldOnSyscallReturn) + CoreS_ForceYieldOnSyscallReturn(); + return status; } From 42e99e768509320f1b0d91d4e4f1cb84ada8413b Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Mon, 24 Nov 2025 20:43:23 -0500 Subject: [PATCH 28/96] misc: Changes --- src/oboskrnl/signal.c | 5 +++++ src/oboskrnl/vfs/fd_sys.c | 9 ++++++++- src/oboskrnl/vfs/tty.c | 7 +++---- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/oboskrnl/signal.c b/src/oboskrnl/signal.c index 0cac45ff..8b572572 100644 --- a/src/oboskrnl/signal.c +++ b/src/oboskrnl/signal.c @@ -79,6 +79,11 @@ obos_status OBOS_Kill(struct thread* as, struct thread* thr, int sigval) Core_MutexRelease(&thr->signal_info->lock); return OBOS_STATUS_SUCCESS; } + if (thr->signal_info->signals[sigval-1].un.handler == SIG_IGN) + { + Core_MutexRelease(&thr->signal_info->lock); + return OBOS_STATUS_SUCCESS; + } thr->signal_info->pending |= BIT(sigval - 1); // set these up before the call to kill. // thr->signal_info->signals[sigval].addr = nullptr; diff --git a/src/oboskrnl/vfs/fd_sys.c b/src/oboskrnl/vfs/fd_sys.c index c198d6ac..5fe7c9a0 100644 --- a/src/oboskrnl/vfs/fd_sys.c +++ b/src/oboskrnl/vfs/fd_sys.c @@ -15,6 +15,7 @@ #include +#include #include #include #include @@ -1400,7 +1401,6 @@ obos_status Sys_PSelect(size_t nFds, uint8_t* uread_set, uint8_t *uwrite_set, ui return status; } - sigset_t sigmask = 0, oldmask = 0; if (extra.sigmask) { @@ -1527,6 +1527,10 @@ obos_status Sys_PSelect(size_t nFds, uint8_t* uread_set, uint8_t *uwrite_set, ui out2: Mm_VirtualMemoryFree(CoreS_GetCPULocalPtr()->currentContext, read_set, 128); Mm_VirtualMemoryFree(CoreS_GetCPULocalPtr()->currentContext, write_set, 128); + + if (CoreS_ForceYieldOnSyscallReturn) + CoreS_ForceYieldOnSyscallReturn(); + return status; } @@ -1713,6 +1717,9 @@ obos_status Sys_PPoll(struct pollfd* ufds, size_t nFds, const uintptr_t* utimeou OBOS_SigProcMask(SIG_SETMASK, &oldmask, nullptr); Mm_VirtualMemoryFree(&Mm_KernelContext, fds, nFds*sizeof(struct pollfd)); + if (CoreS_ForceYieldOnSyscallReturn) + CoreS_ForceYieldOnSyscallReturn(); + return status; } diff --git a/src/oboskrnl/vfs/tty.c b/src/oboskrnl/vfs/tty.c index b269ca0f..84e3da61 100644 --- a/src/oboskrnl/vfs/tty.c +++ b/src/oboskrnl/vfs/tty.c @@ -454,8 +454,7 @@ void erase_bytes(tty* tty, size_t nBytesToErase) static void tty_kill(tty* tty, int sigval) { - if (tty->termios.lflag & ISIG) - OBOS_KillProcessGroup(tty->fg_job, sigval); + OBOS_KillProcessGroup(tty->fg_job, sigval); } static void data_ready(void *tty_, const void *buf, size_t nBytesReady) @@ -518,10 +517,10 @@ static void data_ready(void *tty_, const void *buf, size_t nBytesReady) } else tty->quoted = false; - if (!insert_byte) - continue; if (tty->termios.lflag & ECHO) tty_write_sync((dev_desc)tty, &ch, 1, 0, nullptr); + if (!insert_byte) + continue; if (tty->termios.lflag & ICANON) { if (tty->termios.lflag & ECHONL && ch == '\n') From b48554d82a5fe7ccb84304d894046268b376f302 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 25 Nov 2025 20:45:04 -0500 Subject: [PATCH 29/96] initrd: Fix bug with LNKTYPE files in the archive --- src/drivers/generic/initrd/main.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/drivers/generic/initrd/main.c b/src/drivers/generic/initrd/main.c index 0932982c..874c837f 100644 --- a/src/drivers/generic/initrd/main.c +++ b/src/drivers/generic/initrd/main.c @@ -201,8 +201,6 @@ initrd_inode* create_inode_boot(const ustar_hdr* hdr) ino->name = Allocate(OBOS_KernelAllocator, ino->name_len+1, nullptr); memcpy(ino->name, ino->path+index, ino->name_len); ino->name[ino->name_len] = 0; - ino->filesize = oct2bin(hdr->filesize, strnlen(hdr->filesize, 12)); - ino->data = (char*)hdr + 512; // ino->data = Allocate(OBOS_NonPagedPoolAllocator, ino->filesize, nullptr); // if (!ino->data) // { @@ -213,6 +211,7 @@ initrd_inode* create_inode_boot(const ustar_hdr* hdr) // return nullptr; // } // memcpy(ino->data, (char*)hdr + 512, ino->filesize); + back: switch (hdr->type) { case AREGTYPE: case REGTYPE: @@ -221,13 +220,24 @@ initrd_inode* create_inode_boot(const ustar_hdr* hdr) case DIRTYPE: ino->type = FILE_TYPE_DIRECTORY; break; - case LNKTYPE: case SYMTYPE: ino->type = FILE_TYPE_SYMBOLIC_LINK; break; + case LNKTYPE: + { + obos_status status = OBOS_STATUS_SUCCESS; + hdr = GetFile(hdr->linked, &status); + if (obos_is_error(status)) + return nullptr; + goto back; + break; + } default: OBOS_ENSURE(!"Unrecognized header type"); } + ino->filesize = oct2bin(hdr->filesize, strnlen(hdr->filesize, 12)); + ino->data = (char*)hdr + 512; + uint16_t filemode = oct2bin(hdr->filemode, strnlen(hdr->filemode, 8)); ino->perm.group_read = filemode & FILEMODE_GROUP_READ; ino->perm.owner_read = filemode & FILEMODE_OWNER_READ; @@ -242,7 +252,6 @@ initrd_inode* create_inode_boot(const ustar_hdr* hdr) ino->perm.set_gid = filemode & 02000; ino->linked_path = hdr->linked; - ino->vnode = Vfs_Calloc(1, sizeof(vnode)); ino->vnode->desc = (uintptr_t)ino; ino->vnode->filesize = ino->filesize; @@ -270,6 +279,7 @@ initrd_inode* create_inode_boot(const ustar_hdr* hdr) } ino->hdr = hdr; + return ino; } driver_init_status OBOS_DriverEntry(driver_id* this) From 5e9dcbeab14ce6ac313d49d47dc5680510089129 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 25 Nov 2025 20:45:29 -0500 Subject: [PATCH 30/96] misc: fix bug in limine.cmake dependency file --- dependencies/limine.cmake | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/dependencies/limine.cmake b/dependencies/limine.cmake index 1d0d4cee..7efdd0a6 100644 --- a/dependencies/limine.cmake +++ b/dependencies/limine.cmake @@ -4,12 +4,15 @@ include(FetchContent) -FetchContent_Declare(Limine - GIT_REPOSITORY https://github.com/limine-bootloader/limine.git - GIT_TAG v10.3.0-binary - SOURCE_DIR ${CMAKE_SOURCE_DIR}/dependencies/limine -) -FetchContent_MakeAvailable(Limine) +if (OBOS_REFRESH_DEPENDENCIES) + FetchContent_Declare(Limine + GIT_REPOSITORY https://github.com/limine-bootloader/limine.git + GIT_TAG v10.3.0-binary + SOURCE_DIR ${CMAKE_SOURCE_DIR}/dependencies/limine + ) + FetchContent_MakeAvailable(Limine) + file (COPY_FILE "${CMAKE_SOURCE_DIR}/dependencies/limine/limine.h" "${CMAKE_SOURCE_DIR}/dependencies/include/limine.h") +endif() if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") execute_process( COMMAND "make" @@ -21,4 +24,3 @@ if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") else() message(FATAL_ERROR "You must be on to compile OBOS with Limine.") endif() -file (COPY_FILE "${CMAKE_SOURCE_DIR}/dependencies/limine/limine.h" "${CMAKE_SOURCE_DIR}/dependencies/include/limine.h") \ No newline at end of file From 3cee7062851442b4cc70bee20d249103d44511a5 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 25 Nov 2025 20:47:53 -0500 Subject: [PATCH 31/96] misc: Make signal handlers global in a process --- src/oboskrnl/arch/x86_64/except.c | 2 +- src/oboskrnl/arch/x86_64/ssignal.c | 2 +- src/oboskrnl/scheduler/process.h | 3 + src/oboskrnl/scheduler/sched_sys.c | 1 - src/oboskrnl/signal.c | 27 ++++----- src/oboskrnl/signal.h | 83 +-------------------------- src/oboskrnl/signal_def.h | 90 ++++++++++++++++++++++++++++++ 7 files changed, 110 insertions(+), 98 deletions(-) create mode 100644 src/oboskrnl/signal_def.h diff --git a/src/oboskrnl/arch/x86_64/except.c b/src/oboskrnl/arch/x86_64/except.c index 87192ef5..d57f0b4a 100644 --- a/src/oboskrnl/arch/x86_64/except.c +++ b/src/oboskrnl/arch/x86_64/except.c @@ -94,7 +94,7 @@ __attribute__((no_instrument_function)) OBOS_NO_UBSAN OBOS_NO_KASAN void Arch_Pa if (frame->cs & 3) { OBOS_Log("User thread %d SIGSEGV (rip 0x%p, cr2 0x%p, error code 0x%08x)\n", Core_GetCurrentThread()->tid, frame->rip, getCR2(), frame->errorCode); - Core_GetCurrentThread()->signal_info->signals[SIGSEGV].addr = (void*)getCR2(); + Core_GetCurrentThread()->proc->signal_handlers[SIGSEGV].addr = (void*)getCR2(); OBOS_Kill(Core_GetCurrentThread(), Core_GetCurrentThread(), SIGSEGV); // OBOS_SyncPendingSignal(frame); OBOS_RunSignal(SIGSEGV, frame); // Ensure SIGSEGV runs. diff --git a/src/oboskrnl/arch/x86_64/ssignal.c b/src/oboskrnl/arch/x86_64/ssignal.c index d759453c..6fbcd6e9 100644 --- a/src/oboskrnl/arch/x86_64/ssignal.c +++ b/src/oboskrnl/arch/x86_64/ssignal.c @@ -60,7 +60,7 @@ void OBOSS_RunSignalImpl(int sigval, interrupt_frame* frame) { // if (!(frame->cs & 0x3)) // return; - sigaction* sig = &Core_GetCurrentThread()->signal_info->signals[sigval-1]; + sigaction* sig = &Core_GetCurrentThread()->proc->signal_handlers[sigval-1]; if (sig->un.handler == SIG_IGN) return; ucontext_t ctx = { .frame=*frame,.gs_base=rdmsr(!(frame->cs & 0x3) ? GS_BASE : KERNEL_GS_BASE),.fs_base=rdmsr(FS_BASE),.cr3=frame->cr3 }; diff --git a/src/oboskrnl/scheduler/process.h b/src/oboskrnl/scheduler/process.h index b97d0af2..324a1b9c 100644 --- a/src/oboskrnl/scheduler/process.h +++ b/src/oboskrnl/scheduler/process.h @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -59,6 +60,8 @@ typedef struct process // Only exists for POSIX, ignored in most parts of the kernel. uint32_t umask; + sigaction signal_handlers[64]; + LIST_NODE(process_list, struct process) node; } process; typedef LIST_HEAD(process_list, process) process_list; diff --git a/src/oboskrnl/scheduler/sched_sys.c b/src/oboskrnl/scheduler/sched_sys.c index 8c56f1a2..a527ec93 100644 --- a/src/oboskrnl/scheduler/sched_sys.c +++ b/src/oboskrnl/scheduler/sched_sys.c @@ -184,7 +184,6 @@ handle Sys_ThreadCreate(thread_priority priority, thread_affinity affinity, hand thr->references++; OBOS_UnlockHandleTable(OBOS_CurrentHandleTable()); - memcpy(thr->signal_info->signals, Core_GetCurrentThread()->signal_info->signals, sizeof(thr->signal_info->signals)); thr->signal_info->mask = Core_GetCurrentThread()->signal_info->mask; return hnd; diff --git a/src/oboskrnl/signal.c b/src/oboskrnl/signal.c index 8b572572..a6760777 100644 --- a/src/oboskrnl/signal.c +++ b/src/oboskrnl/signal.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -74,27 +75,27 @@ obos_status OBOS_Kill(struct thread* as, struct thread* thr, int sigval) else if (sigval == SIGSTOP) { // Stop the thread. - thr->signal_info->signals[sigval].sender = as; + thr->proc->signal_handlers[sigval].sender = as; CoreH_ThreadBlock(thr, true); Core_MutexRelease(&thr->signal_info->lock); return OBOS_STATUS_SUCCESS; } - if (thr->signal_info->signals[sigval-1].un.handler == SIG_IGN) + if (thr->proc->signal_handlers[sigval-1].un.handler == SIG_IGN) { Core_MutexRelease(&thr->signal_info->lock); return OBOS_STATUS_SUCCESS; } thr->signal_info->pending |= BIT(sigval - 1); // set these up before the call to kill. - // thr->signal_info->signals[sigval].addr = nullptr; - // thr->signal_info->signals[sigval].status = 0; - // thr->signal_info->signals[sigval].udata = 0; - // thr->signal_info->signals[sigval].sigcode = 0; - thr->signal_info->signals[sigval].sender = as; + // thr->proc->signal_handlers[sigval].addr = nullptr; + // thr->proc->signal_handlers[sigval].status = 0; + // thr->proc->signal_handlers[sigval].udata = 0; + // thr->proc->signal_handlers[sigval].sigcode = 0; + thr->proc->signal_handlers[sigval].sender = as; Core_MutexRelease(&thr->signal_info->lock); if (thr->status == THREAD_STATUS_BLOCKED) { - if (sigval == SIGTSTP && thr->signal_info->mask & BIT(SIGTSTP - 1)) + if (thr->signal_info->mask & BIT(SIGTSTP - 1)) return OBOS_STATUS_SUCCESS; // TODO: Use CoreH_AbortWaitingThreads instead of this? thr->interrupted = true; @@ -109,13 +110,13 @@ obos_status OBOS_SigAction(int signum, const sigaction* act, sigaction* oldact) if (!(signum >= 0 && signum < SIGMAX)) return OBOS_STATUS_INVALID_ARGUMENT; if (oldact) - *oldact = Core_GetCurrentThread()->signal_info->signals[signum]; + *oldact = Core_GetCurrentThread()->proc->signal_handlers[signum]; if (act) { Core_MutexAcquire(&Core_GetCurrentThread()->signal_info->lock); - Core_GetCurrentThread()->signal_info->signals[signum - 1] = *act; + Core_GetCurrentThread()->proc->signal_handlers[signum - 1] = *act; // what. - // Core_GetCurrentThread()->signal_info->signals[signum].un.handler = SIG_DFL /* default handler is the kernel */; + // Core_GetCurrentThread()->proc->signal_handlers[signum].un.handler = SIG_DFL /* default handler is the kernel */; Core_MutexRelease(&Core_GetCurrentThread()->signal_info->lock); } return OBOS_STATUS_SUCCESS; @@ -276,7 +277,7 @@ obos_status OBOS_KillProcessGroup(process_group* pgrp, int sigval) void OBOS_RunSignal(int sigval, interrupt_frame* frame) { - sigaction* sig = &Core_GetCurrentThread()->signal_info->signals[sigval]; + sigaction* sig = &Core_GetCurrentThread()->proc->signal_handlers[sigval]; if (!(sig->flags & SA_NODEFER)) Core_GetCurrentThread()->signal_info->mask |= BIT_TYPE(sigval-1, L); Core_EventSet(&Core_GetCurrentThread()->signal_info->event, false); @@ -301,7 +302,7 @@ OBOS_NO_UBSAN bool OBOS_SyncPendingSignal(interrupt_frame* frame) sigval += 1; Core_MutexRelease(&Core_GetCurrentThread()->signal_info->lock); OBOS_RunSignal(sigval, frame); - return Core_GetCurrentThread()->signal_info->signals[sigval-1].un.handler != SIG_IGN; + return Core_GetCurrentThread()->proc->signal_handlers[sigval-1].un.handler != SIG_IGN; } #define T SIGNAL_DEFAULT_TERMINATE_PROC, diff --git a/src/oboskrnl/signal.h b/src/oboskrnl/signal.h index de6c02bf..49cecafc 100644 --- a/src/oboskrnl/signal.h +++ b/src/oboskrnl/signal.h @@ -26,78 +26,8 @@ #define SIG_DFL (nullptr) #define SIG_IGN ((void*)1) -// Public -enum { - SIGHUP = 1 , SIGINT, SIGQUIT, SIGILL, SIGTRAP, - SIGABRT , SIGBUS, SIGFPE, SIGKILL, SIGUSR1, - SIGSEGV , SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, - SIGSTKFLT , SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, - SIGTTIN , SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, - SIGVTALRM , SIGSYS, SIGMAX = 64, -}; - -// Public -typedef uint64_t sigset_t; +#include -// Public -enum { - SA_SIGINFO = BIT(0), - SA_ONSTACK = BIT(1), - SA_RESETHAND = BIT(2), - SA_NODEFER = BIT(3), - SA_NOCLDWAIT = BIT(4), // unimplemented - SA_NOCLDSTOP = BIT(5), // unimplemented -}; -// Public -typedef struct siginfo_t -{ - int signum; - int sigcode; - struct thread* sender; - void* addr; - int status; - union { - void* ptr; - uintptr_t integer; - } udata; -} siginfo_t; -// Public -typedef struct user_sigaction { - union { - void(*handler)(int signum); - void(*sa_sigaction)(int signum, siginfo_t* info, void* unknown); - } un; - // NOTE(oberrow): Set to __mlibc_restorer in the mlibc sysdeps. - uintptr_t trampoline_base; // required - uint32_t flags; -} user_sigaction; -typedef struct sigaction { - union { - void(*handler)(int signum); - void(*sa_sigaction)(int signum, siginfo_t* info, void* unknown); - } un; - // NOTE(oberrow): Set to __mlibc_restorer in the mlibc sysdeps. - uintptr_t trampoline_base; // required - uint32_t flags; - // The following fields are not to be carried to userspace. - // Fields of 'siginfo_t' are set with this - uintptr_t udata; - void* addr; - int status; - int sigcode; - struct thread* sender; -} sigaction; -// Internal -typedef struct signal_header { - // NOTE: To get the first signal to dispatch, use __builtin_ctzll(pending & ~masked) - sigaction signals[64]; - sigset_t pending; - sigset_t mask; - uintptr_t sp; - size_t stack_size; // Unused in the actual signal implemtation, only exists for Sys_SigAltStack. - mutex lock; // take when modifying this structure. - event event; // set when a signal runs, clear when it exits (sigreturn) -} signal_header; signal_header* OBOSH_AllocateSignalHeader(); obos_status OBOS_Kill(struct thread* as, struct thread* thr, int sigval); @@ -126,17 +56,6 @@ OBOS_WEAK void OBOSS_SigReturn(ucontext_t* frame); OBOS_WEAK void OBOSS_RunSignalImpl(int sigval, interrupt_frame* frame); -enum signal_default_action -{ - // When this is the default, the signal runner returns normally. - SIGNAL_DEFAULT_IGNORE, - // When this is the default, the current thread is exited. - SIGNAL_DEFAULT_TERMINATE_PROC, - // Blocks the thread. - SIGNAL_DEFAULT_STOP, - // Readies the thread. - SIGNAL_DEFAULT_CONTINUE, -}; extern enum signal_default_action OBOS_SignalDefaultActions[SIGMAX+1]; void OBOS_DefaultSignalHandler(int signum, siginfo_t* info, void* unknown); diff --git a/src/oboskrnl/signal_def.h b/src/oboskrnl/signal_def.h new file mode 100644 index 00000000..997dd5e2 --- /dev/null +++ b/src/oboskrnl/signal_def.h @@ -0,0 +1,90 @@ +#pragma once + +#include + +#include +#include + +enum signal_default_action +{ + // When this is the default, the signal runner returns normally. + SIGNAL_DEFAULT_IGNORE, + // When this is the default, the current thread is exited. + SIGNAL_DEFAULT_TERMINATE_PROC, + // Blocks the thread. + SIGNAL_DEFAULT_STOP, + // Readies the thread. + SIGNAL_DEFAULT_CONTINUE, +}; + +// Public +enum { + SIGHUP = 1 , SIGINT, SIGQUIT, SIGILL, SIGTRAP, + SIGABRT , SIGBUS, SIGFPE, SIGKILL, SIGUSR1, + SIGSEGV , SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, + SIGSTKFLT , SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, + SIGTTIN , SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, + SIGVTALRM , SIGSYS, SIGMAX = 64, +}; + +// Public +typedef uint64_t sigset_t; + +// Public +enum { + SA_SIGINFO = BIT(0), + SA_ONSTACK = BIT(1), + SA_RESETHAND = BIT(2), + SA_NODEFER = BIT(3), + SA_NOCLDWAIT = BIT(4), // unimplemented + SA_NOCLDSTOP = BIT(5), // unimplemented +}; +// Public +typedef struct siginfo_t +{ + int signum; + int sigcode; + struct thread* sender; + void* addr; + int status; + union { + void* ptr; + uintptr_t integer; + } udata; +} siginfo_t; +// Public +typedef struct user_sigaction { + union { + void(*handler)(int signum); + void(*sa_sigaction)(int signum, siginfo_t* info, void* unknown); + } un; + // NOTE(oberrow): Set to __mlibc_restorer in the mlibc sysdeps. + uintptr_t trampoline_base; // required + uint32_t flags; +} user_sigaction; +typedef struct sigaction { + union { + void(*handler)(int signum); + void(*sa_sigaction)(int signum, siginfo_t* info, void* unknown); + } un; + // NOTE(oberrow): Set to __mlibc_restorer in the mlibc sysdeps. + uintptr_t trampoline_base; // required + uint32_t flags; + // The following fields are not to be carried to userspace. + // Fields of 'siginfo_t' are set with this + uintptr_t udata; + void* addr; + int status; + int sigcode; + struct thread* sender; +} sigaction; +// Internal +typedef struct signal_header { + // NOTE: To get the first signal to dispatch, use __builtin_ctzll(pending & ~masked) + sigset_t pending; + sigset_t mask; + uintptr_t sp; + size_t stack_size; // Unused in the actual signal implemtation, only exists for Sys_SigAltStack. + mutex lock; // take when modifying this structure. + event event; // set when a signal runs, clear when it exits (sigreturn) +} signal_header; \ No newline at end of file From 35839b720f91cdd76fd9468ffb9a14d3f8e01459 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 25 Nov 2025 21:06:19 -0500 Subject: [PATCH 32/96] misc: Make initial bump allocator size configurable at boot-time --- config/hyper.cfg | 4 ++++ config/limine.conf | 2 ++ src/oboskrnl/arch/x86_64/entry.c | 17 ++++++++++++++--- src/oboskrnl/arch/x86_64/map.c | 8 +++++++- src/oboskrnl/mm/bare_map.c | 26 ++++++++------------------ src/oboskrnl/mm/bare_map.h | 4 +++- 6 files changed, 38 insertions(+), 23 deletions(-) diff --git a/config/hyper.cfg b/config/hyper.cfg index 86eda3ec..5bbf11b7 100644 --- a/config/hyper.cfg +++ b/config/hyper.cfg @@ -28,3 +28,7 @@ module: type="memory" name="FLANTERM_BUFF" size=16777216 +module: + type="memory" + name="BUMP_REGION" + size=16777216 diff --git a/config/limine.conf b/config/limine.conf index c13ffcc3..5ebd6a2d 100644 --- a/config/limine.conf +++ b/config/limine.conf @@ -14,5 +14,7 @@ timeout: 5 module_string: initrd_driver module_path: boot():/obos/flanterm_buff module_string: FLANTERM_BUFF + module_path: boot():/obos/flanterm_buff + module_string: BUMP_REGION path: boot():/obos/oboskrnl cmdline: initrd-module=initrd initrd-driver-module=initrd_driver root-fs-partid initrd load-modules=/libps2,/extfs initial-swap-size=67108864 log-level=1 init-args /usr/bin/bash --login diff --git a/src/oboskrnl/arch/x86_64/entry.c b/src/oboskrnl/arch/x86_64/entry.c index f3b5b01c..65c53fbd 100644 --- a/src/oboskrnl/arch/x86_64/entry.c +++ b/src/oboskrnl/arch/x86_64/entry.c @@ -51,6 +51,8 @@ #include +#include + #include #if OBOS_USE_LIMINE @@ -275,6 +277,15 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry Arch_RSDPBase = Arch_UnmapFromHHDM(Arch_LimineRSDPRequest.response->address); #endif + basicmm_region bump_region = {}; + struct boot_module bump_region_module = {}; + OBOSS_GetModule(&bump_region_module, "BUMP_REGION"); + if (!bump_region_module.address) + OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "Could not find BUMP_REGION kernel module\n"); + bump_region.addr = (uintptr_t)bump_region_module.address; + bump_region.size = bump_region_module.size; + OBOSH_BasicMMSetBumpRegion(&bump_region); + struct boot_module flanterm_buff = {}; OBOSS_GetModule(&flanterm_buff, "FLANTERM_BUFF"); if (!flanterm_buff.address) @@ -315,8 +326,8 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry __builtin_bswap32(0xff55ff) >> 8, __builtin_bswap32(0x55ffff) >> 8, __builtin_bswap32(0xffffff) >> 8, - }; + OBOS_UNUSED(ansi_bright_colors && ansi_colors); #if !OBOS_USE_LIMINE if (!Arch_Framebuffer) OBOS_Warning("No framebuffer passed by the bootloader. All kernel logs will be on port 0xE9.\n"); @@ -379,8 +390,8 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry fb->red_mask_size, fb->red_mask_shift, fb->green_mask_size, fb->green_mask_shift, fb->blue_mask_size, fb->blue_mask_shift, - nullptr, ansi_colors, - ansi_bright_colors, nullptr, + nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, (void*)font_bin, 8, 16, 0, diff --git a/src/oboskrnl/arch/x86_64/map.c b/src/oboskrnl/arch/x86_64/map.c index bc795802..ad1deec0 100644 --- a/src/oboskrnl/arch/x86_64/map.c +++ b/src/oboskrnl/arch/x86_64/map.c @@ -526,7 +526,13 @@ static void map_range(uintptr_t cached_root, uintptr_t base, uintptr_t top, uint top &= ~0xfff; for (uintptr_t addr = base; addr < top; addr += 0x1000) { - uintptr_t phys = Arch_MaskPhysicalAddressFromEntry(Arch_GetPML1Entry(Arch_KernelCR3, addr)); + uintptr_t phys = 0; + uintptr_t pml2ent = Arch_GetPML2Entry(Arch_KernelCR3, addr); + if (pml2ent & BIT_TYPE(7, UL)) + phys = Arch_MaskPhysicalAddressFromEntry(pml2ent) + (addr & (OBOS_HUGE_PAGE_SIZE-1)); + else + phys = Arch_MaskPhysicalAddressFromEntry(Arch_GetPML1Entry(Arch_KernelCR3, addr)); + OBOS_ENSURE(phys != 0); Arch_MapPage(cached_root, (void*)addr, phys, flags, false); } } diff --git a/src/oboskrnl/mm/bare_map.c b/src/oboskrnl/mm/bare_map.c index e2357e6c..d6168308 100644 --- a/src/oboskrnl/mm/bare_map.c +++ b/src/oboskrnl/mm/bare_map.c @@ -49,28 +49,18 @@ static OBOS_PAGEABLE_FUNCTION void Unlock(irql oldIrql) Core_SpinlockRelease(&s_regionListLock, oldIrql); } +void OBOSH_BasicMMSetBumpRegion(basicmm_region* region) +{ + irql oldIrql = Lock(); + bump_region = *region; + Unlock(oldIrql); +} + OBOS_NO_KASAN OBOS_PAGEABLE_FUNCTION void* OBOS_BasicMMAllocatePages(size_t sz, obos_status* status) { irql oldIrql = Lock(); if (!bump_region.addr) - { - // OBOS_ALIGNAS(OBOS_PAGE_SIZE) static uint8_t region[256*1024*1024]; // 256M - OBOS_ALIGNAS(OBOS_PAGE_SIZE) static uint8_t region[4*1024*1024]; // 4M - bump_region.size = sizeof(region); - bump_region.addr = (uintptr_t)region; - // for (uintptr_t addr = bump_region.addr; addr < (bump_region.addr + bump_region.size); addr += OBOS_PAGE_SIZE) - // { - // obos_status stat = OBOS_STATUS_SUCCESS; - // uintptr_t mem = Mm_AllocatePhysicalPages(1, 1, &stat); - // if (stat != OBOS_STATUS_SUCCESS) - // { - // if (status) - // *status = stat; - // return nullptr; - // } - // OBOSS_MapPage_RW_XD((void*)addr, mem); - // } - } + OBOS_Panic(OBOS_PANIC_ALLOCATOR_ERROR, "BasicMM: No region specified by platform code.\n"); sz += (OBOS_PAGE_SIZE-(sz%OBOS_PAGE_SIZE)); if ((bump_offset + sz) >= bump_region.size) OBOS_Panic(OBOS_PANIC_NO_MEMORY, "BasicMM: No more space in bump allocator.\n"); diff --git a/src/oboskrnl/mm/bare_map.h b/src/oboskrnl/mm/bare_map.h index 7840af33..dfe2f51d 100644 --- a/src/oboskrnl/mm/bare_map.h +++ b/src/oboskrnl/mm/bare_map.h @@ -67,4 +67,6 @@ void OBOSH_BasicMMAddRegion(basicmm_region* nodeBase, void* base, size_t sz); /// /// The call back. Returns true to continue iteration, otherwise false. Takes in the current region, and the passed user data. /// The user data to pass. -void OBOSH_BasicMMIterateRegions(bool(*callback)(basicmm_region*, void*), void* udata); \ No newline at end of file +void OBOSH_BasicMMIterateRegions(bool(*callback)(basicmm_region*, void*), void* udata); + +void OBOSH_BasicMMSetBumpRegion(basicmm_region* region); \ No newline at end of file From 21e1576121917d8c9ae0444816e2462ac32e4077 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 25 Nov 2025 21:36:34 -0500 Subject: [PATCH 33/96] mm: Add MmS_TLBShootdown --- src/drivers/generic/ahci/main.c | 1 + src/drivers/generic/freebsd-e1000/main.c | 1 + src/drivers/generic/r8169/device.c | 1 + src/oboskrnl/arch/x86_64/map.c | 27 ++++++++++++------------ src/oboskrnl/driver_interface/pci_irq.c | 1 + src/oboskrnl/mm/alloc.c | 2 ++ src/oboskrnl/mm/context.h | 2 ++ src/oboskrnl/mm/fork.c | 1 + src/oboskrnl/mm/handler.c | 4 ++++ src/oboskrnl/mm/swap.c | 1 + src/uHDA/kernel_api.c | 1 + 11 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/drivers/generic/ahci/main.c b/src/drivers/generic/ahci/main.c index 61f635b2..aac1732d 100644 --- a/src/drivers/generic/ahci/main.c +++ b/src/drivers/generic/ahci/main.c @@ -158,6 +158,7 @@ static void* map_registers(uintptr_t phys, size_t size, bool uc) page.phys = phys+offset; MmS_SetPageMapping(Mm_KernelContext.pt, &page, phys + offset, false); } + MmS_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size); return virt+phys_page_offset; } diff --git a/src/drivers/generic/freebsd-e1000/main.c b/src/drivers/generic/freebsd-e1000/main.c index 9c487faa..d1b7ac9e 100644 --- a/src/drivers/generic/freebsd-e1000/main.c +++ b/src/drivers/generic/freebsd-e1000/main.c @@ -276,6 +276,7 @@ static void* map_registers(uintptr_t phys, size_t size, bool uc, bool mmio, bool MmH_RefPage(pg); MmS_SetPageMapping(Mm_KernelContext.pt, &page, phys + offset, false); } + MmS_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size); return virt+phys_page_offset; } diff --git a/src/drivers/generic/r8169/device.c b/src/drivers/generic/r8169/device.c index 17a549be..08e4d819 100644 --- a/src/drivers/generic/r8169/device.c +++ b/src/drivers/generic/r8169/device.c @@ -385,6 +385,7 @@ static void* map_registers(uintptr_t phys, size_t size, bool uc, bool mmio, bool MmH_RefPage(pg); MmS_SetPageMapping(Mm_KernelContext.pt, &page, phys + offset, false); } + MmS_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size); return virt+phys_page_offset; } diff --git a/src/oboskrnl/arch/x86_64/map.c b/src/oboskrnl/arch/x86_64/map.c index ad1deec0..d8c2b2cc 100644 --- a/src/oboskrnl/arch/x86_64/map.c +++ b/src/oboskrnl/arch/x86_64/map.c @@ -144,8 +144,6 @@ bool Arch_FreePageMapAt(uintptr_t pml4Base, uintptr_t at, uint8_t maxDepth) return true; } -static obos_status invlpg_impl(uintptr_t at); - static bool has_xd() { static bool ret = false, init = false; @@ -166,14 +164,11 @@ obos_status Arch_MapPage(uintptr_t cr3, void* at_, uintptr_t phys, uintptr_t fla phys = Arch_MaskPhysicalAddressFromEntry(phys); uintptr_t* pm = Arch_AllocatePageMapAt(cr3, at, flags & ~512, 3); uintptr_t entry = phys | flags; - bool shouldInvplg = pm[AddressToIndex(at, 0)] != entry; // for (volatile bool b = !(flags & 1); b; ) // ; pm[AddressToIndex(at, 0)] = entry; if (free_pte && ~flags & BIT_TYPE(0, UL)) Arch_FreePageMapAt(cr3, at, 3); - if (shouldInvplg) - invlpg_impl(at); return OBOS_STATUS_SUCCESS; } obos_status Arch_MapHugePage(uintptr_t cr3, void* at_, uintptr_t phys, uintptr_t flags, bool free_pte) @@ -191,17 +186,15 @@ obos_status Arch_MapHugePage(uintptr_t cr3, void* at_, uintptr_t phys, uintptr_t phys = Arch_MaskPhysicalAddressFromEntry(phys); uintptr_t* pm = Arch_AllocatePageMapAt(cr3, at, flags & ~512, 2); uintptr_t entry = phys | flags | ((uintptr_t)1 << 7); - bool shouldInvplg = (entry != pm[AddressToIndex(at, 1)]); pm[AddressToIndex(at, 1)] = entry; if (free_pte && ~flags & BIT_TYPE(0, UL)) Arch_FreePageMapAt(cr3, at, 2); - if (shouldInvplg) - invlpg_impl(at); return OBOS_STATUS_SUCCESS; } static struct { spinlock lock; uintptr_t addr; + size_t size; uintptr_t cr3; atomic_size_t nCPUsRan; bool active; @@ -214,7 +207,8 @@ bool Arch_InvlpgIPI(interrupt_frame* frame) if (!invlpg_ipi_packet.active) return false; if (getCR3() == invlpg_ipi_packet.cr3) - invlpg(invlpg_ipi_packet.addr); + for (uintptr_t addr = invlpg_ipi_packet.addr; addr < (invlpg_ipi_packet.addr + invlpg_ipi_packet.size); addr += OBOS_PAGE_SIZE) + invlpg(addr); invlpg_ipi_packet.nCPUsRan++; if (invlpg_ipi_packet.nCPUsRan >= Core_CpuCount) invlpg_ipi_packet.active = false; @@ -242,7 +236,7 @@ obos_status Arch_UnmapPage(uintptr_t cr3, void* at_, bool free_pte) pt[AddressToIndex(at, (uint8_t)isHugePage)] &= ~BIT(0); if (free_pte) Arch_FreePageMapAt(cr3, at, 3 - (uint8_t)isHugePage); - return invlpg_impl(at); + return OBOS_STATUS_SUCCESS; } static void invlpg_ipi_bootstrap(struct irq* i, interrupt_frame* frame, void* userdata, irql oldIrql) { @@ -251,9 +245,12 @@ static void invlpg_ipi_bootstrap(struct irq* i, interrupt_frame* frame, void* us OBOS_UNUSED(oldIrql); Arch_InvlpgIPI(frame); } -static obos_status invlpg_impl(uintptr_t at) + +obos_status MmS_TLBShootdown(page_table pt, uintptr_t base, size_t size) { - invlpg(at); + for (uintptr_t addr = base; addr < (base + size); addr += OBOS_PAGE_SIZE) + invlpg(addr); + #ifndef OBOS_UP if (!Arch_SMPInitialized || Core_CpuCount == 1) return OBOS_STATUS_SUCCESS; @@ -298,8 +295,9 @@ static obos_status invlpg_impl(uintptr_t at) vector.info.vector = 0; } invlpg_ipi_packet.active = true; - invlpg_ipi_packet.addr = at; - invlpg_ipi_packet.cr3 = getCR3(); + invlpg_ipi_packet.addr = base; + invlpg_ipi_packet.size = size; + invlpg_ipi_packet.cr3 = pt; invlpg_ipi_packet.nCPUsRan = 1; invlpg_ipi_packet.sender = CoreS_GetCPULocalPtr(); obos_status status = Arch_LAPICSendIPI(lapic, vector); @@ -312,6 +310,7 @@ static obos_status invlpg_impl(uintptr_t at) #endif return OBOS_STATUS_SUCCESS; } + obos_status OBOSS_MapPage_RW_XD(void* at_, uintptr_t phys) { return Arch_MapPage(getCR3(), at_, phys, 0x8000000000000003, false); diff --git a/src/oboskrnl/driver_interface/pci_irq.c b/src/oboskrnl/driver_interface/pci_irq.c index 4ce507bd..dd9b367d 100644 --- a/src/oboskrnl/driver_interface/pci_irq.c +++ b/src/oboskrnl/driver_interface/pci_irq.c @@ -40,6 +40,7 @@ static void* map_registers(uintptr_t phys, size_t size, bool uc) page.prot.uc = uc; MmS_SetPageMapping(Mm_KernelContext.pt, &page, phys + offset, false); } + MmS_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size); return virt+phys_page_offset; } static void pci_irq_move_callback(struct irq* i, struct irq_vector* from, struct irq_vector* to, void* userdata) diff --git a/src/oboskrnl/mm/alloc.c b/src/oboskrnl/mm/alloc.c index 42f23cbb..e33fecaa 100644 --- a/src/oboskrnl/mm/alloc.c +++ b/src/oboskrnl/mm/alloc.c @@ -576,6 +576,7 @@ obos_status Mm_VirtualMemoryFree(context* ctx, void* base_, size_t size) } MmS_SetPageMapping(ctx->pt, &pg, 0, true); } + MmS_TLBShootdown(ctx->pt, base, size); if (rng) { @@ -817,6 +818,7 @@ obos_status Mm_VirtualMemoryProtect(context* ctx, void* base_, size_t size, prot pg.prot.present = info.prot.present; MmS_SetPageMapping(ctx->pt, &pg, info.phys, false); } + MmS_TLBShootdown(ctx->pt, base, size); Core_SpinlockRelease(&ctx->lock, oldIrql); return OBOS_STATUS_SUCCESS; } diff --git a/src/oboskrnl/mm/context.h b/src/oboskrnl/mm/context.h index d94862de..d4031189 100644 --- a/src/oboskrnl/mm/context.h +++ b/src/oboskrnl/mm/context.h @@ -43,6 +43,8 @@ OBOS_EXPORT page_table MmS_GetCurrentPageTable(); /// The status of the function. OBOS_EXPORT obos_status MmS_SetPageMapping(page_table pt, const page_info* page, uintptr_t phys, bool free_pte); +OBOS_WEAK obos_status MmS_TLBShootdown(page_table pt, uintptr_t base, size_t size); + typedef struct working_set { struct { diff --git a/src/oboskrnl/mm/fork.c b/src/oboskrnl/mm/fork.c index 69214d66..f75243b9 100644 --- a/src/oboskrnl/mm/fork.c +++ b/src/oboskrnl/mm/fork.c @@ -90,6 +90,7 @@ obos_status Mm_ForkContext(context* into, context* toFork) down: MmS_SetPageMapping(into->pt, &info, info.phys, false); } + MmS_TLBShootdown(toFork->pt, curr->virt, curr->size); } } Core_SpinlockRelease(&toFork->lock, oldIrql); diff --git a/src/oboskrnl/mm/handler.c b/src/oboskrnl/mm/handler.c index f348e7d1..21dc286e 100644 --- a/src/oboskrnl/mm/handler.c +++ b/src/oboskrnl/mm/handler.c @@ -65,6 +65,7 @@ static void map_file_region(page_range* rng, uintptr_t addr, uint32_t ec, fault_ info->prot.rw = rng->prot.rw && !(ec & PF_EC_RW); MmS_SetPageMapping(rng->ctx->pt, info, phys->phys, false); + MmS_TLBShootdown(rng->ctx->pt, info->virt, info->prot.huge_page ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE); } static bool sym_cow_cpy(context* ctx, page_range* rng, uintptr_t addr, uint32_t ec, page* pg, page_info* info) @@ -77,6 +78,7 @@ static bool sym_cow_cpy(context* ctx, page_range* rng, uintptr_t addr, uint32_t info->prot.rw = true; info->prot.ro = false; MmS_SetPageMapping(ctx->pt, info, pg->phys, false); + MmS_TLBShootdown(ctx->pt, info->virt, info->prot.huge_page ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE); pg->cow_type = COW_DISABLED; return true; } @@ -86,6 +88,7 @@ static bool sym_cow_cpy(context* ctx, page_range* rng, uintptr_t addr, uint32_t info->prot.rw = true; info->prot.ro = false; MmS_SetPageMapping(ctx->pt, info, new->phys, false); + MmS_TLBShootdown(ctx->pt, info->virt, info->prot.huge_page ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE); MmH_DerefPage(pg); return true; } @@ -168,6 +171,7 @@ static bool asym_cow_cpy(context* ctx, page_range* rng, uintptr_t addr, uint32_t } done: MmS_SetPageMapping(ctx->pt, info, pg->phys, false); + MmS_TLBShootdown(rng->ctx->pt, info->virt, info->prot.huge_page ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE); info->range = rng; if (ec & PF_EC_RW) Mm_MarkAsDirtyPhys(pg); diff --git a/src/oboskrnl/mm/swap.c b/src/oboskrnl/mm/swap.c index 617de82f..a9a16cdf 100644 --- a/src/oboskrnl/mm/swap.c +++ b/src/oboskrnl/mm/swap.c @@ -60,6 +60,7 @@ obos_status Mm_SwapOut(uintptr_t virt, page_range* rng) return status; page.prot.present = false; status = MmS_SetPageMapping(rng->ctx->pt, &page, phys, false); + MmS_TLBShootdown(rng->ctx->pt, page.virt, page.prot.huge_page ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE); if (obos_is_error(status)) return status; if (page.dirty) diff --git a/src/uHDA/kernel_api.c b/src/uHDA/kernel_api.c index 6f5683be..2a7c8701 100644 --- a/src/uHDA/kernel_api.c +++ b/src/uHDA/kernel_api.c @@ -157,6 +157,7 @@ static void* map_registers(uintptr_t phys, size_t size, bool uc) page.phys = phys+offset; MmS_SetPageMapping(Mm_KernelContext.pt, &page, phys + offset, false); } + MmS_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size); return virt+phys_page_offset; } From 6785dda0896bfc53a1cfb3b59db0bf78fe5288bc Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Wed, 26 Nov 2025 17:01:13 -0500 Subject: [PATCH 34/96] drv: add Drv_TLBShootdown for drivers to use in place of MmS_TLBShootdown --- src/drivers/generic/ahci/main.c | 2 +- src/drivers/generic/freebsd-e1000/main.c | 2 +- src/drivers/generic/r8169/device.c | 2 +- src/oboskrnl/mm/context.c | 7 ++ src/oboskrnl/mm/context.h | 2 + src/oboskrnl/vfs/fd_sys.c | 94 +++++++++++++++++++----- src/uHDA/kernel_api.c | 2 +- 7 files changed, 87 insertions(+), 24 deletions(-) diff --git a/src/drivers/generic/ahci/main.c b/src/drivers/generic/ahci/main.c index aac1732d..515b9fea 100644 --- a/src/drivers/generic/ahci/main.c +++ b/src/drivers/generic/ahci/main.c @@ -158,7 +158,7 @@ static void* map_registers(uintptr_t phys, size_t size, bool uc) page.phys = phys+offset; MmS_SetPageMapping(Mm_KernelContext.pt, &page, phys + offset, false); } - MmS_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size); + Drv_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size); return virt+phys_page_offset; } diff --git a/src/drivers/generic/freebsd-e1000/main.c b/src/drivers/generic/freebsd-e1000/main.c index d1b7ac9e..6c8e0f17 100644 --- a/src/drivers/generic/freebsd-e1000/main.c +++ b/src/drivers/generic/freebsd-e1000/main.c @@ -276,7 +276,7 @@ static void* map_registers(uintptr_t phys, size_t size, bool uc, bool mmio, bool MmH_RefPage(pg); MmS_SetPageMapping(Mm_KernelContext.pt, &page, phys + offset, false); } - MmS_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size); + Drv_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size); return virt+phys_page_offset; } diff --git a/src/drivers/generic/r8169/device.c b/src/drivers/generic/r8169/device.c index 08e4d819..ebd72b27 100644 --- a/src/drivers/generic/r8169/device.c +++ b/src/drivers/generic/r8169/device.c @@ -385,7 +385,7 @@ static void* map_registers(uintptr_t phys, size_t size, bool uc, bool mmio, bool MmH_RefPage(pg); MmS_SetPageMapping(Mm_KernelContext.pt, &page, phys + offset, false); } - MmS_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size); + Drv_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size); return virt+phys_page_offset; } diff --git a/src/oboskrnl/mm/context.c b/src/oboskrnl/mm/context.c index b319fe48..d5f21146 100644 --- a/src/oboskrnl/mm/context.c +++ b/src/oboskrnl/mm/context.c @@ -210,3 +210,10 @@ void Mm_ConstructContext(context* ctx) ctx->pt = MmS_AllocatePageTable(); ctx->lock = Core_SpinlockCreate(); } + +OBOS_EXPORT obos_status Drv_TLBShootdown(page_table pt, uintptr_t base, size_t size) +{ + if (MmS_TLBShootdown) + return MmS_TLBShootdown(pt, base, size); + return OBOS_STATUS_UNIMPLEMENTED; +} \ No newline at end of file diff --git a/src/oboskrnl/mm/context.h b/src/oboskrnl/mm/context.h index d4031189..f2ca8dca 100644 --- a/src/oboskrnl/mm/context.h +++ b/src/oboskrnl/mm/context.h @@ -45,6 +45,8 @@ OBOS_EXPORT obos_status MmS_SetPageMapping(page_table pt, const page_info* page, OBOS_WEAK obos_status MmS_TLBShootdown(page_table pt, uintptr_t base, size_t size); +OBOS_EXPORT obos_status Drv_TLBShootdown(page_table pt, uintptr_t base, size_t size); + typedef struct working_set { struct { diff --git a/src/oboskrnl/vfs/fd_sys.c b/src/oboskrnl/vfs/fd_sys.c index 5fe7c9a0..6285d804 100644 --- a/src/oboskrnl/vfs/fd_sys.c +++ b/src/oboskrnl/vfs/fd_sys.c @@ -519,6 +519,8 @@ obos_status Sys_FdIoctl(handle desc, uintptr_t request, void* argp, size_t sz_ar obos_status Sys_FdFlush(handle desc) { + if (HANDLE_TYPE(desc) == HANDLE_TYPE_DIRENT) + return OBOS_STATUS_SUCCESS; OBOS_LockHandleTable(OBOS_CurrentHandleTable()); obos_status status = OBOS_STATUS_SUCCESS; handle_desc* fd = OBOS_HandleLookup(OBOS_CurrentHandleTable(), desc, HANDLE_TYPE_FD, false, &status); @@ -2824,17 +2826,40 @@ obos_status Sys_FChmodAt(handle dirfd, const char* upathname, int mode, int flag pathname = ZeroAllocate(OBOS_KernelAllocator, sz_path+1, sizeof(char), nullptr); OBOSH_ReadUserString(upathname, pathname, nullptr); + vnode* target = nullptr; + dirent* parent = nullptr; const char* name = nullptr; if (dirfd != AT_FDCWD) { + if (HANDLE_TYPE(dirfd) != HANDLE_TYPE_DIRENT && HANDLE_TYPE(dirfd) != HANDLE_TYPE_FD) + { + status = OBOS_STATUS_INVALID_ARGUMENT; + goto fail; + } + if (HANDLE_TYPE(dirfd) == HANDLE_TYPE_FD && strlen(pathname)) + { + status = OBOS_STATUS_INVALID_ARGUMENT; + goto fail; + } OBOS_LockHandleTable(OBOS_CurrentHandleTable()); - handle_desc* desc = OBOS_HandleLookup(OBOS_CurrentHandleTable(), dirfd, HANDLE_TYPE_DIRENT, false, &status); + handle_desc* desc = OBOS_HandleLookup(OBOS_CurrentHandleTable(), dirfd, 0, true, &status); if (obos_is_error(status)) { OBOS_UnlockHandleTable(OBOS_CurrentHandleTable()); goto fail; } + if (HANDLE_TYPE(dirfd) == HANDLE_TYPE_FD) + { + target = desc->un.fd->vn; + OBOS_UnlockHandleTable(OBOS_CurrentHandleTable()); + if (!target) + { + status = OBOS_STATUS_INVALID_ARGUMENT; + goto fail; + } + goto have_target; + } parent = desc->un.dirent->parent; OBOS_UnlockHandleTable(OBOS_CurrentHandleTable()); @@ -2866,18 +2891,22 @@ obos_status Sys_FChmodAt(handle dirfd, const char* upathname, int mode, int flag name = pathname; } - dirent* target = VfsH_DirentLookupFrom(name, parent); - if (!target) + dirent* targetd = VfsH_DirentLookupFrom(name, parent); + if (!targetd) { status = OBOS_STATUS_NOT_FOUND; goto fail; } if (~flags & AT_SYMLINK_NOFOLLOW) - target = VfsH_FollowLink(target); + targetd = VfsH_FollowLink(targetd); // NOTE(oberrow): AT_EMPTY_PATH is the default on obos, and can actually not be // changed, because of the nature of the lookup() function + + target = targetd->vnode; - if (target->vnode->owner_uid != Sys_GetUid() && Sys_GetUid() != ROOT_UID) + have_target: + + if (target->owner_uid != Sys_GetUid() && Sys_GetUid() != ROOT_UID) { status = OBOS_STATUS_ACCESS_DENIED; goto fail; @@ -2885,18 +2914,18 @@ obos_status Sys_FChmodAt(handle dirfd, const char* upathname, int mode, int flag file_perm real_mode = unix_to_obos_mode(mode, true); - driver_header* header = Vfs_GetVnodeDriver(target->vnode); + driver_header* header = Vfs_GetVnodeDriver(target); if (!header) { status = OBOS_STATUS_INTERNAL_ERROR; goto fail; } - status = !header->ftable.set_file_perms ? OBOS_STATUS_UNIMPLEMENTED : header->ftable.set_file_perms(target->vnode->desc, real_mode); + status = !header->ftable.set_file_perms ? OBOS_STATUS_UNIMPLEMENTED : header->ftable.set_file_perms(target->desc, real_mode); if (obos_is_error(status)) goto fail; - target->vnode->perm = real_mode; + target->perm = real_mode; fail: Free(OBOS_KernelAllocator, pathname, sz_path); @@ -2912,24 +2941,44 @@ obos_status Sys_FChownAt(handle dirfd, const char *upathname, uid owner, gid gro size_t sz_path = 0; status = OBOSH_ReadUserString(upathname, nullptr, &sz_path); if (obos_is_error(status)) - { - Free(OBOS_KernelAllocator, pathname, sz_path); return status; - } pathname = ZeroAllocate(OBOS_KernelAllocator, sz_path+1, sizeof(char), nullptr); OBOSH_ReadUserString(upathname, pathname, nullptr); + vnode* target = nullptr; + dirent* parent = nullptr; const char* name = nullptr; if (dirfd != AT_FDCWD) { + if (HANDLE_TYPE(dirfd) != HANDLE_TYPE_DIRENT && HANDLE_TYPE(dirfd) != HANDLE_TYPE_FD) + { + status = OBOS_STATUS_INVALID_ARGUMENT; + goto fail; + } + if (HANDLE_TYPE(dirfd) == HANDLE_TYPE_FD && strlen(pathname)) + { + status = OBOS_STATUS_INVALID_ARGUMENT; + goto fail; + } OBOS_LockHandleTable(OBOS_CurrentHandleTable()); - handle_desc* desc = OBOS_HandleLookup(OBOS_CurrentHandleTable(), dirfd, HANDLE_TYPE_DIRENT, false, &status); + handle_desc* desc = OBOS_HandleLookup(OBOS_CurrentHandleTable(), dirfd, 0, true, &status); if (obos_is_error(status)) { OBOS_UnlockHandleTable(OBOS_CurrentHandleTable()); goto fail; } + if (HANDLE_TYPE(dirfd) == HANDLE_TYPE_FD) + { + target = desc->un.fd->vn; + OBOS_UnlockHandleTable(OBOS_CurrentHandleTable()); + if (!target) + { + status = OBOS_STATUS_INVALID_ARGUMENT; + goto fail; + } + goto have_target; + } parent = desc->un.dirent->parent; OBOS_UnlockHandleTable(OBOS_CurrentHandleTable()); @@ -2961,38 +3010,43 @@ obos_status Sys_FChownAt(handle dirfd, const char *upathname, uid owner, gid gro name = pathname; } - dirent* target = VfsH_DirentLookupFrom(name, parent); - if (!target) + dirent* targetd = VfsH_DirentLookupFrom(name, parent); + if (!targetd) { status = OBOS_STATUS_NOT_FOUND; goto fail; } if (~flags & AT_SYMLINK_NOFOLLOW) - target = VfsH_FollowLink(target); + targetd = VfsH_FollowLink(targetd); // NOTE(oberrow): AT_EMPTY_PATH is the default on obos, and can actually not be // changed, because of the nature of the lookup() function + + target = targetd->vnode; + + have_target: + OBOS_ENSURE(target); - if (target->vnode->owner_uid != Sys_GetUid() && Sys_GetUid() != ROOT_UID) + if (target->owner_uid != Sys_GetUid() && Sys_GetUid() != ROOT_UID) { status = OBOS_STATUS_ACCESS_DENIED; goto fail; } - driver_header* header = Vfs_GetVnodeDriver(target->vnode); + driver_header* header = Vfs_GetVnodeDriver(target); if (!header) { status = OBOS_STATUS_INTERNAL_ERROR; goto fail; } - status = !header->ftable.set_file_owner ? OBOS_STATUS_UNIMPLEMENTED : header->ftable.set_file_owner(target->vnode->desc, owner, group); + status = !header->ftable.set_file_owner ? OBOS_STATUS_UNIMPLEMENTED : header->ftable.set_file_owner(target->desc, owner, group); if (obos_is_error(status)) goto fail; if (owner != -1) - target->vnode->owner_uid = owner; + target->owner_uid = owner; if (group != -1) - target->vnode->group_uid = group; + target->group_uid = group; fail: Free(OBOS_KernelAllocator, pathname, sz_path); diff --git a/src/uHDA/kernel_api.c b/src/uHDA/kernel_api.c index 2a7c8701..54bcffc4 100644 --- a/src/uHDA/kernel_api.c +++ b/src/uHDA/kernel_api.c @@ -157,7 +157,7 @@ static void* map_registers(uintptr_t phys, size_t size, bool uc) page.phys = phys+offset; MmS_SetPageMapping(Mm_KernelContext.pt, &page, phys + offset, false); } - MmS_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size); + Drv_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size); return virt+phys_page_offset; } From 7221a2ee2158aba19280682e07e9e70f581b81d4 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Wed, 26 Nov 2025 17:43:34 -0500 Subject: [PATCH 35/96] x86_64: Optimize TLB shootdowns --- src/oboskrnl/arch/x86_64/cpu_local_arch.h | 9 +- src/oboskrnl/arch/x86_64/entry.c | 3 +- src/oboskrnl/arch/x86_64/map.c | 184 ++++++++++++---------- src/oboskrnl/power/shutdown.c | 2 + 4 files changed, 114 insertions(+), 84 deletions(-) diff --git a/src/oboskrnl/arch/x86_64/cpu_local_arch.h b/src/oboskrnl/arch/x86_64/cpu_local_arch.h index 910e089b..ccc7b479 100644 --- a/src/oboskrnl/arch/x86_64/cpu_local_arch.h +++ b/src/oboskrnl/arch/x86_64/cpu_local_arch.h @@ -1,7 +1,7 @@ /* - oboskrnl/arch/x86_64/cpu_local_arch.h - - Copyright (c) 2024 Omar Berrow + * oboskrnl/arch/x86_64/cpu_local_arch.h + * + * Copyright (c) 2024 Omar Berrow */ #pragma once @@ -14,6 +14,8 @@ #include +#include + typedef struct cpu_local_arch { uint64_t gdtEntries[7]; @@ -45,4 +47,5 @@ typedef struct cpu_local_arch dpc dbg_dpc; uint64_t stack_check_guard; uint8_t lapicId; + struct tlb_shootdown_packet* curr_pckt; } cpu_local_arch; diff --git a/src/oboskrnl/arch/x86_64/entry.c b/src/oboskrnl/arch/x86_64/entry.c index 65c53fbd..0b86f8bf 100644 --- a/src/oboskrnl/arch/x86_64/entry.c +++ b/src/oboskrnl/arch/x86_64/entry.c @@ -394,7 +394,8 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry nullptr, nullptr, nullptr, nullptr, nullptr, - (void*)font_bin, 8, 16, 0, + // (void*)font_bin, 8, 16, 0, + nullptr, 8, 16, 0, 0,0, 0); init_flanterm_backend(); diff --git a/src/oboskrnl/arch/x86_64/map.c b/src/oboskrnl/arch/x86_64/map.c index d8c2b2cc..278e20e6 100644 --- a/src/oboskrnl/arch/x86_64/map.c +++ b/src/oboskrnl/arch/x86_64/map.c @@ -14,7 +14,7 @@ #include #include - +#include #include #include @@ -29,8 +29,12 @@ #include #include +#include + #include +#include + #include #include @@ -191,30 +195,7 @@ obos_status Arch_MapHugePage(uintptr_t cr3, void* at_, uintptr_t phys, uintptr_t Arch_FreePageMapAt(cr3, at, 2); return OBOS_STATUS_SUCCESS; } -static struct { - spinlock lock; - uintptr_t addr; - size_t size; - uintptr_t cr3; - atomic_size_t nCPUsRan; - bool active; - irq* irq; - cpu_local* sender; -} invlpg_ipi_packet; -bool Arch_InvlpgIPI(interrupt_frame* frame) -{ - OBOS_UNUSED(frame); - if (!invlpg_ipi_packet.active) - return false; - if (getCR3() == invlpg_ipi_packet.cr3) - for (uintptr_t addr = invlpg_ipi_packet.addr; addr < (invlpg_ipi_packet.addr + invlpg_ipi_packet.size); addr += OBOS_PAGE_SIZE) - invlpg(addr); - invlpg_ipi_packet.nCPUsRan++; - if (invlpg_ipi_packet.nCPUsRan >= Core_CpuCount) - invlpg_ipi_packet.active = false; - // Arch_LAPICAddress->eoi = 0; - return true; -} + extern bool Arch_SMPInitialized; obos_status Arch_UnmapPage(uintptr_t cr3, void* at_, bool free_pte) { @@ -238,6 +219,54 @@ obos_status Arch_UnmapPage(uintptr_t cr3, void* at_, bool free_pte) Arch_FreePageMapAt(cr3, at, 3 - (uint8_t)isHugePage); return OBOS_STATUS_SUCCESS; } + +static irq* invlpg_irq; +typedef struct tlb_shootdown_packet { + uintptr_t base; + size_t size; + atomic_size_t refcount; + LIST_NODE(tlb_shootdown_queue, struct tlb_shootdown_packet) node; +} tlb_shootdown_packet; +typedef LIST_HEAD(tlb_shootdown_queue, tlb_shootdown_packet) tlb_shootdown_queue; +LIST_GENERATE_STATIC(tlb_shootdown_queue, tlb_shootdown_packet, node); +tlb_shootdown_queue g_tlb_shootdown_queue; +spinlock g_tlb_shootdown_queue_lock; + +static void deref_tlb_shootdown_pckt(tlb_shootdown_packet* pckt) +{ + if (!--pckt->refcount) + Free(Mm_Allocator, pckt, sizeof(*pckt)); +} + +bool Arch_InvlpgIPI(interrupt_frame* frame) +{ + OBOS_UNUSED(frame); + if (!LIST_GET_NODE_COUNT(tlb_shootdown_queue, &g_tlb_shootdown_queue)) + return false; + tlb_shootdown_packet* curr = CoreS_GetCPULocalPtr()->arch_specific.curr_pckt; + if (!curr) + curr = LIST_GET_HEAD(tlb_shootdown_queue, &g_tlb_shootdown_queue); + else + curr = LIST_GET_NEXT(tlb_shootdown_queue, &g_tlb_shootdown_queue, curr); + + while (curr) + { + for (uintptr_t addr = curr->base; addr <= (curr->base+curr->size); addr += OBOS_PAGE_SIZE) + { + OBOS_ENSURE(addr >= curr->base); + invlpg(addr); + } + + if (curr != LIST_GET_TAIL(tlb_shootdown_queue, &g_tlb_shootdown_queue)) + deref_tlb_shootdown_pckt(curr); + else + CoreS_GetCPULocalPtr()->arch_specific.curr_pckt = curr; + curr = LIST_GET_NEXT(tlb_shootdown_queue, &g_tlb_shootdown_queue, curr); + } + + return true; +} + static void invlpg_ipi_bootstrap(struct irq* i, interrupt_frame* frame, void* userdata, irql oldIrql) { OBOS_UNUSED(i); @@ -246,68 +275,64 @@ static void invlpg_ipi_bootstrap(struct irq* i, interrupt_frame* frame, void* us Arch_InvlpgIPI(frame); } +#define issue_nmi() \ + Arch_LAPICSendIPI((ipi_lapic_info){.isShorthand=true,.info.shorthand=LAPIC_DESTINATION_SHORTHAND_ALL}, \ + (ipi_vector_info){.deliveryMode=LAPIC_DELIVERY_MODE_NMI}) + + +extern uintptr_t Arch_KernelCR3; + +enum { IRQL_INVLPG_IPI=15 }; + obos_status MmS_TLBShootdown(page_table pt, uintptr_t base, size_t size) { - for (uintptr_t addr = base; addr < (base + size); addr += OBOS_PAGE_SIZE) - invlpg(addr); - -#ifndef OBOS_UP - if (!Arch_SMPInitialized || Core_CpuCount == 1) - return OBOS_STATUS_SUCCESS; - enum { IRQL_INVLPG_IPI=15 }; - if (!invlpg_ipi_packet.irq && Core_IrqInterfaceInitialized()) + if (Core_CpuCount == 1 || !Arch_SMPInitialized) { - static irq irq; - invlpg_ipi_packet.irq = &irq; - Core_IrqObjectInitializeIRQL(&irq, IRQL_INVLPG_IPI, false, true); - irq.handler = invlpg_ipi_bootstrap; - irq.handlerUserdata = nullptr; + for (uintptr_t addr = base; addr < (base + size); addr += OBOS_PAGE_SIZE) + invlpg(addr); + return OBOS_STATUS_SUCCESS; } - extern bool Arch_HaltCPUs; - if (Arch_LAPICAddress->interruptRequest224_255 & (1<<16)) + +#if OBOS_UP + return OBOS_STATUS_SUCCESS; +#endif + + if (pt != Arch_KernelCR3) + goto ipi; + + // Can this allocation cause problems? + // i sure do hope not... + tlb_shootdown_packet* pckt = ZeroAllocate(Mm_Allocator, 1, sizeof(tlb_shootdown_packet), nullptr); + pckt->base = base; + pckt->size = size; + pckt->refcount = Core_CpuCount; + irql oldIrql = Core_SpinlockAcquire(&g_tlb_shootdown_queue_lock); + LIST_APPEND(tlb_shootdown_queue, &g_tlb_shootdown_queue, pckt); + Core_SpinlockRelease(&g_tlb_shootdown_queue_lock, oldIrql); + + ipi: + // Issue the IPI. + + if (Core_IrqInterfaceInitialized()) { - irql oldIrql = Core_GetIrql(); - if (oldIrql >= IRQL_INVLPG_IPI) + static ipi_vector_info vec = {}; + static ipi_lapic_info dest = {.isShorthand=true,.info.shorthand=LAPIC_DESTINATION_SHORTHAND_ALL}; + if (!invlpg_irq) { - Core_LowerIrql(IRQL_DISPATCH); - irql unused = Core_RaiseIrql(oldIrql); - OBOS_UNUSED(unused); + static irq irq; + invlpg_irq = &irq; + Core_IrqObjectInitializeIRQL(&irq, IRQL_INVLPG_IPI, false, true); + irq.handler = invlpg_ipi_bootstrap; + irq.handlerUserdata = nullptr; + + vec.deliveryMode = LAPIC_DELIVERY_MODE_FIXED; + vec.info.vector = irq.vector->id + 0x20; } + Arch_LAPICSendIPI(dest, vec); } - size_t spin = 0; - while (invlpg_ipi_packet.active && ++spin <= 10000) - pause(); - Arch_HaltCPUs = false; - irql oldIrql = Core_SpinlockAcquireExplicit(&invlpg_ipi_packet.lock, IRQL_MASKED, false); - ipi_lapic_info lapic = { - .isShorthand=true, - .info.shorthand = LAPIC_DESTINATION_SHORTHAND_ALL_BUT_SELF - }; - ipi_vector_info vector = {}; - if (invlpg_ipi_packet.irq) - { - vector.deliveryMode = LAPIC_DELIVERY_MODE_FIXED; - vector.info.vector = invlpg_ipi_packet.irq->vector->id+0x20; - } - else - { - vector.deliveryMode = LAPIC_DELIVERY_MODE_NMI; - vector.info.vector = 0; - } - invlpg_ipi_packet.active = true; - invlpg_ipi_packet.addr = base; - invlpg_ipi_packet.size = size; - invlpg_ipi_packet.cr3 = pt; - invlpg_ipi_packet.nCPUsRan = 1; - invlpg_ipi_packet.sender = CoreS_GetCPULocalPtr(); - obos_status status = Arch_LAPICSendIPI(lapic, vector); - OBOS_ASSERT(obos_is_success(status)); - OBOS_UNUSED(status); - // This can be done async. - // while (invlpg_ipi_packet.nCPUsRan != Core_CpuCount) - // pause(); - Core_SpinlockRelease(&invlpg_ipi_packet.lock, oldIrql); -#endif + else if (pt != Arch_KernelCR3) + issue_nmi(); + return OBOS_STATUS_SUCCESS; } @@ -359,7 +384,6 @@ static void FreePageTables(uintptr_t* pm, uint8_t level, uint32_t beginIndex, ui } uintptr_t MmS_KernelBaseAddress; uintptr_t MmS_KernelEndAddress; -extern uintptr_t Arch_KernelCR3; obos_status Arch_InitializeKernelPageTable() { obos_status status = OBOS_STATUS_SUCCESS; diff --git a/src/oboskrnl/power/shutdown.c b/src/oboskrnl/power/shutdown.c index ebf012d2..1a6ea0af 100644 --- a/src/oboskrnl/power/shutdown.c +++ b/src/oboskrnl/power/shutdown.c @@ -41,6 +41,7 @@ OBOS_NORETURN void OBOS_Reboot() { if (Mm_SwapProvider->deinit_dev) Mm_SwapProvider->deinit_dev(Mm_SwapProvider); + irql oldIrql = Core_RaiseIrql(IRQL_MASKED); Core_SuspendScheduler(true); Core_WaitForSchedulerSuspend(); uacpi_reboot(); @@ -55,6 +56,7 @@ OBOS_NORETURN void OBOS_Reboot() // We should not be here anymore. OBOS_UNREACHABLE; #endif + (void)oldIrql; while(1) asm volatile(""); } From e95543392ee39c1911411d11ea5c29c6a31a534c Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Wed, 26 Nov 2025 18:05:14 -0500 Subject: [PATCH 36/96] x86_64: Fix bug with TLB shootdown --- src/oboskrnl/arch/x86_64/map.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/oboskrnl/arch/x86_64/map.c b/src/oboskrnl/arch/x86_64/map.c index 278e20e6..02e89eee 100644 --- a/src/oboskrnl/arch/x86_64/map.c +++ b/src/oboskrnl/arch/x86_64/map.c @@ -235,7 +235,12 @@ spinlock g_tlb_shootdown_queue_lock; static void deref_tlb_shootdown_pckt(tlb_shootdown_packet* pckt) { if (!--pckt->refcount) + { + irql oldIrql = Core_SpinlockAcquire(&g_tlb_shootdown_queue_lock); + LIST_REMOVE(tlb_shootdown_queue, &g_tlb_shootdown_queue, pckt); + Core_SpinlockRelease(&g_tlb_shootdown_queue_lock, oldIrql); Free(Mm_Allocator, pckt, sizeof(*pckt)); + } } bool Arch_InvlpgIPI(interrupt_frame* frame) From f97a029cb02181b2a9e5a1e17c2ff8e8e499ebcc Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Wed, 26 Nov 2025 18:05:35 -0500 Subject: [PATCH 37/96] net/tcp: Reset connection when socket is closed before a proper shutdown --- src/oboskrnl/net/tcp.c | 18 +++++++++++++++++- src/oboskrnl/net/tcp.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/oboskrnl/net/tcp.c b/src/oboskrnl/net/tcp.c index 853b2e01..97b086e9 100644 --- a/src/oboskrnl/net/tcp.c +++ b/src/oboskrnl/net/tcp.c @@ -999,6 +999,19 @@ void Net_TCPPushDataToRemote(tcp_connection* con, const void* buffer, size_t siz } +void Net_TCPReset(tcp_connection* con) +{ + struct tcp_pseudo_hdr hdr = {}; + hdr.ack = con->state.rcv.nxt; + hdr.seq = ++con->state.snd.nxt; + hdr.flags = TCP_RST; + hdr.src_port = con->src.port; + hdr.dest_port = con->dest.port; + hdr.ttl = con->ttl; + NetH_SendTCPSegment(con->nic, nullptr, con->ip_ent, con->dest.addr, &hdr); + Net_TCPChangeConnectionState(con, TCP_STATE_CLOSED); +} + // LIST_GENERATE(tcp_incoming_list, tcp_incoming_packet, node); RB_GENERATE(tcp_connection_tree, tcp_connection, node, tcp_connection_cmp); RB_GENERATE(tcp_port_tree, tcp_port, node, tcp_port_cmp); @@ -1036,7 +1049,10 @@ void tcp_free(socket_desc* socket) if (!s->is_server) { - Net_TCPSocketBackend.shutdown(socket, SHUT_RDWR); + // Net_TCPSocketBackend.shutdown(socket, SHUT_RDWR); + // Reset the connection. + if (s->connection->state.state < TCP_STATE_TIME_WAIT) + Net_TCPReset(s->connection); net_tables* iface = s->connection->nic->net_tables; Core_PushlockAcquire(&iface->tcp_connections_lock, false); diff --git a/src/oboskrnl/net/tcp.h b/src/oboskrnl/net/tcp.h index a1cd0d45..9d38cf9a 100644 --- a/src/oboskrnl/net/tcp.h +++ b/src/oboskrnl/net/tcp.h @@ -226,6 +226,7 @@ void Net_TCPCancelAllOutstandingSegments(tcp_connection* con); void Net_TCPChangeConnectionState(tcp_connection* con, int state); void Net_TCPPushReceivedData(tcp_connection* con, const void* buffer, size_t size, size_t *nPushed); void Net_TCPPushDataToRemote(tcp_connection* con, const void* buffer, size_t size, bool oob); +void Net_TCPReset(tcp_connection* con); static inline int tcp_connection_cmp(tcp_connection* lhs, tcp_connection* rhs) { From d5f60fb4cec0d325ae83e0a8383c32b41505d3f5 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Wed, 26 Nov 2025 18:08:20 -0500 Subject: [PATCH 38/96] drv: Fix bug in Drv_LoadDriver --- src/oboskrnl/driver_interface/loader.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/oboskrnl/driver_interface/loader.c b/src/oboskrnl/driver_interface/loader.c index 96e23551..957cfc65 100644 --- a/src/oboskrnl/driver_interface/loader.c +++ b/src/oboskrnl/driver_interface/loader.c @@ -308,6 +308,7 @@ OBOS_NO_UBSAN driver_id *Drv_LoadDriver(const void* file_, size_t szFile, obos_s OBOS_Log("%s: Loaded driver '%s' at 0x%p.\n", __func__, driver->header.driverName, driver->base); else OBOS_Log("%s: Loaded driver at 0x%p.\n", __func__, driver->header.driverName, driver->base); + driver->refCnt++; return driver; } From d4f9390b5e7090f3ac9e9e1cb312fad52be95bcd Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Wed, 26 Nov 2025 19:25:13 -0500 Subject: [PATCH 39/96] net: Fix bug --- src/oboskrnl/net/tcp.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/oboskrnl/net/tcp.c b/src/oboskrnl/net/tcp.c index 97b086e9..92bcc48b 100644 --- a/src/oboskrnl/net/tcp.c +++ b/src/oboskrnl/net/tcp.c @@ -297,12 +297,7 @@ PacketProcessSignature(TCP, ip_header*) resp.seq = be32_to_host(hdr->ack); else { - // TODO: Is this check valid? -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ uint8_t header_length = (hdr->data_offset >> 4) * 4; -#else - uint8_t header_length = (hdr->data_offset & 0xf) * 4; -#endif uint32_t segment_length = be16_to_host(ip_hdr->packet_length)-IPv4_GET_HEADER_LENGTH(ip_hdr) - header_length; resp.seq = 0; resp.ack = be32_to_host(hdr->seq)+segment_length+1; From 4d88c4e29f6b89e0c5fd0c935361daec853feb0e Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Thu, 27 Nov 2025 18:21:43 -0500 Subject: [PATCH 40/96] net/lo: Fix bug --- src/oboskrnl/net/lo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/oboskrnl/net/lo.c b/src/oboskrnl/net/lo.c index 4ee2288d..421134b8 100644 --- a/src/oboskrnl/net/lo.c +++ b/src/oboskrnl/net/lo.c @@ -138,6 +138,7 @@ static obos_status finalize_irp(void* req_) memcpy(pckt->buffer, req->cbuff, req->blkCount); pckt->refs = hnd->dev->refs; pckt->size = req->blkCount; + // printf("LO: TX Packet (size: %d)\n", pckt->size); Core_MutexAcquire(&hnd->dev->lock); LIST_APPEND(lo_packet_queue, &hnd->dev->recv, pckt); @@ -165,6 +166,7 @@ static obos_status ioctl(dev_desc what, uint32_t request, void* argp) switch (request) { case IOCTL_IFACE_MAC_REQUEST: memzero(argp, sizeof(mac_address)); + ((uint8_t*)argp)[0] |= BIT(1); return OBOS_STATUS_SUCCESS; default: return Net_InterfaceIoctl(Net_LoopbackDevice, request, argp); From bdc0ffae754c7e9e10614a9a5533c7b89362e87c Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Thu, 27 Nov 2025 18:22:05 -0500 Subject: [PATCH 41/96] sys: Return ENOSYS from pselect if except_set is non-zero --- src/oboskrnl/vfs/fd_sys.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/oboskrnl/vfs/fd_sys.c b/src/oboskrnl/vfs/fd_sys.c index 6285d804..0301cd66 100644 --- a/src/oboskrnl/vfs/fd_sys.c +++ b/src/oboskrnl/vfs/fd_sys.c @@ -1392,7 +1392,9 @@ obos_status Sys_PSelect(size_t nFds, uint8_t* uread_set, uint8_t *uwrite_set, ui if (!uread_set && !uwrite_set && !uexcept_set) return OBOS_STATUS_SUCCESS; // We waited for nothing, so assume success. OBOS_UNUSED(uexcept_set && "We can't really monitor exceptional cases..."); - + if (uexcept_set) + return OBOS_STATUS_UNIMPLEMENTED; + uint8_t *read_set = Mm_MapViewOfUserMemory(CoreS_GetCPULocalPtr()->currentContext, uread_set, nullptr, 128, 0, true, &status); if (obos_is_error(status) && uread_set) return status; From eedb2a8dd2c96581448e2b04ad2fab42df6be43d Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Thu, 27 Nov 2025 18:37:32 -0500 Subject: [PATCH 42/96] libps2: Fix bug --- src/drivers/generic/libps2/keyboard.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/drivers/generic/libps2/keyboard.c b/src/drivers/generic/libps2/keyboard.c index 8b0afb32..cef6ad7b 100644 --- a/src/drivers/generic/libps2/keyboard.c +++ b/src/drivers/generic/libps2/keyboard.c @@ -284,10 +284,9 @@ OBOS_PAGEABLE_FUNCTION void PS2_InitializeKeyboard(ps2_port* port) // 'true' is not an error, see PS2_StartKeyboard port->suppress_irqs = true; - - data->set = set; + data->input.e = EVENT_INITIALIZE(EVENT_NOTIFICATION); port->data_ready_event = &data->input.e; port->read_code = read_code; port->make_handle = make_handle; From b4f556189e08fef70bdd70b07417b6f546176292 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Thu, 27 Nov 2025 18:38:24 -0500 Subject: [PATCH 43/96] net: Fix bug in tcp --- src/oboskrnl/net/tcp.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/oboskrnl/net/tcp.c b/src/oboskrnl/net/tcp.c index 92bcc48b..3f1b651b 100644 --- a/src/oboskrnl/net/tcp.c +++ b/src/oboskrnl/net/tcp.c @@ -119,7 +119,7 @@ obos_status NetH_SendTCPSegment(vnode* nic, tcp_connection* con, void* ent_ /* i hdr->chksum = tcp_chksum(&ip_psuedo_header, sizeof(ip_psuedo_header), hdr, sz); hdr->chksum = be16_to_host(hdr->chksum); - // OBOS_Debug("tcp tx segment: hdr->flags=0x%x, hdr->ack=0x%x, hdr->seq=0x%x\n", hdr->flags, be32_to_host(hdr->ack), be32_to_host(hdr->seq)); + //printf("tcp tx segment (%d->%d): hdr->flags=0x%x, hdr->ack=0x%x, hdr->seq=0x%x\n", be16_to_host(hdr->src_port), be16_to_host(hdr->dest_port), hdr->flags, be32_to_host(hdr->ack), be32_to_host(hdr->seq)); // NOTE: Keep the list locked until we append the unacked segment // since if we get an ACK immediately (this includes if we get preempted!), @@ -271,20 +271,25 @@ PacketProcessSignature(TCP, ip_header*) .addr=ip_hdr->dest_address, .port=be16_to_host(hdr->dest_port), }, - .is_client = true, + .is_client = false, }; - Core_PushlockAcquire(&nic->net_tables->tcp_connections_lock, true); - tcp_connection* con = RB_FIND(tcp_connection_tree, &nic->net_tables->tcp_outgoing_connections, &conn_key); - Core_PushlockRelease(&nic->net_tables->tcp_connections_lock, true); - + tcp_connection* con = nullptr; + if (port) { Core_PushlockAcquire(&port->connection_tree_lock, true); - conn_key.is_client = false; con = RB_FIND(tcp_connection_tree, &port->connections, &conn_key); Core_PushlockRelease(&port->connection_tree_lock, true); } + if (!con) + { + Core_PushlockAcquire(&nic->net_tables->tcp_connections_lock, true); + conn_key.is_client = true; + con = RB_FIND(tcp_connection_tree, &nic->net_tables->tcp_outgoing_connections, &conn_key); + Core_PushlockRelease(&nic->net_tables->tcp_connections_lock, true); + } + if ((!con || con->state.state == TCP_STATE_CLOSED) && !port) { @@ -473,8 +478,8 @@ PacketProcessSignature(TCP, ip_header*) { // This is UNACCEPTABLE! // (pun intended) - // OBOS_Debug("received unacceptable segment! discarding\n"); - // OBOS_Debug("NOTE: PCKT.SEQ=%d, PCKT.ACK=%d, RCV.NXT=%d, RCV.WND=%d, PCKT.LEN=%d\n", + //printf("received unacceptable segment! discarding\n"); + //printf("NOTE: PCKT.SEQ=%d, PCKT.ACK=%d, RCV.NXT=%d, RCV.WND=%d, PCKT.LEN=%d\n", // be32_to_host(hdr->seq)-con->state.rcv.irs, be32_to_host(hdr->ack)-con->state.snd.iss, // con->state.rcv.nxt, con->state.rcv.wnd, segment_length // ); @@ -636,8 +641,8 @@ PacketProcessSignature(TCP, ip_header*) size_t nPushed = 0; Net_TCPPushReceivedData(con, segment_data, segment_length, &nPushed); con->state.rcv.nxt += nPushed; - // OBOS_Debug("TCP window (%d, %d) receive window %d->%d\n", con->dest.port, con->src.port, con->state.rcv.wnd, con->state.rcv.wnd-nPushed); - // OBOS_Debug("TCP: Expecting SEQ=%d next (current SEQ=%d)\n", con->state.rcv.nxt-con->state.rcv.irs, be32_to_host(hdr->seq) - con->state.rcv.irs); + //printf("TCP window (%d, %d) receive window %d->%d\n", con->dest.port, con->src.port, con->state.rcv.wnd, con->state.rcv.wnd-nPushed); + //printf("TCP: Expecting SEQ=%d next (current SEQ=%d)\n", con->state.rcv.nxt-con->state.rcv.irs, be32_to_host(hdr->seq) - con->state.rcv.irs); con->state.rcv.wnd -= nPushed; struct tcp_pseudo_hdr resp = {}; resp.src_port = be16_to_host(hdr->dest_port); @@ -759,7 +764,7 @@ void Net_TCPChangeConnectionState(tcp_connection* con, int state) { if (state > TCP_STATE_CLOSED || state < TCP_STATE_INVALID) return; - // OBOS_Debug("TCP: Changing from %s to %s\n", con->state.state[state_strs], state[state_strs]); + //printf("TCP: Changing from %s to %s\n", con->state.state[state_strs], state[state_strs]); con->state.state = state; Core_EventPulse(&con->state.state_change_event, false); if (state == TCP_STATE_ESTABLISHED) @@ -806,7 +811,7 @@ bool Net_TCPRemoteACKedSegment(tcp_connection* con, uint32_t ack) nBytesACKed -= seg->nBytesUnACKed; con->state.snd.una += seg->nBytesUnACKed; seg->nBytesUnACKed = 0; - // OBOS_Debug("remote acked packet flags=0x%x remote acked 0x%p seg.seq=0x%p\n", seg->segment.flags, ack - con->state.snd.iss, seg->segment.seq - con->state.snd.iss); + //printf("remote acked packet flags=0x%x remote acked 0x%p seg.seq=0x%p\n", seg->segment.flags, ack - con->state.snd.iss, seg->segment.seq - con->state.snd.iss); } else { @@ -998,7 +1003,7 @@ void Net_TCPReset(tcp_connection* con) { struct tcp_pseudo_hdr hdr = {}; hdr.ack = con->state.rcv.nxt; - hdr.seq = ++con->state.snd.nxt; + hdr.seq = con->state.snd.nxt; hdr.flags = TCP_RST; hdr.src_port = con->src.port; hdr.dest_port = con->dest.port; @@ -1522,7 +1527,7 @@ static void irp_on_event_set(irp* req) return; // if (req->socket_flags) - // OBOS_Debug("TCP: Recv got 0x%p for flags\n", req->socket_flags); + //printf("TCP: Recv got 0x%p for flags\n", req->socket_flags); Core_MutexAcquire(&s->connection->recv_buffer.lock); @@ -1531,8 +1536,8 @@ static void irp_on_event_set(irp* req) if (~req->socket_flags & MSG_PEEK) { s->connection->recv_buffer.in_ptr += read_size; - // OBOS_Debug("TCP: Read %d bytes\n", read_size); - // OBOS_Debug("TCP window (%d, %d) receive window %d->%d\n", s->connection->dest.port, s->connection->src.port, s->connection->state.rcv.wnd, s->connection->state.rcv.wnd+read_size); + //printf("TCP: Read %d bytes\n", read_size); + //printf("TCP window (%d, %d) receive window %d->%d\n", s->connection->dest.port, s->connection->src.port, s->connection->state.rcv.wnd, s->connection->state.rcv.wnd+read_size); s->connection->state.rcv.wnd += read_size; OBOS_ENSURE(s->connection->recv_buffer.in_ptr <= s->connection->recv_buffer.ptr); if (s->connection->recv_buffer.in_ptr == s->connection->recv_buffer.ptr) From e7dd98f745bbe7aa03ab7320a478d445b6d2d65a Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Thu, 27 Nov 2025 19:08:29 -0500 Subject: [PATCH 44/96] mm: Stop indirect use of Mm_Allocator --- src/drivers/generic/ahci/interface.c | 8 +++---- src/oboskrnl/init_proc.c | 2 +- src/oboskrnl/mm/aging.c | 6 ++--- src/oboskrnl/mm/alloc.c | 36 ++++++++++++++-------------- src/oboskrnl/mm/context.c | 8 +++---- src/oboskrnl/mm/fork.c | 2 +- src/oboskrnl/mm/handler.c | 12 +++++----- src/oboskrnl/mm/mm_sys.c | 2 +- src/oboskrnl/mm/swap.c | 2 +- src/oboskrnl/scheduler/process.c | 2 +- src/oboskrnl/syscall.c | 2 +- 11 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/drivers/generic/ahci/interface.c b/src/drivers/generic/ahci/interface.c index d94035e8..7db59399 100644 --- a/src/drivers/generic/ahci/interface.c +++ b/src/drivers/generic/ahci/interface.c @@ -64,7 +64,7 @@ static obos_status populate_physical_regions(uintptr_t base, size_t size, struct base &= ~1; const size_t MAX_PRDT_COUNT = sizeof(((HBA_CMD_TBL*)nullptr))->prdt_entry/sizeof(HBA_PRDT_ENTRY); /* - data->phys_regions = Mm_Allocator->Reallocate(Mm_Allocator, data->phys_regions, ++data->physRegionCount*sizeof(struct ahci_phys_region), nullptr); + data->phys_regions = Reallocate(Mm_Allocator, data->phys_regions, ++data->physRegionCount*sizeof(struct ahci_phys_region), nullptr); struct ahci_phys_region* reg = &data->phys_regions[data->physRegionCount - 1]; */ long bytesLeft = size; @@ -98,7 +98,7 @@ static obos_status populate_physical_regions(uintptr_t base, size_t size, struct if (addr != base) { size_t old_sz = data->physRegionCount*sizeof(struct ahci_phys_region); - data->phys_regions = Mm_Allocator->Reallocate(Mm_Allocator, data->phys_regions, ++data->physRegionCount*sizeof(struct ahci_phys_region), old_sz, nullptr); + data->phys_regions = Reallocate(Mm_Allocator, data->phys_regions, ++data->physRegionCount*sizeof(struct ahci_phys_region), old_sz, nullptr); struct ahci_phys_region* reg = &data->phys_regions[data->physRegionCount - 1]; *reg = curr; wroteback = true; @@ -121,7 +121,7 @@ static obos_status populate_physical_regions(uintptr_t base, size_t size, struct if (!wroteback && curr.phys) { size_t old_sz = data->physRegionCount*sizeof(struct ahci_phys_region); - data->phys_regions = Mm_Allocator->Reallocate(Mm_Allocator, data->phys_regions, ++data->physRegionCount*sizeof(struct ahci_phys_region), old_sz, nullptr); + data->phys_regions = Reallocate(Mm_Allocator, data->phys_regions, ++data->physRegionCount*sizeof(struct ahci_phys_region), old_sz, nullptr); struct ahci_phys_region* reg = &data->phys_regions[data->physRegionCount - 1]; *reg = curr; } @@ -150,7 +150,7 @@ static obos_status unpopulate_physical_regions(uintptr_t base, size_t size, stru MmH_DerefPage(pg); pgSize = info.prot.huge_page ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE; } - Mm_Allocator->Free(Mm_Allocator, data->phys_regions, data->physRegionCount*sizeof(struct ahci_phys_region)); + Free(Mm_Allocator, data->phys_regions, data->physRegionCount*sizeof(struct ahci_phys_region)); return OBOS_STATUS_SUCCESS; } // #pragma GCC pop_options diff --git a/src/oboskrnl/init_proc.c b/src/oboskrnl/init_proc.c index 2ec81d50..b2d1db5a 100644 --- a/src/oboskrnl/init_proc.c +++ b/src/oboskrnl/init_proc.c @@ -61,7 +61,7 @@ void OBOS_LoadInit() if (obos_is_error(status)) OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "Could not open %s. Status: %d\n", init_path, status); - context* new_ctx = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(context), nullptr); + context* new_ctx = ZeroAllocate(Mm_Allocator, 1, sizeof(context), nullptr); Mm_ConstructContext(new_ctx); process* new = Core_ProcessAllocate(nullptr); new->ctx = new_ctx; diff --git a/src/oboskrnl/mm/aging.c b/src/oboskrnl/mm/aging.c index c483d757..decdb72b 100644 --- a/src/oboskrnl/mm/aging.c +++ b/src/oboskrnl/mm/aging.c @@ -67,7 +67,7 @@ obos_status Mm_AgingPRA(context* ctx) if (ent->free) { MmH_RemovePageFromWorkingset(ctx, node_save); - Mm_Allocator->Free(Mm_Allocator, ent, sizeof(*ent)); + Free(Mm_Allocator, ent, sizeof(*ent)); continue; } page_info info = {}; @@ -91,8 +91,8 @@ obos_status Mm_AgingPRA(context* ctx) REMOVE_WORKINGSET_PAGE_NODE(ctx->referenced, node); if (ent->free) { - Mm_Allocator->Free(Mm_Allocator, node, sizeof(*node)); - Mm_Allocator->Free(Mm_Allocator, ent, sizeof(*ent)); + Free(Mm_Allocator, node, sizeof(*node)); + Free(Mm_Allocator, ent, sizeof(*ent)); continue; } ent->age <<= 1; diff --git a/src/oboskrnl/mm/alloc.c b/src/oboskrnl/mm/alloc.c index e33fecaa..a33ecb1d 100644 --- a/src/oboskrnl/mm/alloc.c +++ b/src/oboskrnl/mm/alloc.c @@ -289,7 +289,7 @@ void* Mm_VirtualMemoryAllocEx(context* ctx, void* base_, size_t size, prot_flags if (!rng) { - rng = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); + rng = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); present = rng->prot.present = !(flags & VMA_FLAGS_RESERVE); rng->prot.huge_page = flags & VMA_FLAGS_HUGE_PAGE; @@ -493,8 +493,8 @@ obos_status Mm_VirtualMemoryFree(context* ctx, void* base_, size_t size) return OBOS_STATUS_INVALID_ARGUMENT; } // We need two ranges, one for the range behind base, and another for the range after. - page_range* before = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); - page_range* after = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); + page_range* before = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); + page_range* after = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); memcpy(before, rng, sizeof(*before)); memcpy(after, rng, sizeof(*before)); before->size = base-before->virt; @@ -510,7 +510,7 @@ obos_status Mm_VirtualMemoryFree(context* ctx, void* base_, size_t size) if (curr->data->info.virt >= before->virt && curr->data->info.virt < after->virt) { curr->data->free = true; // mark for deletion. - Mm_Allocator->Free(Mm_Allocator, curr, sizeof(*curr)); + Free(Mm_Allocator, curr, sizeof(*curr)); curr = next; continue; } @@ -532,7 +532,7 @@ obos_status Mm_VirtualMemoryFree(context* ctx, void* base_, size_t size) RB_INSERT(page_tree, &ctx->pages, before); RB_INSERT(page_tree, &ctx->pages, after); rng->ctx = nullptr; - Mm_Allocator->Free(Mm_Allocator, rng, sizeof(*rng)); + Free(Mm_Allocator, rng, sizeof(*rng)); rng = nullptr; } else if (rng->virt == base || rng->size == size) @@ -547,7 +547,7 @@ obos_status Mm_VirtualMemoryFree(context* ctx, void* base_, size_t size) { REMOVE_WORKINGSET_PAGE_NODE(rng->working_set_nodes, &curr->data->pr_node); curr->data->free = true; - Mm_Allocator->Free(Mm_Allocator, curr, sizeof(*curr)); + Free(Mm_Allocator, curr, sizeof(*curr)); } curr = next; } @@ -615,11 +615,11 @@ obos_status Mm_VirtualMemoryFree(context* ctx, void* base_, size_t size) // working_set_node* next = curr->next; // REMOVE_WORKINGSET_PAGE_NODE(rng->working_set_nodes, &curr->data->pr_node); // curr->data->free = true; - // Mm_Allocator->Free(Mm_Allocator, curr, sizeof(*curr)); + // Free(Mm_Allocator, curr, sizeof(*curr)); // curr = next; // } RB_REMOVE(page_tree, &ctx->pages, rng); - Mm_Allocator->Free(Mm_Allocator, rng, sizeof(*rng)); + Free(Mm_Allocator, rng, sizeof(*rng)); } Core_SpinlockRelease(&ctx->lock, oldIrql); @@ -690,9 +690,9 @@ obos_status Mm_VirtualMemoryProtect(context* ctx, void* base_, size_t size, prot return OBOS_STATUS_INVALID_ARGUMENT; } // We need three ranges, one for the range behind base, another for the range after, and another for the new protection flags. - page_range* before = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); - page_range* after = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); - page_range* new = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); + page_range* before = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); + page_range* after = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); + page_range* new = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); memcpy(new, rng, sizeof(*rng)); memcpy(before, rng, sizeof(*rng)); memcpy(after, rng, sizeof(*rng)); @@ -747,16 +747,16 @@ obos_status Mm_VirtualMemoryProtect(context* ctx, void* base_, size_t size, prot if (before->size) RB_INSERT(page_tree, &ctx->pages, before); else - Mm_Allocator->Free(Mm_Allocator, before, sizeof(page_range)); + Free(Mm_Allocator, before, sizeof(page_range)); if (after->size) RB_INSERT(page_tree, &ctx->pages, after); else - Mm_Allocator->Free(Mm_Allocator, after, sizeof(page_range)); + Free(Mm_Allocator, after, sizeof(page_range)); if (new->size) RB_INSERT(page_tree, &ctx->pages, new); else - Mm_Allocator->Free(Mm_Allocator, before, sizeof(page_range)); - Mm_Allocator->Free(Mm_Allocator, rng, sizeof(*rng)); + Free(Mm_Allocator, before, sizeof(page_range)); + Free(Mm_Allocator, rng, sizeof(*rng)); rng = new; } else if (rng->virt == base || rng->size == size) @@ -767,7 +767,7 @@ obos_status Mm_VirtualMemoryProtect(context* ctx, void* base_, size_t size, prot // "0x%p-0x%p\n", // rng->virt, rng->virt+rng->size // ); - page_range* new = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); + page_range* new = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); memcpy(new, rng, sizeof(*rng)); new->size = size; rng->size = (rng->size-size); @@ -870,7 +870,7 @@ void* Mm_MapViewOfUserMemory(context* const user_context, void* ubase_, void* kb } } - page_range* rng = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); + page_range* rng = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); rng->virt = kbase; rng->ctx = &Mm_KernelContext; rng->phys32 = false; @@ -993,7 +993,7 @@ void* Mm_QuickVMAllocate(size_t sz, bool non_pageable) uintptr_t base = (uintptr_t)blk; - page_range* rng = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); + page_range* rng = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); rng->ctx = ctx; rng->size = sz; rng->virt = base; diff --git a/src/oboskrnl/mm/context.c b/src/oboskrnl/mm/context.c index d5f21146..99212fdb 100644 --- a/src/oboskrnl/mm/context.c +++ b/src/oboskrnl/mm/context.c @@ -107,7 +107,7 @@ page* MmH_AllocatePage(uintptr_t phys, bool huge) { if (!phys) return nullptr; - page* buf = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page), nullptr); + page* buf = ZeroAllocate(Mm_Allocator, 1, sizeof(page), nullptr); buf->phys = phys; if (huge) buf->flags |= PHYS_PAGE_HUGE_PAGE; @@ -154,7 +154,7 @@ void MmH_DerefPage(page* buf) } } Mm_PhysicalMemoryUsage -= ((buf->flags & PHYS_PAGE_HUGE_PAGE) ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE); - Mm_Allocator->Free(Mm_Allocator, buf, sizeof(*buf)); + Free(Mm_Allocator, buf, sizeof(*buf)); } } memstat Mm_GlobalMemoryUsage; @@ -173,7 +173,7 @@ OBOS_NODISCARD swap_allocation* MmH_LookupSwapAllocation(uintptr_t id) } swap_allocation* MmH_AddSwapAllocation(uintptr_t id) { - swap_allocation* new = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(swap_allocation), nullptr); + swap_allocation* new = ZeroAllocate(Mm_Allocator, 1, sizeof(swap_allocation), nullptr); new->id = id; new->provider = Mm_SwapProvider; new->refs = 0; @@ -198,7 +198,7 @@ void MmH_DerefSwapAllocation(swap_allocation* alloc) if (alloc->provider->free_obj) alloc->provider->free_obj(alloc->provider); } - Mm_Allocator->Free(Mm_Allocator, alloc, sizeof(*alloc)); + Free(Mm_Allocator, alloc, sizeof(*alloc)); } } LIST_GENERATE(swap_allocation_list, struct swap_allocation, node); diff --git a/src/oboskrnl/mm/fork.c b/src/oboskrnl/mm/fork.c index f75243b9..d861c55d 100644 --- a/src/oboskrnl/mm/fork.c +++ b/src/oboskrnl/mm/fork.c @@ -50,7 +50,7 @@ obos_status Mm_ForkContext(context* into, context* toFork) * Map both page ranges as Sym CoW * Go to the next range */ - page_range* clone = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); + page_range* clone = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr); memcpy(clone, curr, sizeof(*curr)); clone->ctx = into; memzero(&clone->rb_node, sizeof(clone->rb_node)); diff --git a/src/oboskrnl/mm/handler.c b/src/oboskrnl/mm/handler.c index 21dc286e..6a6f5fbb 100644 --- a/src/oboskrnl/mm/handler.c +++ b/src/oboskrnl/mm/handler.c @@ -110,14 +110,14 @@ static obos_status ref_page(context* ctx, const page_info *curr) bool allocated_ent = false; if (!ent) { - ent = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(working_set_entry), nullptr); + ent = ZeroAllocate(Mm_Allocator, 1, sizeof(working_set_entry), nullptr); ent->info.virt = curr->virt; ent->info.prot = curr->prot; ent->info.range = rng; allocated_ent = true; } ent->refs++; - working_set_node* node = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(working_set_node), nullptr); + working_set_node* node = ZeroAllocate(Mm_Allocator, 1, sizeof(working_set_node), nullptr); node->data = ent; #if defined(OBOS_PAGE_REPLACEMENT_AGING) status = Mm_AgingReferencePage(ctx, node); @@ -126,9 +126,9 @@ static obos_status ref_page(context* ctx, const page_info *curr) #endif if (obos_is_error(status)) { - Mm_Allocator->Free(Mm_Allocator, node, sizeof(*node)); + Free(Mm_Allocator, node, sizeof(*node)); if (allocated_ent) - Mm_Allocator->Free(Mm_Allocator, ent, sizeof(*ent)); + Free(Mm_Allocator, ent, sizeof(*ent)); return status; } APPEND_WORKINGSET_PAGE_NODE(ctx->referenced, node); @@ -336,7 +336,7 @@ void MmH_RemovePageFromWorkingset(context* ctx, working_set_node* node) } if (!ent->free) REMOVE_WORKINGSET_PAGE_NODE(ent->info.range->working_set_nodes, &ent->pr_node); - Mm_Allocator->Free(Mm_Allocator, ent, sizeof(*ent)); + Free(Mm_Allocator, ent, sizeof(*ent)); } - Mm_Allocator->Free(Mm_Allocator, node, sizeof(*node)); + Free(Mm_Allocator, node, sizeof(*node)); } diff --git a/src/oboskrnl/mm/mm_sys.c b/src/oboskrnl/mm/mm_sys.c index f1adf076..df4b6d0b 100644 --- a/src/oboskrnl/mm/mm_sys.c +++ b/src/oboskrnl/mm/mm_sys.c @@ -116,7 +116,7 @@ handle Sys_MakeNewContext(size_t ws_capacity) ws_capacity = OBOS_DEFAULT_WS_CAPACITY; if (ws_capacity % OBOS_HUGE_PAGE_SIZE) ws_capacity += (OBOS_HUGE_PAGE_SIZE-(ws_capacity%OBOS_HUGE_PAGE_SIZE)); - context* ctx = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(context), nullptr); + context* ctx = ZeroAllocate(Mm_Allocator, 1, sizeof(context), nullptr); Mm_ConstructContext(ctx); ctx->workingSet.capacity = ws_capacity; OBOS_LockHandleTable(OBOS_CurrentHandleTable()); diff --git a/src/oboskrnl/mm/swap.c b/src/oboskrnl/mm/swap.c index a9a16cdf..7ad49510 100644 --- a/src/oboskrnl/mm/swap.c +++ b/src/oboskrnl/mm/swap.c @@ -107,7 +107,7 @@ obos_status Mm_SwapIn(page_info* page, fault_type* type) node->pagedCount++; page->prot.present = true; obos_status status = MmS_SetPageMapping(page->range->ctx->pt, page, node->phys, false); - // Mm_Allocator->Free(Mm_Allocator, node, sizeof(*node)); + // Free(Mm_Allocator, node, sizeof(*node)); if (obos_expect(obos_is_error(status), false)) { // Unlikely error. diff --git a/src/oboskrnl/scheduler/process.c b/src/oboskrnl/scheduler/process.c index 89ddf881..acdc09af 100644 --- a/src/oboskrnl/scheduler/process.c +++ b/src/oboskrnl/scheduler/process.c @@ -225,7 +225,7 @@ uintptr_t ExitCurrentProcess(uintptr_t unused) } MmS_FreePageTable(proc->ctx->pt); - Mm_Allocator->Free(Mm_Allocator, proc->ctx, sizeof(context)); + Free(Mm_Allocator, proc->ctx, sizeof(context)); thread* ready = nullptr; thread* running = nullptr; diff --git a/src/oboskrnl/syscall.c b/src/oboskrnl/syscall.c index aeb2186a..a990fc6d 100644 --- a/src/oboskrnl/syscall.c +++ b/src/oboskrnl/syscall.c @@ -89,7 +89,7 @@ void Sys_LibCLog(const char* ustr) static handle Sys_MmFork() { // Zeroed in Mm_ConstructContext - context* ctx = Mm_Allocator->Allocate(Mm_Allocator, sizeof(context), nullptr); + context* ctx = Allocate(Mm_Allocator, sizeof(context), nullptr); Mm_ConstructContext(ctx); Mm_ForkContext(ctx, Core_GetCurrentThread()->proc->ctx); ctx->workingSet.capacity = Core_GetCurrentThread()->proc->ctx->workingSet.capacity; From 754918b50f8b8137137417f7124fbf618da5e397 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Thu, 27 Nov 2025 19:21:19 -0500 Subject: [PATCH 45/96] misc: Cleanup limine.conf --- config/limine.conf | 3 --- 1 file changed, 3 deletions(-) diff --git a/config/limine.conf b/config/limine.conf index 5ebd6a2d..79f32363 100644 --- a/config/limine.conf +++ b/config/limine.conf @@ -1,9 +1,6 @@ -# Timeout in seconds that Limine will use before automatically booting. timeout: 5 -# The entry name that will be displayed in the boot menu. /OBOS - # We use the Limine boot protocol. protocol: limine comment: OBOS From d3a144d2d89e7f564fb34cebd5518ade8d9b891f Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Thu, 27 Nov 2025 19:21:30 -0500 Subject: [PATCH 46/96] core: Optimize spinlocks --- src/oboskrnl/locks/spinlock.c | 74 ++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/src/oboskrnl/locks/spinlock.c b/src/oboskrnl/locks/spinlock.c index a2ff6833..afe8e4a2 100644 --- a/src/oboskrnl/locks/spinlock.c +++ b/src/oboskrnl/locks/spinlock.c @@ -1,7 +1,7 @@ /* - oboskrnl/locks/spinlock.c + oboskrnl/locks/spinlock.c - Copyright (c) 2024-2025 Omar Berrow + Copyright (c) 2024-2025 Omar Berrow */ #include @@ -20,76 +20,78 @@ static uint64_t nanoseconds_since_boot() { #if !OBOS_ENABLE_LOCK_PROFILING - return 0; + return 0; #else - if (!CoreS_GetNativeTimerFrequency()) - return 0; - return CoreH_TickToNS(CoreS_GetNativeTimerTick(), true); + if (!CoreS_GetNativeTimerFrequency()) + return 0; + return CoreH_TickToNS(CoreS_GetNativeTimerTick(), true); #endif } __attribute__((no_instrument_function)) OBOS_NO_UBSAN irql Core_SpinlockAcquireExplicit(spinlock* const lock, irql minIrql, bool irqlNthrVariant) { - // IRQL_INVALID is used to specify not to raise the irql at all - // this way, LowerIrql can lock the DPC queue without breaking. - irql oldIrql = IRQL_INVALID; - if (Core_GetIrql() < minIrql) - oldIrql = Core_RaiseIrqlNoThread(minIrql); - if (!atomic_flag_test_and_set_explicit(&lock->val, memory_order_acq_rel)) + // IRQL_INVALID is used to specify not to raise the irql at all + // this way, LowerIrql can lock the DPC queue without breaking. + irql oldIrql = IRQL_INVALID; + if (obos_expect(Core_GetIrql() < minIrql, false)) + oldIrql = Core_RaiseIrqlNoThread(minIrql); + if (!atomic_flag_test_and_set_explicit(&lock->val, memory_order_acq_rel)) goto done_wait; while (atomic_flag_test_and_set_explicit(&lock->val, memory_order_acq_rel)) - OBOSS_SpinlockHint(); + OBOSS_SpinlockHint(); done_wait: - lock->locked = true; - return oldIrql; + lock->locked = true; + return oldIrql; } __attribute__((no_instrument_function)) OBOS_NO_UBSAN irql Core_SpinlockAcquire(spinlock* const lock) { irql oldIrql = IRQL_INVALID; - if (Core_GetIrql() < IRQL_DISPATCH) + if (obos_expect(Core_GetIrql() < IRQL_DISPATCH, false)) oldIrql = Core_RaiseIrqlNoThread(IRQL_DISPATCH); if (!atomic_flag_test_and_set_explicit(&lock->val, memory_order_acq_rel)) goto locked; - while (atomic_flag_test_and_set_explicit(&lock->val, memory_order_acq_rel)) - OBOSS_SpinlockHint(); + while (atomic_flag_test_and_set_explicit(&lock->val, memory_order_acq_rel)) + OBOSS_SpinlockHint(); locked: - lock->locked = true; + lock->locked = true; #if OBOS_ENABLE_LOCK_PROFILING - lock->lastLockTimeNS = nanoseconds_since_boot(); + lock->lastLockTimeNS = nanoseconds_since_boot(); #endif - return oldIrql; + return oldIrql; } __attribute__((no_instrument_function)) OBOS_NO_UBSAN obos_status Core_SpinlockRelease(spinlock* const lock, irql oldIrql) { - if (oldIrql & 0xf0 && oldIrql != IRQL_INVALID) - { - OBOS_ASSERT(!"funny stuff"); - return OBOS_STATUS_INVALID_IRQL; - } - atomic_flag_clear_explicit(&lock->val, memory_order_relaxed); - lock->locked = false; - Core_LowerIrqlNoThread(oldIrql); +#if OBOS_DEBUG + if (oldIrql & 0xf0 && oldIrql != IRQL_INVALID) + { + OBOS_ASSERT(!"funny stuff"); + return OBOS_STATUS_INVALID_IRQL; + } +#endif + atomic_flag_clear_explicit(&lock->val, memory_order_relaxed); + lock->locked = false; + Core_LowerIrqlNoThread(oldIrql); #if OBOS_ENABLE_LOCK_PROFILING - lock->lastLockTimeNS = nanoseconds_since_boot() - lock->lastLockTimeNS; + lock->lastLockTimeNS = nanoseconds_since_boot() - lock->lastLockTimeNS; #endif - return OBOS_STATUS_SUCCESS; + return OBOS_STATUS_SUCCESS; } /* * No. OBOS_NO_UBSAN void Core_SpinlockForcedRelease(spinlock* const lock) { - atomic_flag_clear_explicit(&lock->val, memory_order_seq_cst); - lock->irqlNThrVariant = false; + atomic_flag_clear_explicit(&lock->val, memory_order_seq_cst); + lock->irqlNThrVariant = false; #ifdef OBOS_DEBUG - lock->owner = nullptr; + lock->owner = nullptr; #endif - lock->locked = false; + lock->locked = false; }*/ __attribute__((no_instrument_function)) bool Core_SpinlockAcquired(spinlock* const lock) { - return lock ? lock->locked : false; + return lock ? lock->locked : false; } From 4b39052b371006bdecb564e3d769eb6cdcda2d6e Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Thu, 27 Nov 2025 19:25:51 -0500 Subject: [PATCH 47/96] x86_64: Fix possible bug with SMP --- src/oboskrnl/arch/x86_64/smp.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/oboskrnl/arch/x86_64/smp.c b/src/oboskrnl/arch/x86_64/smp.c index 588d4122..28b1f3a6 100644 --- a/src/oboskrnl/arch/x86_64/smp.c +++ b/src/oboskrnl/arch/x86_64/smp.c @@ -185,14 +185,17 @@ void Arch_SMPStartup() Arch_SaveMTRRs(); Arch_RawRegisterInterrupt(0x2, (uintptr_t)nmiHandler); ParseMADT(); + bool up = false; #ifdef OBOS_UP OBOS_Log("Uniprocessor-build of OBOS. No other cores will be initialized.\n"); - s_nLAPICIDs = 1; + // s_nLAPICIDs = 1; + up = true; #else if (OBOS_GetOPTF("no-smp")) { OBOS_Log("Running OBOS as Uniprocessor. No other cores will be initialized.\n"); - s_nLAPICIDs = 1; + up = true; + // s_nLAPICIDs = 1; } #endif // if (s_nLAPICIDs == 1) @@ -206,7 +209,7 @@ void Arch_SMPStartup() Arch_MapPage(getCR3(), (void*)0x1000, 0x1000, 0x3, false); Arch_SMPTrampolineCR3 = getCR3(); Core_CpuInfo = cpu_info; - Core_CpuCount = s_nLAPICIDs; + Core_CpuCount = up ? 1 : s_nLAPICIDs; // irql oldIrql = Core_RaiseIrql(0xf); for (size_t i = 0; i < s_nLAPICIDs; i++) { From 7f639046277e1cdcc9c5e9c30b217f9f9ae5cdf7 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Fri, 28 Nov 2025 17:06:53 -0500 Subject: [PATCH 48/96] drv: Fix bug with PCI --- src/oboskrnl/driver_interface/pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/oboskrnl/driver_interface/pci.c b/src/oboskrnl/driver_interface/pci.c index 8e6a86cc..22407ba1 100644 --- a/src/oboskrnl/driver_interface/pci.c +++ b/src/oboskrnl/driver_interface/pci.c @@ -322,6 +322,7 @@ static void initialize_irq_resources(pci_device* dev) pci_resource* resource = ZeroAllocate(OBOS_KernelAllocator, 1, sizeof(pci_resource), nullptr); resource->type = PCI_RESOURCE_IRQ; + resource->owner = dev; resource->irq = ZeroAllocate(OBOS_KernelAllocator, 1, sizeof(pci_irq_handle), nullptr); resource->owner = dev; @@ -341,6 +342,7 @@ static void initialize_cmd_register_resource(pci_device* dev) resource->cmd_register = cmd_register & 0xffff; LIST_APPEND(pci_resource_list, &dev->resources, resource); + resource->owner = dev; dev->resource_cmd_register = resource; } From aed45fc6f156db67f218492b074d953bb2a52a07 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Fri, 28 Nov 2025 17:07:53 -0500 Subject: [PATCH 49/96] e1000: Fix bugs --- src/drivers/generic/freebsd-e1000/io.c | 33 +++++++++++++----------- src/drivers/generic/freebsd-e1000/main.c | 7 +++-- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/drivers/generic/freebsd-e1000/io.c b/src/drivers/generic/freebsd-e1000/io.c index 25b2d1d2..a3b1e90e 100644 --- a/src/drivers/generic/freebsd-e1000/io.c +++ b/src/drivers/generic/freebsd-e1000/io.c @@ -196,14 +196,6 @@ void e1000_init_tx(e1000_device* dev) { dev->tx_ring_phys_pg = MmH_PgAllocatePhysical(false, false); dev->tx_ring = dev->tx_ring_phys_pg->phys; - struct e1000_tx_desc* desc = ((struct e1000_tx_desc*)MmS_MapVirtFromPhys(dev->tx_ring)); - for (size_t i = 0; i < TX_QUEUE_SIZE; i++) - { - dev->tx_buffers[i] = Mm_AllocatePhysicalPages(TX_BUFFER_PAGES, 1, nullptr); - desc[i].buffer_addr = dev->tx_buffers[i]; - desc[i].lower.data = 0; - desc[i].upper.fields.status = E1000_TXD_STAT_DD; - } // Copied from managarm E1000_WRITE_REG(&dev->hw, E1000_TDLEN(0), TX_QUEUE_SIZE * sizeof(struct e1000_tx_desc)); @@ -211,8 +203,8 @@ void e1000_init_tx(e1000_device* dev) E1000_WRITE_REG(&dev->hw, E1000_TDBAL(0), (u32)dev->tx_ring); /* Init the HEAD/TAIL indices */ - E1000_WRITE_REG(&dev->hw, E1000_TDT(0), 0); E1000_WRITE_REG(&dev->hw, E1000_TDH(0), 0); + E1000_WRITE_REG(&dev->hw, E1000_TDT(0), 0); u32 txdctl = 0; /* clear txdctl */ txdctl |= 0x1f; /* PTHRESH */ @@ -279,7 +271,7 @@ void e1000_init_tx(e1000_device* dev) /* Program the Transmit Control Register */ u32 tctl = E1000_READ_REG(&dev->hw, E1000_TCTL); tctl &= ~E1000_TCTL_CT; - tctl |= (E1000_TCTL_RTLC | E1000_TCTL_EN | (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT)); + tctl |= (E1000_TCTL_RTLC | E1000_TCTL_EN | E1000_TCTL_PSP | (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT)); if (dev->hw.mac.type >= e1000_82571) tctl |= E1000_TCTL_MULR; @@ -299,6 +291,16 @@ void e1000_init_tx(e1000_device* dev) reg |= E1000_TARC0_CB_MULTIQ_2_REQ; E1000_WRITE_REG(&dev->hw, E1000_TARC(0), reg); } + + struct e1000_tx_desc* desc = ((struct e1000_tx_desc*)MmS_MapVirtFromPhys(dev->tx_ring)); + for (size_t i = 0; i < TX_QUEUE_SIZE; i++) + { + dev->tx_buffers[i] = Mm_AllocatePhysicalPages(TX_BUFFER_PAGES, 1, nullptr); + desc[i].buffer_addr = dev->tx_buffers[i]; + desc[i].lower.data = 0; + desc[i].upper.data = 0; + } + OBOS_ENSURE(memcmp_b(desc, 0, sizeof(*desc)*TX_QUEUE_SIZE) == false); } void e1000_tx_reap(e1000_device* dev); @@ -316,14 +318,15 @@ event* e1000_tx_packet(e1000_device* dev, const void* buffer, size_t size, bool nPages++; if (nPages > TX_BUFFER_PAGES) return nullptr; - uintptr_t buff = dev->tx_buffers[dev->tx_index]; + uintptr_t buff = dev->tx_buffers[dev->tx_index % TX_QUEUE_SIZE]; memcpy(MmS_MapVirtFromPhys(buff), buffer, size); desc->buffer_addr = buff; desc->upper.data = 0; desc->lower.data = size | E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS; + E1000_WRITE_REG(&dev->hw, E1000_TDBAH(0), (u32)(dev->tx_ring >> 32)); + E1000_WRITE_REG(&dev->hw, E1000_TDBAL(0), (u32)dev->tx_ring); E1000_WRITE_REG(&dev->hw, E1000_TDT(0), ++dev->tx_index % TX_QUEUE_SIZE); - - // printf("ret from %s, upper.data=0x%x, lower.data=0x%x, buffer=0x%p\n", __func__, desc->upper.data, desc->lower.data, desc->buffer_addr); + Core_LowerIrql(oldIrql); uintptr_t deadline = CoreS_GetTimerTick() + CoreH_TimeFrameToTick(1*1000*1000); @@ -388,10 +391,10 @@ void e1000_tx_reap(e1000_device* dev) size_t i = dev->tx_index; for (; ; ) { - if (~desc[i].upper.fields.status & E1000_TXD_STAT_DD) + if (~desc[i].upper.data & E1000_TXD_STAT_DD) break; desc[i].upper.fields.status = 0; - desc[i].lower.data = 0; + desc[i].lower.data = 0; desc[i].buffer_addr = 0; i++; } diff --git a/src/drivers/generic/freebsd-e1000/main.c b/src/drivers/generic/freebsd-e1000/main.c index 6c8e0f17..61ceaf47 100644 --- a/src/drivers/generic/freebsd-e1000/main.c +++ b/src/drivers/generic/freebsd-e1000/main.c @@ -331,7 +331,10 @@ static void search_bus(pci_bus* bus) Devices = OBOS_NonPagedPoolAllocator->Reallocate(OBOS_NonPagedPoolAllocator, Devices, nDevices*sizeof(e1000_device), (nDevices-1)*sizeof(e1000_device), nullptr); memzero(&Devices[nDevices-1], sizeof(Devices[nDevices-1])); - dev->resource_cmd_register->cmd_register |= 0x7; // io space + memspace + bus master + // for (volatile bool b = true; b;) + // OBOSS_SpinlockHint(); + + dev->resource_cmd_register->cmd_register |= 0x7; Drv_PCISetResource(dev->resource_cmd_register); Devices[nDevices-1].hw.back = &Devices[nDevices-1].osdep; @@ -419,6 +422,7 @@ static void search_bus(pci_bus* bus) dev = LIST_GET_NEXT(pci_device_list, &bus->devices, dev); continue; } + e1000_power_up_phy(&Devices[nDevices-1].hw); if (e1000_validate_nvm_checksum(&Devices[nDevices-1].hw) != E1000_SUCCESS) { @@ -440,7 +444,6 @@ static void search_bus(pci_bus* bus) // continue; // } - e1000_power_up_phy(&Devices[nDevices-1].hw); e1000_disable_ulp_lpt_lp(&Devices[nDevices-1].hw, true); Devices[nDevices-1].rx_evnt = EVENT_INITIALIZE(EVENT_NOTIFICATION); From 30efc2f1dd16ce050a8798ae893c29d0c5fea8d3 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 10:02:08 -0500 Subject: [PATCH 50/96] vfs: Fix bug with pipes --- src/oboskrnl/vfs/pipe.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/oboskrnl/vfs/pipe.c b/src/oboskrnl/vfs/pipe.c index 571a6b3d..41296a6b 100644 --- a/src/oboskrnl/vfs/pipe.c +++ b/src/oboskrnl/vfs/pipe.c @@ -159,7 +159,11 @@ static obos_status write_sync(dev_desc desc, const void* buf, size_t blkCount, s const char* write_buf = buf; obos_status status = OBOS_STATUS_SUCCESS; while ((written_count += tmp) < blkCount && obos_is_success(status)) + { + if (Core_GetCurrentThread()->signal_info && Core_GetCurrentThread()->signal_info->pending & BIT(SIGPIPE-1)) + break; status = write_sync(desc, write_buf + written_count, (blkCount - written_count) % pipe->size, 0, &tmp); + } if (nBlkWritten) *nBlkWritten = written_count; return status; From a135b7c72230d4ebca5301860e77a054afec8389 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 10:03:53 -0500 Subject: [PATCH 51/96] net: Fix TCP bug --- src/oboskrnl/net/tcp.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/oboskrnl/net/tcp.c b/src/oboskrnl/net/tcp.c index 3f1b651b..a043e1a9 100644 --- a/src/oboskrnl/net/tcp.c +++ b/src/oboskrnl/net/tcp.c @@ -5,6 +5,7 @@ */ #include "error.h" +#include "irq/irql.h" #include #include #include @@ -126,6 +127,7 @@ obos_status NetH_SendTCPSegment(vnode* nic, tcp_connection* con, void* ent_ /* i // and the TCP handler sees no unACKed segment, then this segment will be // spuriously retransmitted, which is probably bad. + irql oldIrql = Core_RaiseIrql(IRQL_DISPATCH); if (con) Core_PushlockAcquire(&con->unacked_segments.lock, false); @@ -144,13 +146,17 @@ obos_status NetH_SendTCPSegment(vnode* nic, tcp_connection* con, void* ent_ /* i if (obos_is_error(status)) { + Core_LowerIrql(oldIrql); if (con) Core_PushlockRelease(&con->unacked_segments.lock, false); return status; } if (!con) + { + Core_LowerIrql(oldIrql); return OBOS_STATUS_SUCCESS; + } tcp_unacked_segment* seg = ZeroAllocate(OBOS_KernelAllocator, 1, sizeof(tcp_unacked_segment), nullptr); OBOS_SharedPtrConstructSz(&seg->ptr, seg, sizeof(*seg)); @@ -187,6 +193,8 @@ obos_status NetH_SendTCPSegment(vnode* nic, tcp_connection* con, void* ent_ /* i Core_PushlockRelease(&con->unacked_segments.lock, false); + Core_LowerIrql(oldIrql); + return OBOS_STATUS_SUCCESS; } From ebea625c5eb89abc82cfb5499b3d87fe9c01b326 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 10:04:36 -0500 Subject: [PATCH 52/96] misc: Change qemu launch script behavior --- scripts/launch_qemu.sh | 1 - scripts/launch_qemu.tcg.sh | 1 - 2 files changed, 2 deletions(-) diff --git a/scripts/launch_qemu.sh b/scripts/launch_qemu.sh index b178d690..bfe11054 100755 --- a/scripts/launch_qemu.sh +++ b/scripts/launch_qemu.sh @@ -13,7 +13,6 @@ qemu-system-x86_64 \ -debugcon file:/dev/stdout \ -monitor stdio \ -serial tcp:0.0.0.0:1534,server,nowait \ --smp cores=1,threads=1,sockets=1 \ -d int \ -D qemu_log.txt "$@" diff --git a/scripts/launch_qemu.tcg.sh b/scripts/launch_qemu.tcg.sh index f91864ac..2635452c 100755 --- a/scripts/launch_qemu.tcg.sh +++ b/scripts/launch_qemu.tcg.sh @@ -13,7 +13,6 @@ qemu-system-x86_64 \ -debugcon file:/dev/stdout \ -monitor stdio \ -serial tcp:0.0.0.0:1534,server,nowait \ --smp cores=1,threads=1,sockets=1 \ -d int \ -D qemu_log.txt "$@" From b4ea494c547fc0b1b39c913c211474e63813612c Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 11:08:23 -0500 Subject: [PATCH 53/96] misc: Fix bug in ELF loader --- src/oboskrnl/elf/load.c | 4 +++- src/oboskrnl/execve.c | 2 +- src/oboskrnl/mm/alloc.c | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/oboskrnl/elf/load.c b/src/oboskrnl/elf/load.c index b859217d..ebc69f37 100644 --- a/src/oboskrnl/elf/load.c +++ b/src/oboskrnl/elf/load.c @@ -131,7 +131,7 @@ obos_status OBOS_LoadELF(context* ctx, const void* file, size_t szFile, elf_info uintptr_t real_limit = phdrs[i].p_vaddr+phdrs[i].p_memsz; if (real_limit % OBOS_PAGE_SIZE) real_limit += (OBOS_PAGE_SIZE-(real_limit%OBOS_PAGE_SIZE)); - // printf("ELF: Allocating 0x%p bytes (memsz=0x%p, real_base=0x%p, real_limit=0x%p, vaddr=0x%p)", real_limit-real_base, phdrs[i].p_memsz, real_base, real_limit, phdrs[i].p_vaddr); + // printf("ELF: Allocating 0x%p bytes (memsz=0x%p, real_base=0x%p, real_limit=0x%p, vaddr=0x%p)\n", real_limit-real_base, phdrs[i].p_memsz, real_base, real_limit, phdrs[i].p_vaddr); ubase = Mm_VirtualMemoryAlloc(ctx, (void*)real_base, real_limit-real_base, @@ -159,6 +159,8 @@ obos_status OBOS_LoadELF(context* ctx, const void* file, size_t szFile, elf_info real_limit += base; } + OBOS_ENSURE(phdrs[i].p_filesz <= (real_limit - real_base)); + kbase = Mm_MapViewOfUserMemory(ctx, (void*)real_base, nullptr, diff --git a/src/oboskrnl/execve.c b/src/oboskrnl/execve.c index c09fec4a..d9aac177 100644 --- a/src/oboskrnl/execve.c +++ b/src/oboskrnl/execve.c @@ -141,7 +141,7 @@ obos_status Sys_ExecVE(const char* upath, char* const* argv, char* const* envp) return status; Core_GetCurrentThread()->proc->exec_file = VfsH_DirentPath(VfsH_DirentLookup(path), nullptr); size_t szBuf = file.vn->filesize; - void* kbuf = Mm_VirtualMemoryAlloc(&Mm_KernelContext, nullptr, szBuf, 0, VMA_FLAGS_PRIVATE|VMA_FLAGS_PREFAULT, &file, nullptr); + void* kbuf = Mm_VirtualMemoryAlloc(&Mm_KernelContext, nullptr, szBuf, OBOS_PROTECTION_READ_ONLY, 0, &file, nullptr); bool set_uid = file.vn->perm.set_uid; bool set_gid = file.vn->perm.set_gid; uid target_uid = set_uid ? file.vn->owner_uid : Core_GetCurrentThread()->proc->currentUID; diff --git a/src/oboskrnl/mm/alloc.c b/src/oboskrnl/mm/alloc.c index a33ecb1d..7b65237d 100644 --- a/src/oboskrnl/mm/alloc.c +++ b/src/oboskrnl/mm/alloc.c @@ -875,6 +875,7 @@ void* Mm_MapViewOfUserMemory(context* const user_context, void* ubase_, void* kb rng->ctx = &Mm_KernelContext; rng->phys32 = false; rng->hasGuardPage = false; + rng->pageable = false; rng->size = size; rng->prot.huge_page = false; rng->prot.rw = !(prot & OBOS_PROTECTION_READ_ONLY); @@ -911,6 +912,7 @@ void* Mm_MapViewOfUserMemory(context* const user_context, void* ubase_, void* kb if (~prot & OBOS_PROTECTION_READ_ONLY) Mm_MarkAsDirtyPhys(phys); } + OBOS_ENSURE(phys); if (phys && phys->cow_type && ~prot & OBOS_PROTECTION_READ_ONLY) { @@ -936,7 +938,7 @@ void* Mm_MapViewOfUserMemory(context* const user_context, void* ubase_, void* kb info.accessed = false; info.range = rng; info.prot = rng->prot; - info.prot.present = !!phys; + info.prot.present = info.phys != 0; info.prot.rw = rng->prot.rw; OBOS_ENSURE(info.phys); MmS_SetPageMapping(Mm_KernelContext.pt, &info, info.phys, false); From 21e45c9df33b5888e68aede2d064ec041dea33b6 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 11:08:33 -0500 Subject: [PATCH 54/96] core: Add CoreH_MakeTimerEvent --- src/oboskrnl/irq/timer.c | 16 ++++++++++++++++ src/oboskrnl/irq/timer.h | 13 ++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/oboskrnl/irq/timer.c b/src/oboskrnl/irq/timer.c index 90ce66eb..ae70bf03 100644 --- a/src/oboskrnl/irq/timer.c +++ b/src/oboskrnl/irq/timer.c @@ -4,6 +4,7 @@ * Copyright (c) 2024 Omar Berrow */ +#include "locks/event.h" #include #include #include @@ -240,3 +241,18 @@ OBOS_EXPORT uint64_t CoreH_TickToNS(timer_tick tick, bool native_tick) return tick * cached_rate; } } + +static void tm_evnt_hnd(void* udata) +{ + event* evnt = udata; + Core_EventSet(evnt, false); +} + +void CoreH_MakeTimerEvent(timer** otm, uint64_t us, event* evnt, bool recurring) +{ + OBOS_ASSERT(otm); + *otm = Core_TimerObjectAllocate(nullptr); + (*otm)->handler = tm_evnt_hnd; + (*otm)->userdata = (void*)evnt; + Core_TimerObjectInitialize(*otm, recurring ? TIMER_MODE_INTERVAL : TIMER_MODE_DEADLINE, us); +} \ No newline at end of file diff --git a/src/oboskrnl/irq/timer.h b/src/oboskrnl/irq/timer.h index 8f54a8af..e1d8dd54 100644 --- a/src/oboskrnl/irq/timer.h +++ b/src/oboskrnl/irq/timer.h @@ -13,6 +13,8 @@ #include #include +#include + typedef uint64_t timer_tick; typedef uint64_t timer_frequency; @@ -111,6 +113,15 @@ OBOS_EXPORT timer_tick CoreH_TimeFrameToTick(uint64_t us); /// The tick count in nanoseconds.. OBOS_EXPORT uint64_t CoreH_TickToNS(timer_tick tick, bool native_tick); +/// +/// Starts a timer for 'us' microseconds, setting evnt when it is triggered.
+/// Useful for timeouts. +///
+/// [out] The timer object used. +/// The time period to start the timer for +/// The event to set when the timer finishes +/// Whether the timer should be an interval or deadline timer +OBOS_EXPORT void CoreH_MakeTimerEvent(timer** otm, uint64_t us, event* evnt, bool recurring); uint64_t CoreS_TimerTickToNS(timer_tick tp); @@ -122,4 +133,4 @@ uint64_t CoreS_TimerTickToNS(timer_tick tp); OBOS_WEAK obos_status CoreS_InitializeTimer(irq_handler handler); #ifdef OBOS_TIMER_IS_DEADLINE obos_status CoreS_ResetTimer(); -#endif +#endif \ No newline at end of file From c814a98da656ed862dea0b0ad250b4dfd10a66e8 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 18:57:58 -0500 Subject: [PATCH 55/96] net: Implement retransmission of ARP packets on timeout --- src/oboskrnl/net/arp.c | 61 +++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/src/oboskrnl/net/arp.c b/src/oboskrnl/net/arp.c index 29eac63a..da298bb9 100644 --- a/src/oboskrnl/net/arp.c +++ b/src/oboskrnl/net/arp.c @@ -4,6 +4,8 @@ * Copyright (c) 2025 Omar Berrow */ +#include "irq/timer.h" +#include "locks/wait.h" #include #include #include @@ -92,26 +94,61 @@ obos_status NetH_ARPRequest(vnode* nic, ip_addr addr, mac_address* out, address_ memcpy(payload->sender_mac, nic->net_tables->mac, sizeof(mac_address)); payload->target_ip = addr; memzero(payload->target_mac, sizeof(payload->target_mac)); - - shared_ptr *eth = NetH_FormatEthernetPacket(nic, MAC_BROADCAST, hdr, sz_hdr, ETHERNET2_TYPE_ARP); - status = NetH_SendEthernetPacket(nic, OBOS_SharedPtrCopy(eth)); - if (obos_is_error(status)) + + event tm_evnt = EVENT_INITIALIZE(EVENT_NOTIFICATION); + timer* tm = nullptr; + CoreH_MakeTimerEvent(&tm, 1000*1000, &tm_evnt, true); + + struct waitable_header* signaled = nullptr; + struct waitable_header* objs[2] = { + WAITABLE_OBJECT(tm_evnt), + WAITABLE_OBJECT(ent->sync) + }; + + size_t nTimeouts = 0; + + do { - Core_PushlockAcquire(&nic->net_tables->table_lock, false); - RB_REMOVE(address_table, &nic->net_tables->arp_cache, ent); - Core_PushlockRelease(&nic->net_tables->table_lock, false); - Free(OBOS_KernelAllocator, ent, sizeof(*ent)); - return status; // hdr_ptr isn't leaked, as we never reference it - } + shared_ptr *eth = NetH_FormatEthernetPacket(nic, MAC_BROADCAST, hdr, sz_hdr, ETHERNET2_TYPE_ARP); + status = NetH_SendEthernetPacket(nic, OBOS_SharedPtrCopy(eth)); + if (obos_is_error(status)) + { + Core_PushlockAcquire(&nic->net_tables->table_lock, false); + RB_REMOVE(address_table, &nic->net_tables->arp_cache, ent); + Core_PushlockRelease(&nic->net_tables->table_lock, false); + Free(OBOS_KernelAllocator, ent, sizeof(*ent)); + return status; // hdr_ptr isn't leaked, as we never reference it + } + + status = Core_WaitOnObjects(2, objs, &signaled); + if (obos_is_error(status)) + { + Core_PushlockAcquire(&nic->net_tables->arp_cache_lock, true); + RB_REMOVE(address_table, &nic->net_tables->arp_cache, ent); + Core_PushlockRelease(&nic->net_tables->arp_cache_lock, true); + Free(OBOS_KernelAllocator, ent, sizeof(*ent)); + return status; + } + if (signaled == WAITABLE_OBJECT(ent->sync)) + break; + Core_EventClear(&tm_evnt); + // We timed out. + continue; + } while (++nTimeouts <= 10); + + Core_CancelTimer(tm); + Core_TimerObjectFree(tm); - status = Core_WaitOnObject(WAITABLE_OBJECT(ent->sync)); - if (obos_is_error(status)) + if (signaled != WAITABLE_OBJECT(ent->sync)) { + status = OBOS_STATUS_TIMED_OUT; Core_PushlockAcquire(&nic->net_tables->arp_cache_lock, true); RB_REMOVE(address_table, &nic->net_tables->arp_cache, ent); Core_PushlockRelease(&nic->net_tables->arp_cache_lock, true); + Free(OBOS_KernelAllocator, ent, sizeof(*ent)); return status; } + if (out) memcpy(*out, ent->phys, sizeof(mac_address)); if (address_table_ent) From 5f43e05fff2e04543676a3ea8ab63e11579d8256 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 18:58:14 -0500 Subject: [PATCH 56/96] init/nm: Handle ioctl() errors in nm_initialize_interface --- src/init/nm.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/init/nm.c b/src/init/nm.c index d9442c6e..ba4e8811 100644 --- a/src/init/nm.c +++ b/src/init/nm.c @@ -191,19 +191,37 @@ bool nm_initialize_interface(cJSON* top_level) for (size_t i = 0; i < ip_table_len; i++) { if (ip_table[i].address.addr && ip_table[i].broadcast.addr && ip_table[i].subnet) - ioctl(fd, IOCTL_IFACE_ADD_IP_TABLE_ENTRY, &ip_table[i]); + { + if (ioctl(fd, IOCTL_IFACE_ADD_IP_TABLE_ENTRY, &ip_table[i]) != 0) + { + fprintf(stderr, "ioctl(IOCTL_IFACE_ADD_IP_TABLE_ENTRY): %s\nIs the interface already configured?\n", strerror(errno)); + return false; + } + } else fprintf(stderr, "NM: %s: Skipping invalid ip table entry\n", interface_name); } for (size_t i = 0; i < nGateways; i++) { if (gateways[i].src.addr && gateways[i].dest.addr) - ioctl(fd, IOCTL_IFACE_ADD_ROUTING_TABLE_ENTRY, &gateways[i]); + { + if (ioctl(fd, IOCTL_IFACE_ADD_ROUTING_TABLE_ENTRY, &gateways[i]) != 0) + { + fprintf(stderr, "ioctl(IOCTL_IFACE_ADD_ROUTING_TABLE_ENTRY): %s\nIs the router up, or is the interface already configured?\n", strerror(errno)); + return false; + } + } else fprintf(stderr, "NM: %s: Skipping invalid static route\n", interface_name); } if (default_gateway.addr) - ioctl(fd, IOCTL_IFACE_SET_DEFAULT_GATEWAY, &default_gateway); + { + if (ioctl(fd, IOCTL_IFACE_SET_DEFAULT_GATEWAY, &default_gateway) != 0) + { + fprintf(stderr, "ioctl(IOCTL_IFACE_SET_DEFAULT_GATEWAY): %s\nIs the router up, or is the interface already configured?\n", strerror(errno)); + return false; + } + } else fprintf(stderr, "NM: %s: Skipping default gateway\n", interface_name); From 49a5ba63cd2776cd47257d3eea3e4a8f06153157 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 19:57:22 -0500 Subject: [PATCH 57/96] core: Do not count the idle thread as a ready thread in cpu_local --- src/oboskrnl/arch/m68k/entry.c | 1 + src/oboskrnl/arch/x86_64/entry.c | 2 ++ src/oboskrnl/arch/x86_64/smp.c | 2 ++ 3 files changed, 5 insertions(+) diff --git a/src/oboskrnl/arch/m68k/entry.c b/src/oboskrnl/arch/m68k/entry.c index 01d6aa2e..baea8904 100644 --- a/src/oboskrnl/arch/m68k/entry.c +++ b/src/oboskrnl/arch/m68k/entry.c @@ -175,6 +175,7 @@ void Arch_KernelEntryBootstrap() CoreH_ThreadInitialize(&idle_thread, THREAD_PRIORITY_IDLE, Core_DefaultThreadAffinity, &ctx); CoreH_ThreadReadyNode(&kmain_thread, &kmain_node); CoreH_ThreadReadyNode(&idle_thread, &idle_thread_node); + bsp_cpu.nReadyThreads--; Core_LowerIrql(oldIrql); // Finally, yield. diff --git a/src/oboskrnl/arch/x86_64/entry.c b/src/oboskrnl/arch/x86_64/entry.c index 0b86f8bf..aec4cae1 100644 --- a/src/oboskrnl/arch/x86_64/entry.c +++ b/src/oboskrnl/arch/x86_64/entry.c @@ -490,6 +490,8 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry CoreH_ThreadReady(&kernelMainThread); CoreH_ThreadReady(&bsp_idleThread); Core_CpuInfo->idleThread = &bsp_idleThread; + Core_CpuInfo->nReadyThreads--; + Core_ReadyThreadCount--; // Initialize the CPU's GDT. Arch_CPUInitializeGDT(&Core_CpuInfo[0], (uintptr_t)Arch_InitialISTStack, sizeof(Arch_InitialISTStack)); diff --git a/src/oboskrnl/arch/x86_64/smp.c b/src/oboskrnl/arch/x86_64/smp.c index 28b1f3a6..f51f16fa 100644 --- a/src/oboskrnl/arch/x86_64/smp.c +++ b/src/oboskrnl/arch/x86_64/smp.c @@ -157,6 +157,8 @@ void __attribute__((no_stack_protector)) Arch_APEntry(cpu_local* info) thread* idleThread = CoreH_ThreadAllocate(nullptr); CoreH_ThreadInitialize(idleThread, THREAD_PRIORITY_IDLE, ((thread_affinity)1<id), &ctx); CoreH_ThreadReady(idleThread); + info->nReadyThreads--; + Core_ReadyThreadCount--; Core_ProcessAppendThread(OBOS_KernelProcess, idleThread); info->idleThread = idleThread; Arch_LAPICInitialize(false); From ccb736fd6288aea82084baa814091c57ef8b0954 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 19:57:41 -0500 Subject: [PATCH 58/96] arch/x86_64: Free page tables in MmS_FreePageTable --- src/oboskrnl/arch/x86_64/map.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/oboskrnl/arch/x86_64/map.c b/src/oboskrnl/arch/x86_64/map.c index 02e89eee..c9125ec6 100644 --- a/src/oboskrnl/arch/x86_64/map.c +++ b/src/oboskrnl/arch/x86_64/map.c @@ -372,18 +372,18 @@ obos_status OBOSS_GetPagePhysicalAddress(void* at_, uintptr_t* oPhys) static basicmm_region kernel_region; static basicmm_region hhdm_region; -static void FreePageTables(uintptr_t* pm, uint8_t level, uint32_t beginIndex, uint32_t* indices) +static void FreePageTables(uintptr_t* pm, uint8_t level, uint32_t beginIndex, bool user, uint32_t* indices) { if (!pm) return; pm = (uintptr_t*)MmS_MapVirtFromPhys((uintptr_t)pm); - for (indices[level] = beginIndex; indices[level] < 512; indices[level]++) + for (indices[level] = beginIndex; indices[level] < (user ? 256 : 512); indices[level]++) { if (!pm[indices[level]]) continue; if (pm[indices[level]] & ((uintptr_t)1<<7) || level == 0) continue; - FreePageTables((uintptr_t*)Arch_MaskPhysicalAddressFromEntry(pm[indices[level]]), level - 1, 0, indices); + FreePageTables((uintptr_t*)Arch_MaskPhysicalAddressFromEntry(pm[indices[level]]), level - 1, 0, false, indices); Mm_FreePhysicalPages(Arch_MaskPhysicalAddressFromEntry(pm[indices[level]]), 1); } } @@ -436,7 +436,7 @@ obos_status Arch_InitializeKernelPageTable() asm volatile("mov %0, %%cr3;" : :"r"(newCR3)); // Reclaim old page tables. uint32_t indices[4] = { 0,0,0,0 }; - FreePageTables((uintptr_t*)oldCR3, 3, AddressToIndex(0xffff800000000000, 3), indices); + FreePageTables((uintptr_t*)oldCR3, 3, AddressToIndex(0xffff800000000000, 3), false, indices); Mm_FreePhysicalPages((uintptr_t)oldCR3, 1); #if OBOS_USE_LIMINE OBOSH_BasicMMAddRegion( @@ -600,7 +600,8 @@ page_table MmS_AllocatePageTable() } void MmS_FreePageTable(page_table pt) { - // uint32_t indices[4] = {}; - // FreePageTables(MmS_MapVirtFromPhys(pt), 3, 0, indices); + OBOS_ENSURE(pt != Arch_KernelCR3); + uint32_t indices[4] = {}; + FreePageTables((uintptr_t*)pt, 3, 0, true, indices); Mm_FreePhysicalPages(pt, 1); } From 267d17ab8852e6c69bc0ce6e2a0470060bbd974e Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 20:41:36 -0500 Subject: [PATCH 59/96] net: Fix bug with ARP --- src/oboskrnl/net/arp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/oboskrnl/net/arp.c b/src/oboskrnl/net/arp.c index da298bb9..1e0d3d83 100644 --- a/src/oboskrnl/net/arp.c +++ b/src/oboskrnl/net/arp.c @@ -113,6 +113,8 @@ obos_status NetH_ARPRequest(vnode* nic, ip_addr addr, mac_address* out, address_ status = NetH_SendEthernetPacket(nic, OBOS_SharedPtrCopy(eth)); if (obos_is_error(status)) { + Core_CancelTimer(tm); + Core_TimerObjectFree(tm); Core_PushlockAcquire(&nic->net_tables->table_lock, false); RB_REMOVE(address_table, &nic->net_tables->arp_cache, ent); Core_PushlockRelease(&nic->net_tables->table_lock, false); @@ -123,6 +125,8 @@ obos_status NetH_ARPRequest(vnode* nic, ip_addr addr, mac_address* out, address_ status = Core_WaitOnObjects(2, objs, &signaled); if (obos_is_error(status)) { + Core_CancelTimer(tm); + Core_TimerObjectFree(tm); Core_PushlockAcquire(&nic->net_tables->arp_cache_lock, true); RB_REMOVE(address_table, &nic->net_tables->arp_cache, ent); Core_PushlockRelease(&nic->net_tables->arp_cache_lock, true); From 9dae8a7453ff109ccf5dd01a054e2aafc4513118 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 20:41:47 -0500 Subject: [PATCH 60/96] sys: Fix memory leak --- src/oboskrnl/vfs/fd_sys.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/oboskrnl/vfs/fd_sys.c b/src/oboskrnl/vfs/fd_sys.c index 0301cd66..4e13d3b7 100644 --- a/src/oboskrnl/vfs/fd_sys.c +++ b/src/oboskrnl/vfs/fd_sys.c @@ -805,6 +805,8 @@ obos_status Sys_ReadLinkAt(handle parent, const char *upath, void* ubuff, size_t if (length) memcpy_k_to_usr(length, &len, sizeof(size_t)); + Mm_VirtualMemoryFree(&Mm_KernelContext, buff, max_size); + return OBOS_STATUS_SUCCESS; } From 6aa168623c950fcfd79c0b07f90efe5c26a47228 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 20:42:13 -0500 Subject: [PATCH 61/96] x86_64: Fix memory leak --- src/oboskrnl/arch/x86_64/execve.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/oboskrnl/arch/x86_64/execve.c b/src/oboskrnl/arch/x86_64/execve.c index 792bc124..17556c38 100644 --- a/src/oboskrnl/arch/x86_64/execve.c +++ b/src/oboskrnl/arch/x86_64/execve.c @@ -160,6 +160,8 @@ OBOS_NORETURN OBOS_NO_KASAN void OBOSS_HandControlTo(struct context* ctx, struct // Core_GetCurrentThread()->context.fs_base = 0; // Core_GetCurrentThread()->context.gs_base = 0; + Mm_VirtualMemoryFree(&Mm_KernelContext, init_vals, szAllocation); + OBOS_Debug("Handing off control to user program.\n"); OBOS_Debug("NOTE: RSP=0x%p.\n", Core_GetCurrentThread()->context.frame.rsp); @@ -180,6 +182,8 @@ void OBOSS_HandOffToInit(struct exec_aux_values* aux) Core_GetCurrentThread()->context.stackBase = Mm_VirtualMemoryAlloc(ctx, nullptr, 4*1024*1024, OBOS_PROTECTION_USER_PAGE, VMA_FLAGS_GUARD_PAGE, nullptr, nullptr); Core_GetCurrentThread()->context.stackSize = 4*1024*1024; + Core_GetCurrentThread()->stackFree = CoreH_VMAStackFree; + Core_GetCurrentThread()->stackFreeUserdata = ctx; CoreS_SetThreadPageTable(&Core_GetCurrentThread()->context, ctx->pt); From ad6ae6dbfcacdbca3a84527963250da9066edaa0 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 20:42:44 -0500 Subject: [PATCH 62/96] misc: Fix erroneous code --- src/drivers/generic/extfs/helper.c | 1 + .../generic/freebsd-e1000/CMakeLists.txt | 4 ++++ src/drivers/generic/initrd/main.c | 20 +++++++++++++++++-- src/oboskrnl/allocators/base.h | 4 ++-- src/oboskrnl/mm/alloc.h | 7 ++++++- src/uACPI/CMakeLists.txt | 4 ++++ 6 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/drivers/generic/extfs/helper.c b/src/drivers/generic/extfs/helper.c index 8a109c34..aa6da2ab 100644 --- a/src/drivers/generic/extfs/helper.c +++ b/src/drivers/generic/extfs/helper.c @@ -702,6 +702,7 @@ uint32_t allocate_bmp(ext_cache* cache, const uint32_t* block_group_ptr, int wha buffer = ext_read_block(cache, block, &pg); MmH_RefPage(pg); } + OBOS_ENSURE(buffer); if (buffer[i] != 0xff) { uint8_t bit = __builtin_ctz(~buffer[i]); diff --git a/src/drivers/generic/freebsd-e1000/CMakeLists.txt b/src/drivers/generic/freebsd-e1000/CMakeLists.txt index 4d2655c4..f5c7fa8e 100644 --- a/src/drivers/generic/freebsd-e1000/CMakeLists.txt +++ b/src/drivers/generic/freebsd-e1000/CMakeLists.txt @@ -17,6 +17,10 @@ target_compile_options(e1000 PRIVATE $<$:-Wno-error> ) +if (OBOS_ENABLE_FANALYZER) + target_compile_options(e1000 PRIVATE "-fno-analyzer") +endif() + set_property(TARGET e1000 PROPERTY link_depends ${DRIVER_LINKER_SCRIPT}) target_include_directories(e1000 diff --git a/src/drivers/generic/initrd/main.c b/src/drivers/generic/initrd/main.c index 874c837f..9bacf96b 100644 --- a/src/drivers/generic/initrd/main.c +++ b/src/drivers/generic/initrd/main.c @@ -177,7 +177,6 @@ static int64_t strrfind(const char* str, char ch) initrd_inode* create_inode_boot(const ustar_hdr* hdr) { initrd_inode* ino = ZeroAllocate(OBOS_KernelAllocator, 1, sizeof(initrd_inode), nullptr); - ino->ino = CurrentInodeNumber++; bool path_needs_slash = hdr->filename[0] != '/' && (*hdr->prefix && hdr->prefix[strnlen(hdr->prefix, 155)-1] != '/'); ino->path_len = strnlen(hdr->filename, 100) + strnlen(hdr->prefix, 155) + path_needs_slash; @@ -228,7 +227,12 @@ initrd_inode* create_inode_boot(const ustar_hdr* hdr) obos_status status = OBOS_STATUS_SUCCESS; hdr = GetFile(hdr->linked, &status); if (obos_is_error(status)) + { + Free(OBOS_KernelAllocator, ino->name, ino->name_size); + Free(OBOS_KernelAllocator, ino->path, ino->path_size); + Free(OBOS_KernelAllocator, ino, sizeof(*ino)); return nullptr; + } goto back; break; } @@ -279,6 +283,7 @@ initrd_inode* create_inode_boot(const ustar_hdr* hdr) } ino->hdr = hdr; + ino->ino = CurrentInodeNumber++; return ino; } @@ -325,6 +330,8 @@ driver_init_status OBOS_DriverEntry(driver_id* this) goto down; initrd_inode* ino = create_inode_boot(hdr); + if (!ino) + return (driver_init_status){.status=OBOS_STATUS_INTERNAL_ERROR,.fatal=false}; ino->parent = InitrdRoot; if (!ino->parent->children.head) ino->parent->children.head = ino; @@ -482,6 +489,8 @@ initrd_inode* create_inode_with_parents(const char* path, const ustar_hdr* hdr) return nullptr; initrd_inode* ino = create_inode_boot(hdr); + if (!ino) + return nullptr; // Get our parent. int64_t index = strrfind(ino->path, '/'); if (index == -1) @@ -518,6 +527,13 @@ initrd_inode* create_inode_with_parents(const char* path, const ustar_hdr* hdr) goto down; initrd_inode* sub_ino = create_inode_boot(sub_hdr); + if (!sub_ino) + { + Free(OBOS_KernelAllocator, ino->name, ino->name_size); + Free(OBOS_KernelAllocator, ino->path, ino->path_size); + Free(OBOS_KernelAllocator, ino, sizeof(*ino)); + return nullptr; + } sub_ino->parent = ino->parent; // printf("%s %s\n", iter, sub_ino->parent->name); if (!sub_ino->parent->children.head) @@ -628,7 +644,7 @@ OBOS_PAGEABLE_FUNCTION obos_status list_dir(dev_desc dir_, void* unused, iterate initrd_inode *ino = DirentLookupFrom(hdr_path, dir); if (!ino) ino = create_inode_with_parents(hdr_path, hdr); - if (ino->dead) + if (!ino || ino->dead) goto down; if (cb((dev_desc)ino, 1, ino->filesize, userdata, ino->name) == ITERATE_DECISION_STOP) { diff --git a/src/oboskrnl/allocators/base.h b/src/oboskrnl/allocators/base.h index 45cc6002..4645996f 100644 --- a/src/oboskrnl/allocators/base.h +++ b/src/oboskrnl/allocators/base.h @@ -66,8 +66,8 @@ typedef struct allocator_info OBOS_EXPORT obos_status Free(struct allocator_info* This, void* base, size_t nBytes); #ifndef __clang__ -OBOS_EXPORT __attribute__((malloc, malloc(Free, 2))) void* Allocate(struct allocator_info* This, size_t nBytes, obos_status* status); -OBOS_EXPORT __attribute__((malloc, malloc(Free, 2))) void* ZeroAllocate(struct allocator_info* This, size_t nObjects, size_t bytesPerObject, obos_status* status); +OBOS_EXPORT __attribute__((malloc, malloc(Free, 2), returns_nonnull)) void* Allocate(struct allocator_info* This, size_t nBytes, obos_status* status); +OBOS_EXPORT __attribute__((malloc, malloc(Free, 2), returns_nonnull)) void* ZeroAllocate(struct allocator_info* This, size_t nObjects, size_t bytesPerObject, obos_status* status); #else OBOS_EXPORT void* Allocate(struct allocator_info* This, size_t nBytes, obos_status* status); OBOS_EXPORT void* ZeroAllocate(struct allocator_info* This, size_t nObjects, size_t bytesPerObject, obos_status* status); diff --git a/src/oboskrnl/mm/alloc.h b/src/oboskrnl/mm/alloc.h index f305f429..3c3ed17a 100644 --- a/src/oboskrnl/mm/alloc.h +++ b/src/oboskrnl/mm/alloc.h @@ -75,9 +75,14 @@ extern OBOS_EXPORT page* Mm_UserAnonPage; OBOS_EXPORT void* MmH_FindAvailableAddress(context* ctx, size_t size, vma_flags flags, obos_status* status); // file can be nullptr for a anonymous mapping. +OBOS_EXPORT obos_status Mm_VirtualMemoryFree(context* ctx, void* base, size_t size); +#ifndef __clang__ +OBOS_EXPORT __attribute__((malloc, malloc(Mm_VirtualMemoryFree, 2))) void* Mm_VirtualMemoryAlloc(context* ctx, void* base, size_t size, prot_flags prot, vma_flags flags, fd* file, obos_status* status); +OBOS_EXPORT __attribute__((malloc, malloc(Mm_VirtualMemoryFree, 2))) void* Mm_VirtualMemoryAllocEx(context* ctx, void* base, size_t size, prot_flags prot, vma_flags flags, fd* file, uoff_t offset, obos_status* status); +#else OBOS_EXPORT void* Mm_VirtualMemoryAlloc(context* ctx, void* base, size_t size, prot_flags prot, vma_flags flags, fd* file, obos_status* status); OBOS_EXPORT void* Mm_VirtualMemoryAllocEx(context* ctx, void* base, size_t size, prot_flags prot, vma_flags flags, fd* file, uoff_t offset, obos_status* status); -OBOS_EXPORT obos_status Mm_VirtualMemoryFree(context* ctx, void* base, size_t size); +#endif // Note: base must be the exact address as returned by VirtualMemoryAlloc. // isPageable values: // 0: Non-pageable diff --git a/src/uACPI/CMakeLists.txt b/src/uACPI/CMakeLists.txt index 0657d2d7..abb3f543 100644 --- a/src/uACPI/CMakeLists.txt +++ b/src/uACPI/CMakeLists.txt @@ -23,6 +23,10 @@ if (OBOS_ENABLE_PROFILER) target_compile_options(uacpi PRIVATE $<$:-finstrument-functions>) endif() +if (OBOS_ENABLE_FANALYZER) + target_compile_options(uacpi PRIVATE "-fno-analyzer") +endif() + # All symbols exported, except for the kernel api of course. set_source_files_properties("kernel_api.c" PROPERTIES COMPILE_OPTIONS "-fvisibility=hidden") From fcedc012ccfe28068026b74acba16afea774566b Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 20:42:58 -0500 Subject: [PATCH 63/96] user-utils: Install the module commands into sbin instead of bin --- src/user-utilities/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/user-utilities/CMakeLists.txt b/src/user-utilities/CMakeLists.txt index df2357a9..a2fe18c0 100644 --- a/src/user-utilities/CMakeLists.txt +++ b/src/user-utilities/CMakeLists.txt @@ -29,10 +29,12 @@ add_executable (lsmod "lsmod.c") add_executable (ldmod "ldmod.c") add_executable (stmod "stmod.c") add_executable (rmmod "rmmod.c") -install(TARGETS powerctl klog-level fork-test mem-usage mount umount swapon mkswap sync-anon lsmod ldmod stmod rmmod) +install(TARGETS powerctl klog-level fork-test mem-usage mount umount swapon mkswap sync-anon) +install(TARGETS lsmod ldmod stmod rmmod DESTINATION sbin) if (${OBOS_ARCHITECTURE} STREQUAL "x86_64") add_executable(obos-gettime "x86_obos-gettime.c") add_executable(enable-kgdbstub "x86_enable-kgdbstub.c") - install(TARGETS obos-gettime enable-kgdbstub) + install(TARGETS obos-gettime) + install(TARGETS enable-kgdbstub DESTINATION sbin) endif() From 75cc84664781cdad3d69aef785e72ce2ecd660c3 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 20:52:14 -0500 Subject: [PATCH 64/96] misc: Add new UID/GID fields in process, rename owner_uid and group_uid fields in vnode --- src/drivers/generic/extfs/probe.c | 4 ++-- src/drivers/generic/initrd/main.c | 4 ++-- src/oboskrnl/arch/x86_64/gdbstub/vFile.c | 4 ++-- src/oboskrnl/driver_interface/drv_sys.c | 2 +- src/oboskrnl/execve.c | 8 ++++---- src/oboskrnl/scheduler/process.h | 4 ++-- src/oboskrnl/scheduler/sched_sys.c | 12 ++++++------ src/oboskrnl/vfs/create.c | 14 +++++++------- src/oboskrnl/vfs/dirent.c | 12 ++++++------ src/oboskrnl/vfs/dummy_devices.c | 4 ++-- src/oboskrnl/vfs/fd.c | 4 ++-- src/oboskrnl/vfs/fd_sys.c | 16 ++++++++-------- src/oboskrnl/vfs/pipe.c | 4 ++-- src/oboskrnl/vfs/vnode.h | 4 ++-- 14 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/drivers/generic/extfs/probe.c b/src/drivers/generic/extfs/probe.c index 931add18..898fe9f5 100644 --- a/src/drivers/generic/extfs/probe.c +++ b/src/drivers/generic/extfs/probe.c @@ -166,8 +166,8 @@ vnode* ext_make_vnode(ext_cache* cache, uint32_t ino, mount* mnt) vn->desc = (dev_desc)handle; vn->vtype = vtype; vn->blkSize = 1; - vn->owner_uid = inode->uid; - vn->group_uid = inode->gid; + vn->uid = inode->uid; + vn->gid = inode->gid; vn->filesize = (uint64_t)inode->size | (ext_sb_supports_64bit_filesize ? (uint64_t)inode->dir_acl << 32 : 0); vn->times.access = inode->access_time; vn->times.birth = inode->creation_time; diff --git a/src/drivers/generic/initrd/main.c b/src/drivers/generic/initrd/main.c index 9bacf96b..a94981d0 100644 --- a/src/drivers/generic/initrd/main.c +++ b/src/drivers/generic/initrd/main.c @@ -260,8 +260,8 @@ initrd_inode* create_inode_boot(const ustar_hdr* hdr) ino->vnode->desc = (uintptr_t)ino; ino->vnode->filesize = ino->filesize; ino->vnode->blkSize = 1; - ino->vnode->owner_uid = 0; - ino->vnode->group_uid = 0; + ino->vnode->uid = 0; + ino->vnode->gid = 0; ino->vnode->inode = ino->ino; ino->vnode->perm = ino->perm; ino->vnode->times.change = oct2bin(hdr->last_mod, strnlen(hdr->last_mod, 12)); diff --git a/src/oboskrnl/arch/x86_64/gdbstub/vFile.c b/src/oboskrnl/arch/x86_64/gdbstub/vFile.c index 44b0907f..e5b4adf2 100644 --- a/src/oboskrnl/arch/x86_64/gdbstub/vFile.c +++ b/src/oboskrnl/arch/x86_64/gdbstub/vFile.c @@ -197,8 +197,8 @@ static obos_status common_stat(vnode* vn, struct gdb_stat* out) out->st_dev = 0; out->st_ino = vn->inode; out->st_nlink = vn->refs; - out->st_uid = vn->owner_uid; - out->st_gid = vn->group_uid; + out->st_uid = vn->uid; + out->st_gid = vn->gid; out->st_rdev = 0; out->st_size = vn->filesize; out->st_blksize = vn->blkSize; diff --git a/src/oboskrnl/driver_interface/drv_sys.c b/src/oboskrnl/driver_interface/drv_sys.c index 06c41145..b2e4d544 100644 --- a/src/oboskrnl/driver_interface/drv_sys.c +++ b/src/oboskrnl/driver_interface/drv_sys.c @@ -24,7 +24,7 @@ handle Sys_LoadDriver(const void* file, size_t szFile, obos_status* ustatus) { - if (Core_GetCurrentThread()->proc->currentUID != ROOT_UID) + if (Core_GetCurrentThread()->proc->euid != ROOT_UID) { if (ustatus) *ustatus = OBOS_STATUS_ACCESS_DENIED; return HANDLE_INVALID; diff --git a/src/oboskrnl/execve.c b/src/oboskrnl/execve.c index d9aac177..4b99e627 100644 --- a/src/oboskrnl/execve.c +++ b/src/oboskrnl/execve.c @@ -144,8 +144,8 @@ obos_status Sys_ExecVE(const char* upath, char* const* argv, char* const* envp) void* kbuf = Mm_VirtualMemoryAlloc(&Mm_KernelContext, nullptr, szBuf, OBOS_PROTECTION_READ_ONLY, 0, &file, nullptr); bool set_uid = file.vn->perm.set_uid; bool set_gid = file.vn->perm.set_gid; - uid target_uid = set_uid ? file.vn->owner_uid : Core_GetCurrentThread()->proc->currentUID; - gid target_gid = set_gid ? file.vn->group_uid : Core_GetCurrentThread()->proc->currentGID; + uid target_uid = set_uid ? file.vn->uid : Core_GetCurrentThread()->proc->euid; + gid target_gid = set_gid ? file.vn->gid : Core_GetCurrentThread()->proc->egid; Vfs_FdClose(&file); char** kargv = allocate_user_vector_as_kernel(ctx, argv, &argc, &status); @@ -309,8 +309,8 @@ obos_status Sys_ExecVE(const char* upath, char* const* argv, char* const* envp) aux.at_secure = set_gid || set_uid; - Core_GetCurrentThread()->proc->currentUID = target_uid; - Core_GetCurrentThread()->proc->currentGID = target_gid; + Core_GetCurrentThread()->proc->euid = target_uid; + Core_GetCurrentThread()->proc->egid = target_gid; OBOSS_HandControlTo(ctx, &aux); } diff --git a/src/oboskrnl/scheduler/process.h b/src/oboskrnl/scheduler/process.h index 324a1b9c..ac697526 100644 --- a/src/oboskrnl/scheduler/process.h +++ b/src/oboskrnl/scheduler/process.h @@ -37,8 +37,8 @@ typedef struct process struct process_group* pgrp; - uid currentUID; - gid currentGID; + uid euid, ruid, suid; + gid egid, rgid, sgid; uint32_t exitCode; bool dead; diff --git a/src/oboskrnl/scheduler/sched_sys.c b/src/oboskrnl/scheduler/sched_sys.c index a527ec93..955aa8ab 100644 --- a/src/oboskrnl/scheduler/sched_sys.c +++ b/src/oboskrnl/scheduler/sched_sys.c @@ -667,25 +667,25 @@ obos_status Sys_WaitProcess(handle proc, int* wstatus, int options, uint32_t* pi obos_status Sys_SetUid(uid to) { process* proc = Core_GetCurrentThread()->proc; - if (proc->currentUID != 0) + if (proc->euid != 0) return OBOS_STATUS_ACCESS_DENIED; - proc->currentUID = to; + proc->euid = to; return OBOS_STATUS_SUCCESS; } obos_status Sys_SetGid(gid to) { process* proc = Core_GetCurrentThread()->proc; - if (proc->currentUID != 0) + if (proc->euid != 0) return OBOS_STATUS_ACCESS_DENIED; - proc->currentGID = to; + proc->egid = to; return OBOS_STATUS_SUCCESS; } uid Sys_GetUid() -{ return Core_GetCurrentThread()->proc->currentUID; } +{ return Core_GetCurrentThread()->proc->euid; } gid Sys_GetGid() -{ return Core_GetCurrentThread()->proc->currentGID; } +{ return Core_GetCurrentThread()->proc->egid; } obos_status Sys_SetProcessGroup(handle process, uint32_t pgid) { diff --git a/src/oboskrnl/vfs/create.c b/src/oboskrnl/vfs/create.c index 6ca818a2..772cab74 100644 --- a/src/oboskrnl/vfs/create.c +++ b/src/oboskrnl/vfs/create.c @@ -25,20 +25,20 @@ static bool has_write_perm(vnode* parent) { - uid current_uid = Core_GetCurrentThread()->proc->currentUID; - uid current_gid = Core_GetCurrentThread()->proc->currentGID; + uid current_uid = Core_GetCurrentThread()->proc->euid; + uid current_gid = Core_GetCurrentThread()->proc->egid; if (parent->flags & VFLAGS_MOUNTPOINT) { drv_fs_info info = {}; parent->un.mounted->fs_driver->driver->header.ftable.stat_fs_info(parent->un.mounted->device, &info); - if (parent->owner_uid == current_uid || parent->group_uid == current_gid) + if (parent->uid == current_uid || parent->gid == current_gid) return ~info.flags & FS_FLAGS_RDONLY; else return false; } - if (parent->owner_uid == current_uid) + if (parent->uid == current_uid) return parent->perm.owner_write; - else if (parent->group_uid == current_gid) + else if (parent->gid == current_gid) return parent->perm.group_write; else return parent->perm.other_write; @@ -94,8 +94,8 @@ obos_status Vfs_CreateNode(dirent* parent, const char* name, uint32_t vtype, fil return OBOS_STATUS_INVALID_ARGUMENT; } vnode* vn = Vfs_Calloc(1, sizeof(vnode)); - vn->group_uid = Core_GetCurrentThread()->proc->currentGID; - vn->owner_uid = Core_GetCurrentThread()->proc->currentUID; + vn->gid = Core_GetCurrentThread()->proc->egid; + vn->uid = Core_GetCurrentThread()->proc->euid; vn->perm = mode; vn->flags = 0; vn->vtype = vtype; diff --git a/src/oboskrnl/vfs/dirent.c b/src/oboskrnl/vfs/dirent.c index 88fcfe7e..beb13dd2 100644 --- a/src/oboskrnl/vfs/dirent.c +++ b/src/oboskrnl/vfs/dirent.c @@ -468,8 +468,8 @@ vnode* Drv_AllocateVNode(driver_id* drv, dev_desc desc, size_t filesize, vdev** vn->inode = devfs_inode++; vn->perm = default_fileperm; vn->vtype = type; - vn->group_uid = ROOT_GID; - vn->owner_uid = ROOT_UID; + vn->gid = ROOT_GID; + vn->uid = ROOT_UID; vn->times.access = get_current_time(); vn->times.birth = vn->times.access; vn->times.change = vn->times.access; @@ -662,12 +662,12 @@ char* VfsH_DirentPath(dirent* ent, dirent* relative_to) static bool check_chdir_perms(dirent* ent) { - uid uid = Core_GetCurrentThread()->proc->currentUID; - gid gid = Core_GetCurrentThread()->proc->currentGID; + uid uid = Core_GetCurrentThread()->proc->euid; + gid gid = Core_GetCurrentThread()->proc->egid; - if (uid == ent->vnode->owner_uid) + if (uid == ent->vnode->uid) return ent->vnode->perm.owner_exec; - else if (gid == ent->vnode->group_uid) + else if (gid == ent->vnode->gid) return ent->vnode->perm.group_exec; else return ent->vnode->perm.other_exec; diff --git a/src/oboskrnl/vfs/dummy_devices.c b/src/oboskrnl/vfs/dummy_devices.c index 0275881d..a4e043d5 100644 --- a/src/oboskrnl/vfs/dummy_devices.c +++ b/src/oboskrnl/vfs/dummy_devices.c @@ -417,8 +417,8 @@ static void init_desc(dev_desc desc) dirent* ent = Vfs_Calloc(1, sizeof(dirent)); vnode* vn = Vfs_Calloc(1, sizeof(vnode)); - vn->owner_uid = 0; - vn->group_uid = 0; + vn->uid = 0; + vn->gid = 0; vn->desc = desc; get_max_blk_count(desc, &vn->filesize); diff --git a/src/oboskrnl/vfs/fd.c b/src/oboskrnl/vfs/fd.c index 33f98597..74789443 100644 --- a/src/oboskrnl/vfs/fd.c +++ b/src/oboskrnl/vfs/fd.c @@ -94,7 +94,7 @@ OBOS_EXPORT obos_status Vfs_FdOpenVnode(fd* const desc, void* vn, uint32_t oflag desc->flags |= FD_FLAGS_OPEN; desc->flags |= FD_FLAGS_READ; desc->flags |= FD_FLAGS_WRITE; - if (desc->vn->owner_uid == Core_GetCurrentThread()->proc->currentUID || Core_GetCurrentThread()->proc->currentUID == 0) + if (desc->vn->uid == Core_GetCurrentThread()->proc->euid || Core_GetCurrentThread()->proc->euid == 0) { // We have owner perms. struct vnode* const vn = desc->vn; @@ -105,7 +105,7 @@ OBOS_EXPORT obos_status Vfs_FdOpenVnode(fd* const desc, void* vn, uint32_t oflag if (oflags & FD_OFLAGS_EXECUTE && !vn->perm.owner_exec) return OBOS_STATUS_ACCESS_DENIED; } - else if (desc->vn->group_uid == Core_GetCurrentThread()->proc->currentGID) + else if (desc->vn->gid == Core_GetCurrentThread()->proc->egid) { // We have group perms. struct vnode* const vn = desc->vn; diff --git a/src/oboskrnl/vfs/fd_sys.c b/src/oboskrnl/vfs/fd_sys.c index 4e13d3b7..f3a3f1eb 100644 --- a/src/oboskrnl/vfs/fd_sys.c +++ b/src/oboskrnl/vfs/fd_sys.c @@ -680,8 +680,8 @@ obos_status Sys_Stat(int fsfdt, handle desc, const char* upath, int flags, struc st.st_atim.tv_nsec = 0; st.st_ctim.tv_nsec = 0; st.st_mtim.tv_nsec = 0; - st.st_gid = to_stat->group_uid; - st.st_uid = to_stat->owner_uid; + st.st_gid = to_stat->gid; + st.st_uid = to_stat->uid; st.st_ino = to_stat->inode; if (to_stat->flags & VFLAGS_EVENT_DEV && ~to_stat->flags & VFLAGS_DRIVER_DEAD) goto done; @@ -1326,8 +1326,8 @@ obos_status Sys_CreateNamedPipe(handle dirfd, const char* upath, int mode, size_ fifo_name = path; } - gid current_gid = Core_GetCurrentThread()->proc->currentGID; - uid current_uid = Core_GetCurrentThread()->proc->currentUID; + gid current_gid = Core_GetCurrentThread()->proc->egid; + uid current_uid = Core_GetCurrentThread()->proc->euid; status = Vfs_CreateNamedPipe(perm, current_gid, current_uid, parent, fifo_name, pipesize); Free(OBOS_KernelAllocator, path, sz_path); @@ -2910,7 +2910,7 @@ obos_status Sys_FChmodAt(handle dirfd, const char* upathname, int mode, int flag have_target: - if (target->owner_uid != Sys_GetUid() && Sys_GetUid() != ROOT_UID) + if (target->uid != Sys_GetUid() && Sys_GetUid() != ROOT_UID) { status = OBOS_STATUS_ACCESS_DENIED; goto fail; @@ -3030,7 +3030,7 @@ obos_status Sys_FChownAt(handle dirfd, const char *upathname, uid owner, gid gro have_target: OBOS_ENSURE(target); - if (target->owner_uid != Sys_GetUid() && Sys_GetUid() != ROOT_UID) + if (target->uid != Sys_GetUid() && Sys_GetUid() != ROOT_UID) { status = OBOS_STATUS_ACCESS_DENIED; goto fail; @@ -3048,9 +3048,9 @@ obos_status Sys_FChownAt(handle dirfd, const char *upathname, uid owner, gid gro goto fail; if (owner != -1) - target->owner_uid = owner; + target->uid = owner; if (group != -1) - target->group_uid = group; + target->gid = group; fail: Free(OBOS_KernelAllocator, pathname, sz_path); diff --git a/src/oboskrnl/vfs/pipe.c b/src/oboskrnl/vfs/pipe.c index 41296a6b..3be564d1 100644 --- a/src/oboskrnl/vfs/pipe.c +++ b/src/oboskrnl/vfs/pipe.c @@ -442,8 +442,8 @@ obos_status Vfs_CreateNamedPipe(file_perm perm, gid group_uid, uid owner_uid, di dirent* ent = Vfs_Calloc(1, sizeof(dirent)); vnode* vn = Vfs_Calloc(1, sizeof(vnode)); desc->vn = vn; - vn->owner_uid = owner_uid; - vn->group_uid = group_uid; + vn->uid = owner_uid; + vn->gid = group_uid; vn->desc = (uintptr_t)desc; vn->perm = perm; vn->vtype = VNODE_TYPE_FIFO; diff --git a/src/oboskrnl/vfs/vnode.h b/src/oboskrnl/vfs/vnode.h index d0475e83..ec91ee5e 100644 --- a/src/oboskrnl/vfs/vnode.h +++ b/src/oboskrnl/vfs/vnode.h @@ -90,8 +90,8 @@ typedef struct vnode size_t refs; file_perm perm; size_t filesize; // filesize. - uid owner_uid; // the owner's UID. - gid group_uid; // the group's GID. + uid uid; // the owner's UID. + gid gid; // the group's GID. dev_desc desc; // the cached device descriptor. fd_list opened; size_t nMappedRegions; From f4f8c30fa978a5cd280a2c62600d7ddd083a6399 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 21:41:21 -0500 Subject: [PATCH 65/96] sys: Rewrite uid/gid syscalls --- src/oboskrnl/execve.c | 10 ++- src/oboskrnl/scheduler/sched_sys.c | 120 +++++++++++++++++++++++++---- src/oboskrnl/scheduler/sched_sys.h | 8 +- src/oboskrnl/syscall.c | 4 + 4 files changed, 122 insertions(+), 20 deletions(-) diff --git a/src/oboskrnl/execve.c b/src/oboskrnl/execve.c index 4b99e627..620ad9bd 100644 --- a/src/oboskrnl/execve.c +++ b/src/oboskrnl/execve.c @@ -144,8 +144,8 @@ obos_status Sys_ExecVE(const char* upath, char* const* argv, char* const* envp) void* kbuf = Mm_VirtualMemoryAlloc(&Mm_KernelContext, nullptr, szBuf, OBOS_PROTECTION_READ_ONLY, 0, &file, nullptr); bool set_uid = file.vn->perm.set_uid; bool set_gid = file.vn->perm.set_gid; - uid target_uid = set_uid ? file.vn->uid : Core_GetCurrentThread()->proc->euid; - gid target_gid = set_gid ? file.vn->gid : Core_GetCurrentThread()->proc->egid; + uid target_euid = set_uid ? file.vn->uid : Core_GetCurrentThread()->proc->euid; + gid target_egid = set_gid ? file.vn->gid : Core_GetCurrentThread()->proc->egid; Vfs_FdClose(&file); char** kargv = allocate_user_vector_as_kernel(ctx, argv, &argc, &status); @@ -309,8 +309,10 @@ obos_status Sys_ExecVE(const char* upath, char* const* argv, char* const* envp) aux.at_secure = set_gid || set_uid; - Core_GetCurrentThread()->proc->euid = target_uid; - Core_GetCurrentThread()->proc->egid = target_gid; + Core_GetCurrentThread()->proc->euid = target_euid; + Core_GetCurrentThread()->proc->egid = target_egid; + Core_GetCurrentThread()->proc->sgid = -1; + Core_GetCurrentThread()->proc->sgid = -1; OBOSS_HandControlTo(ctx, &aux); } diff --git a/src/oboskrnl/scheduler/sched_sys.c b/src/oboskrnl/scheduler/sched_sys.c index 955aa8ab..15421adb 100644 --- a/src/oboskrnl/scheduler/sched_sys.c +++ b/src/oboskrnl/scheduler/sched_sys.c @@ -663,29 +663,121 @@ obos_status Sys_WaitProcess(handle proc, int* wstatus, int options, uint32_t* pi return status; } +uid Sys_GetUid() +{ return Core_GetCurrentThread()->proc->ruid; } +gid Sys_GetGid() +{ return Core_GetCurrentThread()->proc->rgid; } -obos_status Sys_SetUid(uid to) +static bool check_unpriv_uid(uid uid) { - process* proc = Core_GetCurrentThread()->proc; - if (proc->euid != 0) - return OBOS_STATUS_ACCESS_DENIED; - proc->euid = to; + return (uid != Core_GetCurrentThread()->proc->ruid) && + (uid != Core_GetCurrentThread()->proc->euid) && + (uid != Core_GetCurrentThread()->proc->suid); +} +static bool check_unpriv_gid(gid gid) +{ + return (gid != Core_GetCurrentThread()->proc->rgid) && + (gid != Core_GetCurrentThread()->proc->egid) && + (gid != Core_GetCurrentThread()->proc->sgid); +} + +obos_status Sys_SetRESUid(uid ruid, uid euid, uid suid) +{ + if (Core_GetCurrentThread()->proc->euid != 0) + { + if ((ruid != -1) && !check_unpriv_uid(ruid)) + return OBOS_STATUS_ACCESS_DENIED; + if ((euid != -1) && !check_unpriv_uid(euid)) + return OBOS_STATUS_ACCESS_DENIED; + if ((suid != -1) && !check_unpriv_uid(suid)) + return OBOS_STATUS_ACCESS_DENIED; + if (ruid != -1) + Core_GetCurrentThread()->proc->ruid = ruid; + if (euid != -1) + Core_GetCurrentThread()->proc->euid = euid; + if (suid != -1) + Core_GetCurrentThread()->proc->suid = suid; + } + else + { + if (ruid != -1) Core_GetCurrentThread()->proc->ruid = ruid; + if (euid != -1) Core_GetCurrentThread()->proc->euid = euid; + if (suid != -1) Core_GetCurrentThread()->proc->suid = suid; + } return OBOS_STATUS_SUCCESS; } -obos_status Sys_SetGid(gid to) +obos_status Sys_SetRESGid(gid rgid, gid egid, gid sgid) { - process* proc = Core_GetCurrentThread()->proc; - if (proc->euid != 0) - return OBOS_STATUS_ACCESS_DENIED; - proc->egid = to; + if (Core_GetCurrentThread()->proc->euid != 0) + { + if ((rgid != -1) && !check_unpriv_gid(rgid)) + return OBOS_STATUS_ACCESS_DENIED; + if ((egid != -1) && !check_unpriv_gid(egid)) + return OBOS_STATUS_ACCESS_DENIED; + if ((sgid != -1) && !check_unpriv_gid(sgid)) + return OBOS_STATUS_ACCESS_DENIED; + if (rgid != -1) + Core_GetCurrentThread()->proc->rgid = rgid; + if (egid != -1) + Core_GetCurrentThread()->proc->egid = egid; + if (sgid != -1) + Core_GetCurrentThread()->proc->sgid = sgid; + } + else + { + if (rgid != -1) Core_GetCurrentThread()->proc->rgid = rgid; + if (egid != -1) Core_GetCurrentThread()->proc->egid = egid; + if (sgid != -1) Core_GetCurrentThread()->proc->sgid = sgid; + } return OBOS_STATUS_SUCCESS; } -uid Sys_GetUid() -{ return Core_GetCurrentThread()->proc->euid; } -gid Sys_GetGid() -{ return Core_GetCurrentThread()->proc->egid; } +obos_status Sys_GetRESUid(uid* ruid, uid* euid, uid* suid) +{ + if (ruid) + memcpy_k_to_usr(ruid, &Core_GetCurrentThread()->proc->ruid, sizeof(uid)); + if (euid) + memcpy_k_to_usr(euid, &Core_GetCurrentThread()->proc->euid, sizeof(uid)); + if (suid) + memcpy_k_to_usr(suid, &Core_GetCurrentThread()->proc->suid, sizeof(uid)); + return OBOS_STATUS_SUCCESS; +} + +obos_status Sys_GetRESGid(gid* rgid, gid* egid, gid* sgid) +{ + if (rgid) + memcpy_k_to_usr(rgid, &Core_GetCurrentThread()->proc->rgid, sizeof(gid)); + if (egid) + memcpy_k_to_usr(egid, &Core_GetCurrentThread()->proc->egid, sizeof(gid)); + if (sgid) + memcpy_k_to_usr(sgid, &Core_GetCurrentThread()->proc->sgid, sizeof(gid)); + return OBOS_STATUS_SUCCESS; +} + +obos_status Sys_SetUid(uid uid) +{ + if (Core_GetCurrentThread()->proc->euid == 0) + { + Core_GetCurrentThread()->proc->ruid = uid; + Core_GetCurrentThread()->proc->euid = uid; + Core_GetCurrentThread()->proc->suid = uid; + return OBOS_STATUS_SUCCESS; + } + return OBOS_STATUS_ACCESS_DENIED; +} + +obos_status Sys_SetGid(gid gid) +{ + if (Core_GetCurrentThread()->proc->euid == 0) + { + Core_GetCurrentThread()->proc->rgid = gid; + Core_GetCurrentThread()->proc->egid = gid; + Core_GetCurrentThread()->proc->sgid = gid; + return OBOS_STATUS_SUCCESS; + } + return OBOS_STATUS_ACCESS_DENIED; +} obos_status Sys_SetProcessGroup(handle process, uint32_t pgid) { diff --git a/src/oboskrnl/scheduler/sched_sys.h b/src/oboskrnl/scheduler/sched_sys.h index d0381dc5..673658b2 100644 --- a/src/oboskrnl/scheduler/sched_sys.h +++ b/src/oboskrnl/scheduler/sched_sys.h @@ -66,10 +66,14 @@ handle Sys_ProcessGetChildHandle(); // If HANDLE_ANY to make it choose an arbitrary child process. obos_status Sys_WaitProcess(handle proc, int* status, int options, uint32_t* ret_pid); -obos_status Sys_SetUid(uid to); -obos_status Sys_SetGid(gid to); uid Sys_GetUid(); gid Sys_GetGid(); +obos_status Sys_SetRESUid(uid ruid, uid euid, uid suid); +obos_status Sys_SetRESGid(gid rgid, gid egid, gid sgid); +obos_status Sys_GetRESUid(uid* ruid, uid* euid, uid* suid); +obos_status Sys_GetRESGid(gid* rgid, gid* egid, gid* sgid); +obos_status Sys_SetUid(uid uid); +obos_status Sys_SetGid(gid gid); obos_status Sys_SetProcessGroup(handle proc, uint32_t pgid); obos_status Sys_GetProcessGroup(handle proc, uint32_t* pgid); \ No newline at end of file diff --git a/src/oboskrnl/syscall.c b/src/oboskrnl/syscall.c index a990fc6d..2902ed99 100644 --- a/src/oboskrnl/syscall.c +++ b/src/oboskrnl/syscall.c @@ -458,6 +458,10 @@ uintptr_t OBOS_SyscallTable[SYSCALL_END-SYSCALL_BEGIN] = { (uintptr_t)Sys_RenameAt, (uintptr_t)Sys_UTimeNSAt, (uintptr_t)Sys_ThreadGetStack, + (uintptr_t)Sys_SetRESUid, + (uintptr_t)Sys_SetRESGid, + (uintptr_t)Sys_GetRESUid, + (uintptr_t)Sys_GetRESGid, }; // Arch syscall table is defined per-arch From d0a5452f1bd59becdb2c7056c6703e9586e11b72 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 21:44:00 -0500 Subject: [PATCH 66/96] misc: Fix compile error --- src/oboskrnl/driver_interface/drv_sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oboskrnl/driver_interface/drv_sys.c b/src/oboskrnl/driver_interface/drv_sys.c index b2e4d544..7fa55e7c 100644 --- a/src/oboskrnl/driver_interface/drv_sys.c +++ b/src/oboskrnl/driver_interface/drv_sys.c @@ -62,7 +62,7 @@ handle Sys_LoadDriver(const void* file, size_t szFile, obos_status* ustatus) } #define perm_check_impl(ret) do {\ - if (Core_GetCurrentThread()->proc->currentUID != ROOT_UID)\ + if (Core_GetCurrentThread()->proc->euid != ROOT_UID)\ return (ret);\ } while(0) #define perm_check() perm_check_impl(OBOS_STATUS_ACCESS_DENIED) From a808dd5f0c8bcc29a286efaa00a3aa98726301ea Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sat, 29 Nov 2025 22:05:56 -0500 Subject: [PATCH 67/96] misc: Add new syscalls to syscall name table --- src/oboskrnl/arch/m68k/syscall.c | 4 ++++ src/oboskrnl/arch/x86_64/syscall.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/oboskrnl/arch/m68k/syscall.c b/src/oboskrnl/arch/m68k/syscall.c index 0f04dc88..fc93dec1 100644 --- a/src/oboskrnl/arch/m68k/syscall.c +++ b/src/oboskrnl/arch/m68k/syscall.c @@ -161,6 +161,10 @@ const char *syscall_to_string[] = { "Sys_RenameAt", "Sys_UTimeNSAt", "Sys_ThreadGetStack", + "Sys_SetRESUid", + "Sys_SetRESGid", + "Sys_GetRESUid", + "Sys_GetRESGid", }; const char* status_to_string[] = { diff --git a/src/oboskrnl/arch/x86_64/syscall.c b/src/oboskrnl/arch/x86_64/syscall.c index 58f16c48..3efafb9c 100644 --- a/src/oboskrnl/arch/x86_64/syscall.c +++ b/src/oboskrnl/arch/x86_64/syscall.c @@ -246,6 +246,10 @@ const char* syscall_to_string[] = { "Sys_RenameAt", "Sys_UTimeNSAt", "Sys_ThreadGetStack", + "Sys_SetRESUid", + "Sys_SetRESGid", + "Sys_GetRESUid", + "Sys_GetRESGid", }; const char* status_to_string[] = { From d26ad93d6c35f1d06fb773da08e83aecec7b0ad9 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Sun, 30 Nov 2025 09:57:09 -0500 Subject: [PATCH 68/96] user-utils: fix compilation error --- src/user-utilities/x86_enable-kgdbstub.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/user-utilities/x86_enable-kgdbstub.c b/src/user-utilities/x86_enable-kgdbstub.c index ab27937f..f09f8b47 100644 --- a/src/user-utilities/x86_enable-kgdbstub.c +++ b/src/user-utilities/x86_enable-kgdbstub.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include From f3e2845efdf2550e67f0effca962f7ba68345a68 Mon Sep 17 00:00:00 2001 From: oberrow <72581470+oberrow@users.noreply.github.com> Date: Sun, 30 Nov 2025 14:26:31 -0500 Subject: [PATCH 69/96] sys: fix bug in Sys_ExecVE --- src/oboskrnl/execve.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/oboskrnl/execve.c b/src/oboskrnl/execve.c index 620ad9bd..12c2f6d6 100644 --- a/src/oboskrnl/execve.c +++ b/src/oboskrnl/execve.c @@ -311,8 +311,8 @@ obos_status Sys_ExecVE(const char* upath, char* const* argv, char* const* envp) Core_GetCurrentThread()->proc->euid = target_euid; Core_GetCurrentThread()->proc->egid = target_egid; - Core_GetCurrentThread()->proc->sgid = -1; - Core_GetCurrentThread()->proc->sgid = -1; + Core_GetCurrentThread()->proc->sgid = target_euid; + Core_GetCurrentThread()->proc->sgid = target_egid; OBOSS_HandControlTo(ctx, &aux); } From 4627885cf0950c0edb6aeccda43740287edcaa47 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Mon, 1 Dec 2025 18:22:30 -0500 Subject: [PATCH 70/96] sys: Implement permission checking for power control syscalls --- src/oboskrnl/syscall.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/oboskrnl/syscall.c b/src/oboskrnl/syscall.c index 2902ed99..b0ee2b30 100644 --- a/src/oboskrnl/syscall.c +++ b/src/oboskrnl/syscall.c @@ -320,15 +320,37 @@ obos_status Sys_ThreadGetStack(handle thr, void** stack_base, size_t *stack_size return OBOS_STATUS_SUCCESS; } +obos_status Sys_Shutdown() +{ + if (Core_GetCurrentThread()->proc->euid != 0) + return OBOS_STATUS_ACCESS_DENIED; + OBOS_Shutdown(); + OBOS_UNREACHABLE; +} +obos_status Sys_Reboot() +{ + if (Core_GetCurrentThread()->proc->euid != 0) + return OBOS_STATUS_ACCESS_DENIED; + OBOS_Reboot(); + OBOS_UNREACHABLE; +} +obos_status Sys_Suspend() +{ + if (Core_GetCurrentThread()->proc->euid != 0) + return OBOS_STATUS_ACCESS_DENIED; + OBOS_Suspend(); + OBOS_UNREACHABLE; +} + uintptr_t OBOS_SyscallTable[SYSCALL_END-SYSCALL_BEGIN] = { (uintptr_t)Core_ExitCurrentThread, (uintptr_t)Core_Yield, - (uintptr_t)OBOS_Reboot, - (uintptr_t)OBOS_Shutdown, + (uintptr_t)Sys_Reboot, + (uintptr_t)Sys_Shutdown, (uintptr_t)Sys_HandleClose, (uintptr_t)Sys_HandleClone, (uintptr_t)Sys_ThreadContextCreate, // 6 - (uintptr_t)OBOS_Suspend, + (uintptr_t)Sys_Suspend, (uintptr_t)Sys_ThreadOpen, (uintptr_t)Sys_ThreadCreate, (uintptr_t)Sys_ThreadReady, From f204f4d51ea0aff78e7d550f8b05f811b470d4a7 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Mon, 1 Dec 2025 18:23:03 -0500 Subject: [PATCH 71/96] misc: Fix bugs with UID/GID code --- src/oboskrnl/scheduler/process.c | 6 ++++ src/oboskrnl/vfs/create.c | 58 +++++++++++++++++--------------- src/oboskrnl/vfs/dirent.c | 55 ++++++++++++++++++++++++++---- src/oboskrnl/vfs/fd.c | 41 +++++----------------- src/oboskrnl/vfs/fd_sys.c | 15 ++++++++- src/oboskrnl/vfs/tty.c | 2 ++ src/oboskrnl/vfs/vnode.h | 4 ++- 7 files changed, 112 insertions(+), 69 deletions(-) diff --git a/src/oboskrnl/scheduler/process.c b/src/oboskrnl/scheduler/process.c index acdc09af..36569a20 100644 --- a/src/oboskrnl/scheduler/process.c +++ b/src/oboskrnl/scheduler/process.c @@ -86,6 +86,12 @@ OBOS_PAGEABLE_FUNCTION obos_status Core_ProcessStart(process* proc, thread* main proc->prev = proc->parent->children.tail; proc->parent->children.tail = proc; proc->parent->children.nChildren++; + proc->ruid = proc->parent->ruid; + proc->euid = proc->parent->euid; + proc->suid = proc->parent->suid; + proc->rgid = proc->parent->rgid; + proc->egid = proc->parent->egid; + proc->sgid = proc->parent->sgid; proc->refcount++; Core_SetProcessGroup(proc, proc->parent->pgrp->pgid); proc->waiting_threads = WAITABLE_HEADER_INITIALIZE(false, true); diff --git a/src/oboskrnl/vfs/create.c b/src/oboskrnl/vfs/create.c index 772cab74..a1fb8f09 100644 --- a/src/oboskrnl/vfs/create.c +++ b/src/oboskrnl/vfs/create.c @@ -23,27 +23,6 @@ #include #include -static bool has_write_perm(vnode* parent) -{ - uid current_uid = Core_GetCurrentThread()->proc->euid; - uid current_gid = Core_GetCurrentThread()->proc->egid; - if (parent->flags & VFLAGS_MOUNTPOINT) - { - drv_fs_info info = {}; - parent->un.mounted->fs_driver->driver->header.ftable.stat_fs_info(parent->un.mounted->device, &info); - if (parent->uid == current_uid || parent->gid == current_gid) - return ~info.flags & FS_FLAGS_RDONLY; - else - return false; - } - if (parent->uid == current_uid) - return parent->perm.owner_write; - else if (parent->gid == current_gid) - return parent->perm.group_write; - else - return parent->perm.other_write; -} - #ifdef __x86_64__ # include #endif @@ -54,13 +33,21 @@ obos_status Vfs_CreateNode(dirent* parent, const char* name, uint32_t vtype, fil parent = Vfs_Root; if (!name || !vtype || vtype >= VNODE_TYPE_BAD) return OBOS_STATUS_INVALID_ARGUMENT; + + obos_status status = Vfs_Access(Core_GetCurrentThread()->proc->euid, + Core_GetCurrentThread()->proc->egid, + parent->vnode, + false, + true, + false); + if (obos_is_error(status)) + return status; + vnode* parent_vn = parent->vnode; if (!parent_vn) return OBOS_STATUS_INVALID_ARGUMENT; if (parent_vn->vtype != VNODE_TYPE_DIR) return OBOS_STATUS_INVALID_ARGUMENT; - if (!has_write_perm(parent_vn)) - return OBOS_STATUS_ACCESS_DENIED; mount *parent_mnt = parent_vn->flags & VFLAGS_MOUNTPOINT ? parent_vn->un.mounted: parent_vn->mount_point; @@ -114,7 +101,7 @@ obos_status Vfs_CreateNode(dirent* parent, const char* name, uint32_t vtype, fil OBOS_InitString(&ent->name, name); ent->vnode = vn; vnode* mount_vn = parent_mnt->device; - obos_status status = OBOS_STATUS_SUCCESS; + status = OBOS_STATUS_SUCCESS; if (parent_mnt->fs_driver->driver->header.flags & DRIVER_HEADER_DIRENT_CB_PATHS) { char* parent_path = VfsH_DirentPath(parent, parent_mnt->root); @@ -144,8 +131,14 @@ OBOS_EXPORT obos_status Vfs_UnlinkNode(dirent* node) return OBOS_STATUS_SUCCESS; if (node->d_children.nChildren) return OBOS_STATUS_IN_USE; // cannot remove a directory with children - if (!has_write_perm(node->d_parent->vnode)) - return OBOS_STATUS_ACCESS_DENIED; + obos_status status = Vfs_Access(Core_GetCurrentThread()->proc->euid, + Core_GetCurrentThread()->proc->egid, + node->d_parent->vnode, + false, + true, + false); + if (obos_is_error(status)) + return status; mount *parent_mnt = node->vnode->flags & VFLAGS_MOUNTPOINT ? node->vnode->un.mounted: @@ -156,7 +149,7 @@ OBOS_EXPORT obos_status Vfs_UnlinkNode(dirent* node) if (LIST_GET_NODE_COUNT(fd_list, &node->vnode->opened)) return OBOS_STATUS_IN_USE; // TODO: Handle correctly (when the last FD is closed, then free+delete the vnode) - obos_status status = OBOS_STATUS_SUCCESS; + status = OBOS_STATUS_SUCCESS; if (node->vnode->vtype == VNODE_TYPE_DIR || node->vnode->vtype == VNODE_TYPE_REG || node->vnode->vtype == VNODE_TYPE_LNK) { @@ -212,6 +205,15 @@ obos_status Vfs_RenameNode(dirent* node, dirent* newparent, const char* name) if (!header) return OBOS_STATUS_INVALID_ARGUMENT; + obos_status status = Vfs_Access(Core_GetCurrentThread()->proc->euid, + Core_GetCurrentThread()->proc->egid, + (newparent ? newparent : node->d_parent)->vnode, + false, + true, + false); + if (obos_is_error(status)) + return status; + // Rename the entry if (!newparent || newparent == node->d_parent) { @@ -268,7 +270,7 @@ obos_status Vfs_RenameNode(dirent* node, dirent* newparent, const char* name) // Move and rename the entry. - obos_status status = OBOS_STATUS_SUCCESS; + status = OBOS_STATUS_SUCCESS; if (header->flags & DRIVER_HEADER_DIRENT_CB_PATHS) { char* node_path = VfsH_DirentPath(node, Vfs_Root); diff --git a/src/oboskrnl/vfs/dirent.c b/src/oboskrnl/vfs/dirent.c index beb13dd2..920ef43c 100644 --- a/src/oboskrnl/vfs/dirent.c +++ b/src/oboskrnl/vfs/dirent.c @@ -665,12 +665,7 @@ static bool check_chdir_perms(dirent* ent) uid uid = Core_GetCurrentThread()->proc->euid; gid gid = Core_GetCurrentThread()->proc->egid; - if (uid == ent->vnode->uid) - return ent->vnode->perm.owner_exec; - else if (gid == ent->vnode->gid) - return ent->vnode->perm.group_exec; - else - return ent->vnode->perm.other_exec; + return Vfs_Access(uid, gid, ent->vnode, false, false, true) == OBOS_STATUS_SUCCESS; } obos_status VfsH_Chdir(void* target_, const char *path) @@ -799,3 +794,51 @@ mount* Vfs_GetVnodeMount(vnode* vn) return nullptr; return vn->flags & VFLAGS_MOUNTPOINT ? vn->un.mounted : vn->mount_point; } + +obos_status Vfs_Access(uid asUid, gid asGid, vnode* vn, bool read, bool write, bool exec) +{ + if (write) + { + drv_fs_info info = {}; + driver_header* header = Vfs_GetVnodeDriver(vn); + mount* mount = Vfs_GetVnodeMount(vn); + if (header && mount && header->ftable.stat_fs_info) + header->ftable.stat_fs_info(mount->device, &info); + if (info.flags & FS_FLAGS_RDONLY) + return OBOS_STATUS_READ_ONLY; + } + + if (vn->uid == asUid || asUid == 0) + { + if (!vn->perm.owner_read && read) + return OBOS_STATUS_ACCESS_DENIED; + else if (!vn->perm.owner_write && write) + return OBOS_STATUS_ACCESS_DENIED; + else if (!vn->perm.owner_exec && exec) + return OBOS_STATUS_ACCESS_DENIED; + else + return OBOS_STATUS_SUCCESS; + } + else if (vn->gid == asGid) + { + if (!vn->perm.group_read && read) + return OBOS_STATUS_ACCESS_DENIED; + else if (!vn->perm.group_write && write) + return OBOS_STATUS_ACCESS_DENIED; + else if (!vn->perm.group_exec && exec) + return OBOS_STATUS_ACCESS_DENIED; + else + return OBOS_STATUS_SUCCESS; + } + else + { + if (!vn->perm.other_read && read) + return OBOS_STATUS_ACCESS_DENIED; + else if (!vn->perm.other_write && write) + return OBOS_STATUS_ACCESS_DENIED; + else if (!vn->perm.other_exec && exec) + return OBOS_STATUS_ACCESS_DENIED; + else + return OBOS_STATUS_SUCCESS; + } +} \ No newline at end of file diff --git a/src/oboskrnl/vfs/fd.c b/src/oboskrnl/vfs/fd.c index 74789443..5ad833ea 100644 --- a/src/oboskrnl/vfs/fd.c +++ b/src/oboskrnl/vfs/fd.c @@ -94,39 +94,14 @@ OBOS_EXPORT obos_status Vfs_FdOpenVnode(fd* const desc, void* vn, uint32_t oflag desc->flags |= FD_FLAGS_OPEN; desc->flags |= FD_FLAGS_READ; desc->flags |= FD_FLAGS_WRITE; - if (desc->vn->uid == Core_GetCurrentThread()->proc->euid || Core_GetCurrentThread()->proc->euid == 0) - { - // We have owner perms. - struct vnode* const vn = desc->vn; - if (!vn->perm.owner_read) - desc->flags &= ~FD_FLAGS_READ; - if (!vn->perm.owner_write) - desc->flags &= ~FD_FLAGS_WRITE; - if (oflags & FD_OFLAGS_EXECUTE && !vn->perm.owner_exec) - return OBOS_STATUS_ACCESS_DENIED; - } - else if (desc->vn->gid == Core_GetCurrentThread()->proc->egid) - { - // We have group perms. - struct vnode* const vn = desc->vn; - if (!vn->perm.group_read) - desc->flags &= ~FD_FLAGS_READ; - if (!vn->perm.group_write) - desc->flags &= ~FD_FLAGS_WRITE; - if (oflags & FD_OFLAGS_EXECUTE && !vn->perm.group_exec) - return OBOS_STATUS_ACCESS_DENIED; - } - else - { - // We have other perms. - struct vnode* const vn = desc->vn; - if (!vn->perm.other_read) - desc->flags &= ~FD_FLAGS_READ; - if (!vn->perm.other_write) - desc->flags &= ~FD_FLAGS_WRITE; - if (oflags & FD_OFLAGS_EXECUTE && !vn->perm.other_exec) - return OBOS_STATUS_ACCESS_DENIED; - } + obos_status status = Vfs_Access(Core_GetCurrentThread()->proc->euid, + Core_GetCurrentThread()->proc->egid, + vnode, + oflags & FD_OFLAGS_READ, + oflags & FD_OFLAGS_WRITE, + oflags & FD_OFLAGS_EXECUTE); + if (obos_is_error(status)) + return status; if (~oflags & FD_OFLAGS_READ) desc->flags &= ~FD_FLAGS_READ; if (~oflags & FD_OFLAGS_WRITE) diff --git a/src/oboskrnl/vfs/fd_sys.c b/src/oboskrnl/vfs/fd_sys.c index f3a3f1eb..3fa5bb5c 100644 --- a/src/oboskrnl/vfs/fd_sys.c +++ b/src/oboskrnl/vfs/fd_sys.c @@ -864,6 +864,18 @@ handle Sys_OpenDir(const char* upath, obos_status *statusp) dent = VfsH_FollowLink(dent); + if (dent->vnode) + { + obos_status status = Vfs_Access(Core_GetCurrentThread()->proc->euid, + Core_GetCurrentThread()->proc->egid, + dent->vnode, + true, + false, + false); + if (obos_is_error(status)) + return status; + } + Vfs_PopulateDirectory(dent); handle_desc* desc = nullptr; @@ -2918,7 +2930,8 @@ obos_status Sys_FChmodAt(handle dirfd, const char* upathname, int mode, int flag file_perm real_mode = unix_to_obos_mode(mode, true); - driver_header* header = Vfs_GetVnodeDriver(target); + mount* mount = Vfs_GetVnodeMount(target); + driver_header* header = Vfs_GetVnodeDriver(mount->root->vnode); if (!header) { status = OBOS_STATUS_INTERNAL_ERROR; diff --git a/src/oboskrnl/vfs/tty.c b/src/oboskrnl/vfs/tty.c index 84e3da61..d75fc28e 100644 --- a/src/oboskrnl/vfs/tty.c +++ b/src/oboskrnl/vfs/tty.c @@ -566,6 +566,8 @@ obos_status Vfs_RegisterTTY(const tty_interface *i, dirent **onode, bool pty) VNODE_TYPE_CHR); vn->flags |= VFLAGS_IS_TTY; vn->data = tty; + vn->perm.other_read = true; + vn->perm.other_write = true; size_t index = pty ? last_pty_index++ : last_tty_index++; size_t szName = snprintf(nullptr, 0, "tty%ld", index); char *name = nullptr; diff --git a/src/oboskrnl/vfs/vnode.h b/src/oboskrnl/vfs/vnode.h index ec91ee5e..10d0b099 100644 --- a/src/oboskrnl/vfs/vnode.h +++ b/src/oboskrnl/vfs/vnode.h @@ -119,4 +119,6 @@ OBOS_EXPORT vnode* Drv_AllocateVNode(driver_id* drv, dev_desc desc, size_t files OBOS_EXPORT driver_header* Vfs_GetVnodeDriver(vnode* vn); // For files that can and can't have I/O on them (directories, symbolic links, FIFOs, regular files, CHR/BLK devices, and sockets) OBOS_EXPORT driver_header* Vfs_GetVnodeDriverStat(vnode* vn); -OBOS_EXPORT struct mount* Vfs_GetVnodeMount(vnode* vn); \ No newline at end of file +OBOS_EXPORT struct mount* Vfs_GetVnodeMount(vnode* vn); + +OBOS_EXPORT obos_status Vfs_Access(uid asUid, gid asGid, vnode* vn, bool read, bool write, bool exec); \ No newline at end of file From d85efc9c63981069aaf2c1387fd17183292d5192 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Mon, 1 Dec 2025 18:23:16 -0500 Subject: [PATCH 72/96] user-utils: Add a login program --- src/user-utilities/CMakeLists.txt | 4 +- src/user-utilities/login.c | 265 ++++++++++++++++++++++++++++++ 2 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 src/user-utilities/login.c diff --git a/src/user-utilities/CMakeLists.txt b/src/user-utilities/CMakeLists.txt index a2fe18c0..eb538c32 100644 --- a/src/user-utilities/CMakeLists.txt +++ b/src/user-utilities/CMakeLists.txt @@ -29,8 +29,10 @@ add_executable (lsmod "lsmod.c") add_executable (ldmod "ldmod.c") add_executable (stmod "stmod.c") add_executable (rmmod "rmmod.c") +add_executable (login "login.c") +target_link_libraries(login crypt) install(TARGETS powerctl klog-level fork-test mem-usage mount umount swapon mkswap sync-anon) -install(TARGETS lsmod ldmod stmod rmmod DESTINATION sbin) +install(TARGETS lsmod ldmod stmod rmmod login DESTINATION sbin) if (${OBOS_ARCHITECTURE} STREQUAL "x86_64") add_executable(obos-gettime "x86_obos-gettime.c") diff --git a/src/user-utilities/login.c b/src/user-utilities/login.c new file mode 100644 index 00000000..56d67515 --- /dev/null +++ b/src/user-utilities/login.c @@ -0,0 +1,265 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if __obos__ +#include +#endif + +char g_hostname[32]; + +static char* readline() +{ + char* buf = NULL; + size_t size = 0; + while (1) + { + char ch = getchar(); + if (ch == '\n') + break; + buf = realloc(buf, ++size); + buf[size-1] = ch; + } + buf = realloc(buf, size + 1); + buf[size] = 0; + return buf; +} + +static void prompt(char** ousername, char** opassword) +{ + struct termios tc = {}; + tcgetattr(0, &tc); + tc.c_lflag |= ECHO; + tcsetattr(0, 0, &tc); + + fprintf(stderr, "%.*s login: ", (int)sizeof(g_hostname), g_hostname); + *ousername = readline(); + fprintf(stderr, "%s password: ", *ousername); + struct termios old_tc = tc; + tc.c_lflag &= ~ECHO; + tc.c_lflag |= ECHONL; + tcsetattr(0, 0, &tc); + *opassword = readline(); + tcsetattr(0, 0, &old_tc); +} + +#define invalid_pwd_timeout (5) +#define invalid_pwd_msg "Invalid username or password" + +static int login(char* username, char* password, struct passwd** ouser) +{ + struct passwd* user = getpwnam(username); + if (!user) + return 0; + + // Check password + if (strcmp(user->pw_passwd, "x") == 0) + { + struct spwd* ent = getspnam(user->pw_name); + if (!ent) + { + endspent(); + if (errno == 0) + return 1; // authenticated + else + { + perror("getspnam"); + return 0; + } + } + if (strlen(ent->sp_pwdp) == 0) + { + endspent(); + goto success; + } + // Verify password. + // NOTE: If the user account cannot be signed in using a password, + // then this code will still be able to handle that, as ent->sp_pwdp + // would be invalid. + char* hash = crypt(password, ent->sp_pwdp); + if (!hash) + { + perror("crypt_ra"); + return 0; + } + if (strcmp(hash, ent->sp_pwdp) == 0) + { + endspent(); + goto success; + } + endspent(); + return 0; + } + else + { + if (strcmp(user->pw_passwd, password) == 0) + goto success; + return 0; + } + + success: + + *ouser = user; + return 1; +} + +int do_waitpid(int child) +{ + int status = 0; + do { + if (waitpid(child, &status, 0) == 0) + break; + switch (errno) { + case EINTR: + errno = 0; + continue; + case ECHILD: + break; + case 0: + break; + default: + status = -1; + perror("waitpid"); + continue; + } + break; + } while(1); + return status; +} + +int main() +{ + if (geteuid() != 0) + { + fprintf(stderr, "FATAL: euid != 0\n"); + return -1; + } + + signal(SIGINT, SIG_IGN); + + gethostname(g_hostname, sizeof(g_hostname)); + + // oh god forgive me. + system("reset"); + + while (1) + { + char* username = NULL; + char* password = NULL; + prompt(&username, &password); + + struct passwd* user = NULL; + + if (!login(username, password, &user)) + { + sleep(invalid_pwd_timeout); + puts(invalid_pwd_msg); + free(username); + memset(password, 0xde, strlen(password)); +#if __obos__ + // Make sure the cleared password is noted in the swap. + // Note: Ideally we would not have the password on swap at all. + // (TODO) + syscall0(Sys_SyncAnonPages); +#endif + free(password); + continue; + } + + free(username); + memset(password, 0xde, strlen(password)); +#if __obos__ + // Make sure the cleared password is noted in the swap. + // Ideally we would not have the password on swap at all. + // (TODO) + syscall0(Sys_SyncAnonPages); +#endif + free(password); + + int child = fork(); + if (child == 0) + { + // TODO: Session IDs? + // TODO: Parse /etc/environment + + if (setresgid(user->pw_gid, user->pw_gid, user->pw_gid) != 0) + { + perror("setresgid"); + exit(-1); + } + + int ngroups = 0; + gid_t* groups = 0; + getgrouplist(user->pw_name, user->pw_gid, groups, &ngroups); + groups = calloc(ngroups, sizeof(gid_t)); + getgrouplist(user->pw_name, user->pw_gid, groups, &ngroups); + + int ret = setgroups(ngroups, groups); + if (ret == -1) + { + switch (errno) { + case ENOSYS: + break; + default: + perror("setgroups"); + return -1; + } + } + + if (setresuid(user->pw_uid, user->pw_uid, user->pw_uid) != 0) + { + perror("setresuid"); + exit(-1); + } + + const char* term = getenv("TERM"); + clearenv(); + setenv("HOME", user->pw_dir, 1); + setenv("TERM", term, 1); + setenv("SHELL", user->pw_shell, 1); + setenv("USER", user->pw_name, 1); + setenv("LOGNAME", user->pw_name, 1); + // Sensible value? + if (user->pw_uid == 0) + setenv("PATH", "/usr/local/bin:/usr/bin:/usr/sbin", 1); + else + setenv("PATH", "/usr/local/bin:/usr/bin:/usr/local/games:/usr/games", 1); + char* argv[3] = { user->pw_shell, NULL, NULL }; + if (strcmp(basename(user->pw_shell), "bash") == 0) + argv[1] = "--login"; + + if (chdir(user->pw_dir) == -1) + { + perror("chdir(user->pw_dir)"); + return -1; + } + + execvp(user->pw_shell, argv); + + perror("execvp"); + return -1; + } + else + { + if (do_waitpid(child) == 0) + // god forgive me + system("reset"); + else + continue; + } + } + + return 0; +} \ No newline at end of file From ef4b856ad9e5d801a20cbb33ec0f2427b5e3de87 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Mon, 1 Dec 2025 18:33:01 -0500 Subject: [PATCH 73/96] user-utils: Do not reset terminal in login on start --- src/user-utilities/login.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/user-utilities/login.c b/src/user-utilities/login.c index 56d67515..2541522f 100644 --- a/src/user-utilities/login.c +++ b/src/user-utilities/login.c @@ -151,9 +151,6 @@ int main() gethostname(g_hostname, sizeof(g_hostname)); - // oh god forgive me. - system("reset"); - while (1) { char* username = NULL; From 38b424e35da67be8be806f300fa1b153f76299be Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Mon, 1 Dec 2025 18:38:53 -0500 Subject: [PATCH 74/96] sys: Fix bug with converting from a unix mode to a `struct file_perm` --- src/oboskrnl/vfs/fd_sys.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/oboskrnl/vfs/fd_sys.c b/src/oboskrnl/vfs/fd_sys.c index 3fa5bb5c..9a8a6b8b 100644 --- a/src/oboskrnl/vfs/fd_sys.c +++ b/src/oboskrnl/vfs/fd_sys.c @@ -90,6 +90,10 @@ static file_perm unix_to_obos_mode(uint32_t mode, bool respect_umask) real_mode.owner_write = true; if (mode & 0400) real_mode.owner_read = true; + if (mode & 04000) + real_mode.set_uid = true; + if (mode & 02000) + real_mode.set_uid = true; return real_mode; } obos_status Sys_FdOpenEx(handle desc, const char* upath, uint32_t oflags, uint32_t mode) From 3fbbda487b6dc2889333693bc363394bcbbe07eb Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Mon, 1 Dec 2025 18:41:23 -0500 Subject: [PATCH 75/96] sys: Fix bug with Sys_Stat --- src/oboskrnl/vfs/fd_sys.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/oboskrnl/vfs/fd_sys.c b/src/oboskrnl/vfs/fd_sys.c index 9a8a6b8b..8398c124 100644 --- a/src/oboskrnl/vfs/fd_sys.c +++ b/src/oboskrnl/vfs/fd_sys.c @@ -626,6 +626,10 @@ obos_status Sys_Stat(int fsfdt, handle desc, const char* upath, int flags, struc return status; st.st_size = to_stat->filesize; st.st_mode = 0; + if (to_stat->perm.set_uid) + st.st_mode |= 04000; + if (to_stat->perm.set_gid) + st.st_mode |= 02000; if (to_stat->perm.owner_read) st.st_mode |= 0400; if (to_stat->perm.owner_write) From c43cc83e5801d4ca080733ba7220e06bec8b4205 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Mon, 1 Dec 2025 18:43:17 -0500 Subject: [PATCH 76/96] sys: Bug fix --- src/oboskrnl/vfs/fd_sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oboskrnl/vfs/fd_sys.c b/src/oboskrnl/vfs/fd_sys.c index 8398c124..1dc134ea 100644 --- a/src/oboskrnl/vfs/fd_sys.c +++ b/src/oboskrnl/vfs/fd_sys.c @@ -93,7 +93,7 @@ static file_perm unix_to_obos_mode(uint32_t mode, bool respect_umask) if (mode & 04000) real_mode.set_uid = true; if (mode & 02000) - real_mode.set_uid = true; + real_mode.set_gid = true; return real_mode; } obos_status Sys_FdOpenEx(handle desc, const char* upath, uint32_t oflags, uint32_t mode) From 0959f121714a12b6d0757c1b0d35cacce9c0c07c Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Mon, 1 Dec 2025 21:05:54 -0500 Subject: [PATCH 77/96] sys: Fix security bug with chown --- src/oboskrnl/vfs/fd_sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oboskrnl/vfs/fd_sys.c b/src/oboskrnl/vfs/fd_sys.c index 1dc134ea..06d0389f 100644 --- a/src/oboskrnl/vfs/fd_sys.c +++ b/src/oboskrnl/vfs/fd_sys.c @@ -3051,7 +3051,7 @@ obos_status Sys_FChownAt(handle dirfd, const char *upathname, uid owner, gid gro have_target: OBOS_ENSURE(target); - if (target->uid != Sys_GetUid() && Sys_GetUid() != ROOT_UID) + if (Sys_GetUid() != ROOT_UID) { status = OBOS_STATUS_ACCESS_DENIED; goto fail; From edf76052d08b0bbf53a5a169c2a89155424b2ff5 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 07:41:44 -0500 Subject: [PATCH 78/96] vfs: Fix bug in socket implementation --- src/oboskrnl/vfs/socket.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/oboskrnl/vfs/socket.c b/src/oboskrnl/vfs/socket.c index c4ead232..6d255377 100644 --- a/src/oboskrnl/vfs/socket.c +++ b/src/oboskrnl/vfs/socket.c @@ -113,6 +113,8 @@ static obos_status reference_device(dev_desc* pdesc) static obos_status unreference_device(dev_desc desc) { socket_desc* socket = (void*)desc; + if (!socket) + return OBOS_STATUS_INVALID_ARGUMENT; if (!(--socket->refs)) socket->ops->free(socket); return OBOS_STATUS_SUCCESS; @@ -558,4 +560,4 @@ void VfsH_InitializeSocketInterface() NetH_AddSocketBackend(&Net_TCPSocketBackend); NetH_AddSocketBackend(&Vfs_LocalDgramSocketBackend); NetH_AddSocketBackend(&Vfs_LocalStreamSocketBackend); -} \ No newline at end of file +} From 10bfab08dafc9736505edb771eb426a15264add5 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 07:46:26 -0500 Subject: [PATCH 79/96] vfs: fix bug in Vfs_UnlinkNode --- src/oboskrnl/vfs/create.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/oboskrnl/vfs/create.c b/src/oboskrnl/vfs/create.c index a1fb8f09..a4773b4a 100644 --- a/src/oboskrnl/vfs/create.c +++ b/src/oboskrnl/vfs/create.c @@ -48,10 +48,16 @@ obos_status Vfs_CreateNode(dirent* parent, const char* name, uint32_t vtype, fil return OBOS_STATUS_INVALID_ARGUMENT; if (parent_vn->vtype != VNODE_TYPE_DIR) return OBOS_STATUS_INVALID_ARGUMENT; - mount *parent_mnt = parent_vn->flags & VFLAGS_MOUNTPOINT ? - parent_vn->un.mounted: - parent_vn->mount_point; - driver_ftable* ftable = &parent_mnt->fs_driver->driver->header.ftable; + + mount *parent_mnt = Vfs_GetVnodeMount(parent->vnode); + driver_header* header = Vfs_GetVnodeDriver(parent_mnt->root->vnode); + if (!header) + return OBOS_STATUS_INTERNAL_ERROR; + + driver_ftable* ftable = &header->ftable; + if (!ftable->remove_file) + return OBOS_STATUS_UNIMPLEMENTED; + if (!ftable->mk_file) return OBOS_STATUS_UNIMPLEMENTED; @@ -140,12 +146,18 @@ OBOS_EXPORT obos_status Vfs_UnlinkNode(dirent* node) if (obos_is_error(status)) return status; - mount *parent_mnt = node->vnode->flags & VFLAGS_MOUNTPOINT ? - node->vnode->un.mounted: - node->vnode->mount_point; - driver_ftable* ftable = &parent_mnt->fs_driver->driver->header.ftable; + mount *parent_mnt = Vfs_GetVnodeMount(node->vnode); + if (!parent_mnt) + return OBOS_STATUS_INTERNAL_ERROR; + OBOS_ENSURE(parent_mnt->root); + driver_header* header = Vfs_GetVnodeDriver(parent_mnt->root->vnode); + if (!header) + return OBOS_STATUS_INTERNAL_ERROR; + + driver_ftable* ftable = &header->ftable; if (!ftable->remove_file) return OBOS_STATUS_UNIMPLEMENTED; + if (LIST_GET_NODE_COUNT(fd_list, &node->vnode->opened)) return OBOS_STATUS_IN_USE; // TODO: Handle correctly (when the last FD is closed, then free+delete the vnode) From 7ff6261cb6721dc7a8c8df7c3895f4241f55b757 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 07:58:12 -0500 Subject: [PATCH 80/96] user-utils: Set ICRNL --- src/user-utilities/login.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/user-utilities/login.c b/src/user-utilities/login.c index 2541522f..1ab324a9 100644 --- a/src/user-utilities/login.c +++ b/src/user-utilities/login.c @@ -42,6 +42,7 @@ static void prompt(char** ousername, char** opassword) struct termios tc = {}; tcgetattr(0, &tc); tc.c_lflag |= ECHO; + tc.c_iflag |= ICRNL; tcsetattr(0, 0, &tc); fprintf(stderr, "%.*s login: ", (int)sizeof(g_hostname), g_hostname); From bc4e1cb83f206d05798cf8671b5301a427e8b56c Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 08:26:05 -0500 Subject: [PATCH 81/96] misc: add login prompt option to limine.conf --- config/limine.conf | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/config/limine.conf b/config/limine.conf index 79f32363..2282dd43 100644 --- a/config/limine.conf +++ b/config/limine.conf @@ -15,3 +15,18 @@ timeout: 5 module_string: BUMP_REGION path: boot():/obos/oboskrnl cmdline: initrd-module=initrd initrd-driver-module=initrd_driver root-fs-partid initrd load-modules=/libps2,/extfs initial-swap-size=67108864 log-level=1 init-args /usr/bin/bash --login +/OBOS (Login) + protocol: limine + comment: OBOS (Login Prompt) + + paging_mode: 4level + module_path: boot():/obos/initrd.tar + module_string: initrd + module_path: boot():/obos/initrd + module_string: initrd_driver + module_path: boot():/obos/flanterm_buff + module_string: FLANTERM_BUFF + module_path: boot():/obos/flanterm_buff + module_string: BUMP_REGION + path: boot():/obos/oboskrnl + cmdline: initrd-module=initrd initrd-driver-module=initrd_driver root-fs-partid initrd load-modules=/libps2,/extfs initial-swap-size=67108864 log-level=1 init-args /usr/bin/bash --login -c login \ No newline at end of file From 8cba7aa1d603f72f8d555b23c77ca9856a260c03 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 08:32:39 -0500 Subject: [PATCH 82/96] user-utils: ignore SIGTSTP in login --- src/user-utilities/login.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/user-utilities/login.c b/src/user-utilities/login.c index 1ab324a9..ab7b4993 100644 --- a/src/user-utilities/login.c +++ b/src/user-utilities/login.c @@ -149,6 +149,7 @@ int main() } signal(SIGINT, SIG_IGN); + signal(SIGTSTP, SIG_IGN); gethostname(g_hostname, sizeof(g_hostname)); From f33fb26a6db1a10041eb50aabed11dab18090059 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 08:55:26 -0500 Subject: [PATCH 83/96] vfs/tty: fix bug with line editing --- src/oboskrnl/vfs/tty.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/oboskrnl/vfs/tty.c b/src/oboskrnl/vfs/tty.c index d75fc28e..8cca68b7 100644 --- a/src/oboskrnl/vfs/tty.c +++ b/src/oboskrnl/vfs/tty.c @@ -439,16 +439,29 @@ static size_t strrfind(const char* str, char ch) return SIZE_MAX; } +static bool char_is_nl(tty* tty, char ch) +{ + return ch == '\n' || ch == '\r' || tty->termios.cc[VEOL] == ch || tty->termios.cc[VEOL2] == ch; +} + void erase_bytes(tty* tty, size_t nBytesToErase) { if (nBytesToErase == SIZE_MAX) nBytesToErase = tty->input_buffer.out_ptr % tty->input_buffer.size; for (size_t j = 0; j < nBytesToErase && tty->input_buffer.out_ptr > 0; j++) { + if (char_is_nl(tty, tty->input_buffer.buf[tty->input_buffer.out_ptr]) || char_is_nl(tty, tty->input_buffer.buf[tty->input_buffer.out_ptr-1])) + { + if (tty->input_buffer.buf[tty->input_buffer.out_ptr] != '\n' && tty->input_buffer.buf[tty->input_buffer.out_ptr-1] == '\n') + tty->input_buffer.out_ptr--; + if (tty->input_buffer.in_ptr > tty->input_buffer.out_ptr) + tty->input_buffer.in_ptr = tty->input_buffer.out_ptr; + break; + } if (tty->input_buffer.out_ptr == tty->input_buffer.in_ptr) tty->input_buffer.in_ptr--; tty->input_buffer.buf[tty->input_buffer.out_ptr-- % tty->input_buffer.size] = 0; - tty->interface.write(tty, "\b", 1); + tty->interface.write(tty, "\b \b", 3); } } @@ -461,6 +474,7 @@ static void data_ready(void *tty_, const void *buf, size_t nBytesReady) { tty *tty = (struct tty *)tty_; const uint8_t *buf8 = buf; + bool inserted_any_bytes = false; for (size_t i = 0; i < nBytesReady; i++) { char ch = buf8[i]; @@ -517,10 +531,11 @@ static void data_ready(void *tty_, const void *buf, size_t nBytesReady) } else tty->quoted = false; - if (tty->termios.lflag & ECHO) - tty_write_sync((dev_desc)tty, &ch, 1, 0, nullptr); if (!insert_byte) continue; + inserted_any_bytes = true; + if (tty->termios.lflag & ECHO) + tty_write_sync((dev_desc)tty, &ch, 1, 0, nullptr); if (tty->termios.lflag & ICANON) { if (tty->termios.lflag & ECHONL && ch == '\n') @@ -532,6 +547,8 @@ static void data_ready(void *tty_, const void *buf, size_t nBytesReady) toupper(ch & mask) : (ch & mask); } + if (!inserted_any_bytes) + return; if (tty->termios.lflag & ICANON) find_eol(tty, &tty->input_buffer.buf[(tty->input_buffer.out_ptr - 1) % tty->input_buffer.size]) == SIZE_MAX ? (void)0 : Core_EventSet(&tty->data_ready_evnt, true); else From 0aa2378c0029f34539a8f04a4e537c0ae7d00dd6 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 08:55:45 -0500 Subject: [PATCH 84/96] user-utils: do not accept empty usernames in login utility --- src/user-utilities/login.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/user-utilities/login.c b/src/user-utilities/login.c index ab7b4993..6b0c52e4 100644 --- a/src/user-utilities/login.c +++ b/src/user-utilities/login.c @@ -45,8 +45,14 @@ static void prompt(char** ousername, char** opassword) tc.c_iflag |= ICRNL; tcsetattr(0, 0, &tc); + retry_uname_prompt: fprintf(stderr, "%.*s login: ", (int)sizeof(g_hostname), g_hostname); *ousername = readline(); + if (!strlen(*ousername)) + { + free(*ousername); + goto retry_uname_prompt; + } fprintf(stderr, "%s password: ", *ousername); struct termios old_tc = tc; tc.c_lflag &= ~ECHO; From abf07e641152b9d9838f35672418a72cb8bc01eb Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 09:00:30 -0500 Subject: [PATCH 85/96] vfs/tty: fix bug --- src/oboskrnl/vfs/tty.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/oboskrnl/vfs/tty.c b/src/oboskrnl/vfs/tty.c index 8cca68b7..33a0cb45 100644 --- a/src/oboskrnl/vfs/tty.c +++ b/src/oboskrnl/vfs/tty.c @@ -441,7 +441,9 @@ static size_t strrfind(const char* str, char ch) static bool char_is_nl(tty* tty, char ch) { - return ch == '\n' || ch == '\r' || tty->termios.cc[VEOL] == ch || tty->termios.cc[VEOL2] == ch; + return ch == '\n' || ch == '\r' || + (tty->termios.cc[VEOL] == ch && tty->termios.cc[VEOL]) || + (tty->termios.cc[VEOL2] == ch && tty->termios.cc[VEOL2]); } void erase_bytes(tty* tty, size_t nBytesToErase) From 96a4eef9e0c84b9e9261b9b9acce73a8928329d4 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 09:11:15 -0500 Subject: [PATCH 86/96] sys: fix page fault in Sys_LoadDriver --- src/oboskrnl/driver_interface/drv_sys.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/oboskrnl/driver_interface/drv_sys.c b/src/oboskrnl/driver_interface/drv_sys.c index 7fa55e7c..2d99ee15 100644 --- a/src/oboskrnl/driver_interface/drv_sys.c +++ b/src/oboskrnl/driver_interface/drv_sys.c @@ -26,7 +26,8 @@ handle Sys_LoadDriver(const void* file, size_t szFile, obos_status* ustatus) { if (Core_GetCurrentThread()->proc->euid != ROOT_UID) { - if (ustatus) *ustatus = OBOS_STATUS_ACCESS_DENIED; + obos_status status = OBOS_STATUS_ACCESS_DENIED; + if (ustatus) memcpy_k_to_usr(ustatus, &status, sizeof(obos_status)); return HANDLE_INVALID; } From 0a3e41174ba91c489553ffe84ba73c5525bc7b55 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 09:31:41 -0500 Subject: [PATCH 87/96] init: print motd after initializing NM --- src/init/main.c | 6 +++--- src/init/nm.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/init/main.c b/src/init/main.c index 78954dda..16d945a6 100644 --- a/src/init/main.c +++ b/src/init/main.c @@ -144,13 +144,13 @@ int main(int argc, char** argv) setenv("PATH", "/usr/bin:/bin:/usr/sbin:/sbin", 1); + nm_initialize_hostname(); + nm_initialize_interfaces("/etc/interfaces.json"); + int ret = print_motd(); if (ret != 0) return ret; - nm_initialize_hostname(); - nm_initialize_interfaces("/etc/interfaces.json"); - syscall1(Sys_SetKLogLevel, final_log_level); // Start a shell, I guess. diff --git a/src/init/nm.c b/src/init/nm.c index ba4e8811..9a2546d4 100644 --- a/src/init/nm.c +++ b/src/init/nm.c @@ -284,7 +284,7 @@ void nm_initialize_interfaces(const char* config_file) if (nm_initialize_interface(obj)) nInterfacesInitialized++; } - printf("NM: Initialized %ld interfaces (%ld failed)\n", nInterfacesInitialized, nInterfaces-nInterfacesInitialized); + printf("NM: Initialized %ld interfaces (%ld failed)\n\n", nInterfacesInitialized, nInterfaces-nInterfacesInitialized); cJSON_Delete(top_level); } From 23d7af4670f7fc9431832fdfa6855466f481c85d Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 09:32:47 -0500 Subject: [PATCH 88/96] misc: do permission check in signal code --- src/oboskrnl/signal.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/oboskrnl/signal.c b/src/oboskrnl/signal.c index a6760777..3871a937 100644 --- a/src/oboskrnl/signal.c +++ b/src/oboskrnl/signal.c @@ -45,6 +45,8 @@ obos_status OBOS_Kill(struct thread* as, struct thread* thr, int sigval) return OBOS_STATUS_INVALID_OPERATION; if (thr->proc->pid == 0) return OBOS_STATUS_INVALID_OPERATION; + if (thr->proc->euid != as->proc->euid && as->proc->euid != 0) + return OBOS_STATUS_ACCESS_DENIED; if (sigval == 0) return OBOS_STATUS_SUCCESS; // see man fork.2, "If sig is 0, then no signal is sent, but existence and permission checks are still performed" @@ -207,8 +209,12 @@ obos_status OBOS_KillProcess(struct process* proc, int sigval) case SIGCONT: case SIGSTOP: case SIGTSTP: - OBOS_Kill(Core_GetCurrentThread(), thr, sigval); + { + obos_status status = OBOS_Kill(Core_GetCurrentThread(), thr, sigval); + if (obos_is_error(status)) + return status; continue; + } default: break; } From 2b484473b7705241049fa249d376e5f02d059cce Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 09:32:55 -0500 Subject: [PATCH 89/96] misc: add new screenshot --- screenshots/20251202_0930.png | Bin 0 -> 12005 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 screenshots/20251202_0930.png diff --git a/screenshots/20251202_0930.png b/screenshots/20251202_0930.png new file mode 100644 index 0000000000000000000000000000000000000000..fa9682cdb1476be02a4407b7246744cf4706d31b GIT binary patch literal 12005 zcmeHtXIN9wvi7C~5Cue}NL4|RBA}q5BcdQ6MM~%;D1ydNrH3L_h=2%K2u%g)1OlOV z1eA^np?3*I2pAwhD0g$t`JQ{vbN}Aw`*qfj>||%JwP(+~GxN@@9c`$u#lp;g zIeq@Ur?_b;%NyQi`_VJ~Uf|5*q1bs-B85n^Gb(TMb(PfLm@x;+R!;fhRh{FrP&AD-H_c zX|wzWkF4MKueZe#OfR(6zIhQx3rue`L}5b_QPk=`C z0#$&Gry=-y^)0*oUHKB<2>dA5JD2uz;icwIhEI`+9cta3<{o1)RJWqfHz|b2z6kXN zDRE;Me4H;4>%(yFS6Q_&SL4LFc1syhDDFlI(5UB8r124KOX< zXq-tfdZ$NHQbs^FLl7(DB5=>1m_VcYfGFk;aw?&rw`iA!Q6r`&-eAkgjs|FQ+H+#w z)KY;EGp`2DpSGB25HBu@2qRbVbhc;oJvj*g=@+&Hr>A3f_s62yO=ezt5 z|Hi4zmMD;;7Y$TYX@K(sl=%Sej<&ciDNCN+d9HTo^?N=vfW1Qsz?~bwwytjmF;*Gj zx&DE$6K-`+;N`epMd(;=d`S;FZ1&kg`&S^PcSf27 zBfED=AHO3@*Md$wRVtIHJ7fd^--30)X#jCVhQnDRa{LHvn5a%Y^W(Rz>8>vj>dy7q-q>N0iXeFZk?TuBu2rfwy5W@6SPfz9z+zW7@cny1A3_c-YK>_f<`v z@`iKfIuQZO8PM|GnoO4`iBP-rvnEyB3prJzq0g@&YKKNg$BWx44UiRh9&oj$9(s+J zgHg?*oaqYPlbPEApAVR5fDmi}T~(sEaCvnPiz-UK^kC9i?e@QeL@FqQR)s136u(*^ z^dPU!aa$Q$^(n2ATCtCs&Wz$)+E>wE+|~468|@Vjx}ta-tw;eO)P_EPu{F2kI+%>P ziT$C+_Q7emMMPV^mU(?qnu?kU=Eka8!GJ7P z<{Hn4GyoWQQR#itGwN)y8^dO6pJqf`Q(6gV$Fi1hyjAI66VJfyWn1urvv;cl%?mT3 zo&Kus;=b=t&rGI@!@dR40KRou^i|IqHmZJ&Y9!~|AsIQjaxQVkGH!00nP#U;-Jgsh z*KF*G&YNKLlD1H72c`@2&rP;Z0!?L?E;S*@Y8<+QMk<_7>RJ%S*gH88KlJ1kx3Auu z1i#JmvH)Pcf)ne95JnvRd?$GH3uGF$$_0q?x;{&>){IEA4ZA}9_s*b`a;K<5QYt&L z%>QgWiF%<`NC&Jx`$=E5Gc-;a9&leFVQ&_+!Q~3ANU@=MuPslpDgvPkX9$IV`|}bj zi<>ON5ejZpD|!IH1m)afGpmf|KA1aut-#(!oyP)QW3k^{>qe}0H=KEN@Kw^Gv_&PK zgiTT{%q|4A(V#oFg+_eYpAactmybo+gAj@2SyEK*N>h$5`fUjQl(aKr>`&dCQA%G< zg(LqBD5z$(smU+G$3klpp&j8?7R}hJY^+!q1UH6Nn z?{8cxF0pv}}&n4LVhAWG)vXuw}tA`c}!8#F$X2NpoY#69}=OGf)x_rmC z`Y%H9(Z9JQuWO>@?fKGy&bh0E|B!Bo_Ec zuudc4`0EY{bYK{{x6!B4q~Wcot+&GJ$I=>B{iGxTy1?Zm3I5j|XqK0Ker1uWT2)`h zezl{b!?+S$>AZ|y$j`(d8@F7B%975MVK;BAfT8g7Dk=76r34}UTc5(GVnr9w2zq>2 zb>1nQ(&5ZJ`mRQvd;1Nno9cwWs*)nBa0QQM;a(C6uP3zaXEOg6`NqSMoQdXmrvK*37V7h)k{9t!sz$Z%Jn+v3(iB7L7I|}Bx)PwCxdiR&(^P3zlOn>By&?QgrYnn zCULIIQmyi@_6ROi?1m6jR5|JmbubCs<;lbKXq69x_2}yH$2=RK@G|M6FdeafH{id1sdm3G zcwt*mc57dLO2dXKHR3(_$ZDgyWA)uX(zMggQ{TKlD_i0LwSA!Fa$o)VEsntQuKlHW zP_sc2k+b&!brghfQBOaQ_04blLwV$=_3q&r0N}w~Zt^+X_tkdad&mEZQpV22??;Bw zoC}&&Tz!utAefTJf^1;g5eT#sxD`qGwi9JT*b4Si$QupF3^00X4R;x;w1E4Ew{|At z#5koQ-BWRwW9TGmrEAh^^FV|bh{OVI`bwiMrnQj#in@nqef5$eV-b}_wkpgAP~1f zsoNA<=SNHi35|D@*kON)Wdj-ti)3{{3}nptFh5^IdqzST;)9K#RcY{~yYf<|>*p71 z*!4p#ByLEX56sF|8i(4I6HCO#=6@<4)BXQF4z~s);=iXU2mAiRbrKVORQ)Uc!`pgP znr1P@y??GKfs#~x{YRb*7UhhVK0Nm~7a!XE>H45>q4}~DSLN^SIGi!4{Q?x2CwrwL zyXT$J>|f}uxn`b>d4+Pl(F_2^t?KL>q~XscQ3)$s{`EMIoGKIL6{?Ll^1(V17SZ-9 z4K#4ZGeugI9oo;vqO%hA)brw+60%sn3|iTe)|qmJ_1T8YyzfC}Ay};duG+#)RPrak z8Y5`zxkzN#UCxddVMdA4-Z2t&UgGAb_kDepeF)%%BFA~oi$gcs=a%E z7<;uFyp~x3VEmUO1+aS~X!iX@ftIZ`TsUF=?VAHol6StnDor*83WGbWw$&Me;6laM z^+M3(M7)(7qDW0@IQy>o&>eUC7w)Xq*CRB)lpu-}FC{WjUqGeM zM?YLWuT2Z-2$8k$Gl+n+v&5EdEDI!aYU?zU*>3)CbAV@tR|`%GeOL1H?3=A5hmxT~ ze^8HIx0rug6;2w?cD)YOQ>}r9GP&+?O|_MD2{r^i&T}8x&GDG^KDJaZh02>XV}mDG zZb_zywkH0=P!g}kYPQ?TFj!XAGN=pEUCl+XUfq-yVRD?xT`m}j%TLU3@}Qr;M-1*pf!*~M9!*0zme{Ahcb zCz`K^nbf~Wc}X%?z1^%oGH$1}Z~8mj2xoVk&o{;ThieVm4%#dmbdj7yB4u3|Oi zO^)N+F_Uo!HxcD^ z0-OCkaKk_+=zX%rhR5%T~%KskDO(f$?ZlUY^YC+Yv*6qhOXRFy5rI-Tt7w5z|zd%!rR@0*Z zZi?o_YHUCi#L?izWMN66$@;Gi9Bbj>00R)Rtv5x7DsLb~q5o_UAZ=_{Ik9$JnpZW7 zuZJgW!G;lG!I-0j>>KLaRzu`AOkG9e^4iz86i|`B{(^LY&_KE?6~{Mlo54yKGv=}A z=8VCNe}6#(>;P)fD`{>P%8vvPo=V)os;rW>ABU`mdSn*77?5eo9P&&-rNp^4o3Y{^ zo9c6umajRvZ(NKknO=7$+S36cL;Hz9qb(Ny{VnM(F{`=t-Y=2#Hh_y{nqGL?DF=;& zgvzvY>Ng0AM$I8ppWQAVFYUA!mD)!2*Ef4ZI2lxa7Lk&^s@}INH-@P=Vw5F&6lGXd zh5=xDEr?^9lI`7`>^`ykiH!#%zVbS>QCe=2tPw#*xjM}|La>VE`OiFTi2K(-Fj|uP znAWvyxP;2H5q|nx3%uI7%PwZ_NJQ9v>(p~8Qtk~c{-_MH7^q3fJPN?Lt5KGB*Iw0l z^X1cy##N~NN66+gPZP*9aW>Jel3>I+Lg zI<5^Kc~!r@R0(-VNDj|S9m&6vIK_JNxbpbF9dff^!-uePWB17vg<23~W@T;azoEUa zk>Fc9q|=6uVex|H70HKGZKc)zITPT(>fQO93hF&~Enp}AsK81`0CQtr4bcpeB^@Np ze1XgFSIKvwi^Ie5%OIWFISp1<{ff~b8*h?*CfWosj_6R!Fu0_bx871-_OFc68+~D| zwaqmO%Uz4`JlwVvWyB*ZZWNX{b?)^VIUd*NsJJP5-&Aq>C&RDLF`&83zU7z9^8aaD zjY<1JXMn?RYIYpF#TkbhX^0>u8b)A4hvLKYxYbcf&NUn~uz6Inm_olJHRq*8 zY(hi#RIN5H$2-aUC`9$!u!0$2+IecMpy};TBZ~LqB@i-|o|?4EuSOj?6|THb`U16* z9{!}u&r2L_EsyKBjH=`UiOTEQ0;|rO9Cjick|~9!la}9J{tELe>KzzMPTnd~d8L>Q zw#4(ukfu`^e1()T%e0M9=cG~xUH&VI`L z^*G|bJS(HR+Ty1UXSkVuuNiQfTCE7Enju;Te4cw~;Y+l56>jpL0HcK@SZpbO#({+O zoFOFpvUGA9;lr8v+2>#Vc*NKlrXHKV=h=1ONyK^*=|o{w)mMC^h2Z>6%9P<#u4E={ zWngynW>|b!YUNnbGt!gEA~5jamS%0_54>=sfYnbUod zGz}H*UX8^u*N#Zt@(9ug%gJR@jIoI37ub58Dm0VU~%xn`zhCs12f@dbm!iiVd!gB%_J3c$krRsw8vo%{C>+)k+Nu z*QDzC(`gx-tcoQxJNFw;xPj4bCa-=CeWzEb_PeQfPXbOA{Zv~Jbg^i-o_ORfp9AeB+~WbpC)B`Z=z`)T z<@Qr$jY6uAM(ABJug7@&W7Q&wYmu7ITs($K-0EJI>MA~6-8Y1px+KU#73530TAcUq zYyvqf>F>Nq-x~!|(sW9Uh2emk59m+fE(v8@focu$SKJ?LRjf%&zDhhp+@O8Sj=wlk;)Beu3^(PEi{zy3v|@~>Q0&QFaew?4%L zRt*u!M$s8b8Fvsk3=$-q651qY`G1S8>AxL(7cM&Z?*K}dOd5c31_f8ZpcZPFZ zf6a-goq-nxYfHmtb1F^!p&O^VXGFQ%>7c*Ez_9h-1MHO>ybx5HQ7zR>A2C0zx&D4C z5t@^rDp|5Cx#+uecwjn_4*MY#8`Kd9wlG$A0@>V-%zU~rz=a5YFu2KoqilxbjZU;hJN;uZQ)P_3(fTt+YO96TmCHX2(1K+kqfCi-|gC~9%fIDkhZ6ks0XEN zl<-oRsrtHlUXQBe*u4EgQa}aUYU}~K{*Q^}jI+lnsPV-5&PAmI+)mZW#ljS0nCgsW zV`2323r;ih*X%4SjF5~J$DYcS%&P)yW0x(*k_{%fkK;6yMo_^>2*5f2Ha2 zlzY&Xp$P5bcXUkyk!bXaeD(ROe%8gArftKqP|gw%tX zqxLo|^RA|kCG1r&{zb_sr%=0EI&Je_8CIi2;9mKYxfXp zKdu!1$7rJ4SB3b$4q#jwokMle*(dLy{Rg) zue}-8m$qfoKh(=aoMLEx=jB=#G|_t5rMQsognD&1H=#k=%))0Hj@6Ethr2`UjT}0B1L8#)52D zs^}j_aEIVo0KIQdx=6_liw!mjv#I6G7E7cJE{FF-!-33@$I>_#lx<++wENXnACOyt zg$jhwIVg=?@fQU!!oGO9Nxng(H%YkFe5^~IC-%9?2hC7dkyBuE>w*}~q-<9u;>H1= zW(nbXq9x13Culypmf{Eh8lb@RIU!E`=e_mVa2nti^^3uaL%F~y?8J}mpxEcG6EZOp zCt94dK6lEUL4k1(=*K;wMWHVw!E=c%ym6=Rcs*|F@pg4d6N8@(Pf;Rz_qha07fpV^ zAD(u52butIJ$BRk#Y@~;1($V+Pi`5C*H>qbem$$=ED`tsn)2|&yDQ>-8&ZVRL;5rs^!sW@S_Ij&RYsP}Yrdyzcsv2O}HHO_0GB zB{wphSnD;s@ISx-%K0TC=ax_MT5Me#Uoz{P+SOQ!>D&xx?5v$YrlB225iCKs!t-)H zh&Q)#Qo(U-36Xu)$nfO4y1z24y25#%JhRfH-V0A(bw~)6xhedrkwvGCeSwu&%z3Ip zqB!3{=>zCvttzL1*_7s|OJjnYwhm60HNn zSx8Ggohk|g8LD%?8e4Np_cXFY20}sNp6|>!_@k!o|2?jXf$}faIk&i-{O6uu3w%Iz z5l{yEy-HtBtg~0chJXbs!{}y?6eQWTf@*82Qd(#P$9!%;YJ#NmwZoiP|Ab_kE~=>a zQADBH4!tfnW{ez}HS@w0B5h!ab}Q{|8lCIdu48yo_Hn$Tj_w2)A$UKdL4EP(R0o8B zGXEcqZ`+*GLG`v^Q!Fr8N2c-W5OQy`g4AFMrNe zRACJD!0@U2gBZMscUcksnYXOOWH81BaeP(NSA$L+C35l49~B!fU1s;1f7B=tZH`;? z(|N4bjJ`ar-8x$5enx>Zd0mPHxZlsa`tUc^DK9W?g7CYg6bEiwt{;B%jJzhKVD9fB z1O`WCQzP0`jDMPfyN~jHOP^QeYq0Y1;{`INR}Q8|`Fv&x5P=Qm4EN?x<}gN8pA|M! z+ti2F+w04jSF!5g0-58FvVJukw=&TU#jKgM!r9>0|1nUf`;x>zPl0DF6E_9z!DE%u z39ujlgl32bQwx~zNX~Y2s1XEv*`FKSz;>`gpd%|nUBisr!zWw8-gkc{R;rspRD0rB zEm!NUIm+=>3+Xc3lB0iEK7i}o3JWrVjehv%$f;Ibgtu0#Y=a-*L+38cYFoL7gSX)) zz77b9deI+aa62egq{8bC4|sCis5lb^s}TVJteMB}0)S8siPF{y@g%pal*LU!`@gUaGa!+X8z62aq~bs~ z2$@6GAC2wKW)$8<%x3wla!t+3T*koG|7PKtxL3v{!H!!~j?As&0>nM8p7B_ie~pl? zYMXPQCB1`Y+ky`%IV&|s4TlB8^R>O|I={8T-EnOl&Sr&vrK8JzY1`)!;FS%%K}d`T8Nc!6a)tqMgSK^-A9&SkjTJZ43O%SJsq-mL>F zw~vf7p*fe>BwletvY8hYpd6ZNR0qd;-n?m%h)Fvq8G?UNk@jPW0niNvmvS%@a4Io4 z_;8=pClbs5MIye@RswGUuaqP2zL6=u(Wh*OHS=Fk=rie1`;b*TI0oLL>RoJu;`&i-cZCd(B7i|NZ09q32zKD$IYp{5i-)eDkyD<)Nsb0SgFLJ;q81jKdoT zn(CfptCUMkp!tMWtE&6|pB?}EC^U1FK`Wq)_C*fNazsj_BHd0mo!{8#f*3rWATk>{|Y;Py6zffGJ{zXnJWFj@!j+WMm=J^Ow35X2;VrvpscaMm>*H*Y_Z;Zq1e4S66yVk@YIR+0RgEv2epY7A>{}p1yRWd&s9(eDwC>rfhsmL8w(Q(mrD(W^LmK_L zWn(vu2>F7VIuX@kYfmy7mYX|*U5jdM7zLuLgC*mje(`w2c;|ux8Cp(Z<;Blt61OdW z;yu{nah_+_y>sYy{@O)Ff3~{SE$SFg@j_a}1nf?wZ_^9OBWu?J7G1XYQ))2d_jq1} zT`cr{SuqtgZ#jnXKF6PRn-(>SH*wccZ^qr_L|Yp_6o+}97(kMSrMOD-|VY+e_ni=;R6oE`HspR4_6x0+Y z5p!@88%c0sRldD79R{<$`~^eV7mZ@i<(zSka;Ad&_z71PFPw6csrq`GR(W49L0E3A z9;tcvWas1YdV=c(f{s`NtQ9Xb+?GCd?#C0e?hZ(>9c0WFk;oBnxJdUoL1y-g+SQiN zeIC)G!y6^r>=~PyE$_?6CXUJ(d^WcZT|JE6_i1CKEmQS5x{F74Pq2yKw@bp=Y<$8o ziAp4G!IO>WXGgquW|UiGTZf+^>f{0k(wT^yL#weWj7_`5S`=_^bUEM6GSxGj` zf0X^Xbs^}^-Y7_?f6&HXm(l<>m4_MUP=@*UVe4Y--baGE(L&^9Et7s2ESx2Bz&Cu5 zZD5(bof8%{RU zZ?4fCk{i`*2nUocySB?yUaUsqY8OEk3aECDfTS!72j&xE-_c?DyAjsUwFgsJ?sT0a z#X|vi@RDB+%$wu#b2i_CsEsx2hqmCUl)p#9O_-l=qW+ng$*GtVpECkWap^P18IroQ zrup;D)KQJaJiTW1%w|N0GjrbAn0!oiN{`h~bamLKv*sUjIp zU%rB`K;Ra1!Nl92lqJ?*ZTylgWgm5iCo#bPVQV?@W6~oqg-%N~Odb{0OF6$+u--V( zAZI=QF|GiwOa5JIksV5JbqK1$E#>&lnM=paqiK~Ne9OyN+ZrT?F2vV_^Z$1w5q$jr ujQ?ohKN|Rt2L7Xg|7hU Date: Tue, 2 Dec 2025 09:35:20 -0500 Subject: [PATCH 90/96] vfs: change signature of Vfs_Access, and add Vfs_AccessAs --- src/oboskrnl/vfs/create.c | 18 ++++++------------ src/oboskrnl/vfs/dirent.c | 14 +++++++++----- src/oboskrnl/vfs/fd.c | 4 +--- src/oboskrnl/vfs/fd_sys.c | 4 +--- src/oboskrnl/vfs/vnode.h | 3 ++- 5 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/oboskrnl/vfs/create.c b/src/oboskrnl/vfs/create.c index a4773b4a..c4dae200 100644 --- a/src/oboskrnl/vfs/create.c +++ b/src/oboskrnl/vfs/create.c @@ -34,9 +34,7 @@ obos_status Vfs_CreateNode(dirent* parent, const char* name, uint32_t vtype, fil if (!name || !vtype || vtype >= VNODE_TYPE_BAD) return OBOS_STATUS_INVALID_ARGUMENT; - obos_status status = Vfs_Access(Core_GetCurrentThread()->proc->euid, - Core_GetCurrentThread()->proc->egid, - parent->vnode, + obos_status status = Vfs_Access(parent->vnode, false, true, false); @@ -137,9 +135,7 @@ OBOS_EXPORT obos_status Vfs_UnlinkNode(dirent* node) return OBOS_STATUS_SUCCESS; if (node->d_children.nChildren) return OBOS_STATUS_IN_USE; // cannot remove a directory with children - obos_status status = Vfs_Access(Core_GetCurrentThread()->proc->euid, - Core_GetCurrentThread()->proc->egid, - node->d_parent->vnode, + obos_status status = Vfs_Access(node->d_parent->vnode, false, true, false); @@ -217,12 +213,10 @@ obos_status Vfs_RenameNode(dirent* node, dirent* newparent, const char* name) if (!header) return OBOS_STATUS_INVALID_ARGUMENT; - obos_status status = Vfs_Access(Core_GetCurrentThread()->proc->euid, - Core_GetCurrentThread()->proc->egid, - (newparent ? newparent : node->d_parent)->vnode, - false, - true, - false); + obos_status status = Vfs_Access((newparent ? newparent : node->d_parent)->vnode, + false, + true, + false); if (obos_is_error(status)) return status; diff --git a/src/oboskrnl/vfs/dirent.c b/src/oboskrnl/vfs/dirent.c index 920ef43c..3d17ae30 100644 --- a/src/oboskrnl/vfs/dirent.c +++ b/src/oboskrnl/vfs/dirent.c @@ -662,10 +662,7 @@ char* VfsH_DirentPath(dirent* ent, dirent* relative_to) static bool check_chdir_perms(dirent* ent) { - uid uid = Core_GetCurrentThread()->proc->euid; - gid gid = Core_GetCurrentThread()->proc->egid; - - return Vfs_Access(uid, gid, ent->vnode, false, false, true) == OBOS_STATUS_SUCCESS; + return Vfs_Access(ent->vnode, false, false, true) == OBOS_STATUS_SUCCESS; } obos_status VfsH_Chdir(void* target_, const char *path) @@ -795,7 +792,14 @@ mount* Vfs_GetVnodeMount(vnode* vn) return vn->flags & VFLAGS_MOUNTPOINT ? vn->un.mounted : vn->mount_point; } -obos_status Vfs_Access(uid asUid, gid asGid, vnode* vn, bool read, bool write, bool exec) +obos_status Vfs_Access(vnode* vn, bool read, bool write, bool exec) +{ + uid euid = Core_GetCurrentThread() && Core_GetCurrentThread()->proc ? Core_GetCurrentThread()->proc->euid : 0; + gid egid = Core_GetCurrentThread() && Core_GetCurrentThread()->proc ? Core_GetCurrentThread()->proc->egid : 0; + return Vfs_AccessAs(euid, egid, vn, read, write, exec); +} + +obos_status Vfs_AccessAs(uid asUid, gid asGid, vnode* vn, bool read, bool write, bool exec) { if (write) { diff --git a/src/oboskrnl/vfs/fd.c b/src/oboskrnl/vfs/fd.c index 5ad833ea..310550ae 100644 --- a/src/oboskrnl/vfs/fd.c +++ b/src/oboskrnl/vfs/fd.c @@ -94,9 +94,7 @@ OBOS_EXPORT obos_status Vfs_FdOpenVnode(fd* const desc, void* vn, uint32_t oflag desc->flags |= FD_FLAGS_OPEN; desc->flags |= FD_FLAGS_READ; desc->flags |= FD_FLAGS_WRITE; - obos_status status = Vfs_Access(Core_GetCurrentThread()->proc->euid, - Core_GetCurrentThread()->proc->egid, - vnode, + obos_status status = Vfs_Access(vnode, oflags & FD_OFLAGS_READ, oflags & FD_OFLAGS_WRITE, oflags & FD_OFLAGS_EXECUTE); diff --git a/src/oboskrnl/vfs/fd_sys.c b/src/oboskrnl/vfs/fd_sys.c index 06d0389f..50ab5462 100644 --- a/src/oboskrnl/vfs/fd_sys.c +++ b/src/oboskrnl/vfs/fd_sys.c @@ -874,9 +874,7 @@ handle Sys_OpenDir(const char* upath, obos_status *statusp) if (dent->vnode) { - obos_status status = Vfs_Access(Core_GetCurrentThread()->proc->euid, - Core_GetCurrentThread()->proc->egid, - dent->vnode, + obos_status status = Vfs_Access(dent->vnode, true, false, false); diff --git a/src/oboskrnl/vfs/vnode.h b/src/oboskrnl/vfs/vnode.h index 10d0b099..537bc422 100644 --- a/src/oboskrnl/vfs/vnode.h +++ b/src/oboskrnl/vfs/vnode.h @@ -121,4 +121,5 @@ OBOS_EXPORT driver_header* Vfs_GetVnodeDriver(vnode* vn); OBOS_EXPORT driver_header* Vfs_GetVnodeDriverStat(vnode* vn); OBOS_EXPORT struct mount* Vfs_GetVnodeMount(vnode* vn); -OBOS_EXPORT obos_status Vfs_Access(uid asUid, gid asGid, vnode* vn, bool read, bool write, bool exec); \ No newline at end of file +OBOS_EXPORT obos_status Vfs_Access(vnode* vn, bool read, bool write, bool exec); +OBOS_EXPORT obos_status Vfs_AccessAs(uid asUid, gid asGid, vnode* vn, bool read, bool write, bool exec); \ No newline at end of file From cc49c517a290093c38a8e6345cd31c01c9390727 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 09:39:06 -0500 Subject: [PATCH 91/96] user-utils: clear group list before setting new groups --- src/user-utilities/login.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/user-utilities/login.c b/src/user-utilities/login.c index 6b0c52e4..f7dd3646 100644 --- a/src/user-utilities/login.c +++ b/src/user-utilities/login.c @@ -211,6 +211,7 @@ int main() groups = calloc(ngroups, sizeof(gid_t)); getgrouplist(user->pw_name, user->pw_gid, groups, &ngroups); + setgroups(0, NULL); int ret = setgroups(ngroups, groups); if (ret == -1) { From 7186bba0e3ec7bb057f3b3068d9adf60ff19a7d3 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 09:53:21 -0500 Subject: [PATCH 92/96] sys: add Sys_SigPending to the syscall list --- src/oboskrnl/arch/m68k/syscall.c | 1 + src/oboskrnl/arch/x86_64/syscall.c | 1 + src/oboskrnl/syscall.c | 1 + 3 files changed, 3 insertions(+) diff --git a/src/oboskrnl/arch/m68k/syscall.c b/src/oboskrnl/arch/m68k/syscall.c index fc93dec1..1b3fa149 100644 --- a/src/oboskrnl/arch/m68k/syscall.c +++ b/src/oboskrnl/arch/m68k/syscall.c @@ -165,6 +165,7 @@ const char *syscall_to_string[] = { "Sys_SetRESGid", "Sys_GetRESUid", "Sys_GetRESGid", + "Sys_SigPending", }; const char* status_to_string[] = { diff --git a/src/oboskrnl/arch/x86_64/syscall.c b/src/oboskrnl/arch/x86_64/syscall.c index 3efafb9c..2456e8d6 100644 --- a/src/oboskrnl/arch/x86_64/syscall.c +++ b/src/oboskrnl/arch/x86_64/syscall.c @@ -250,6 +250,7 @@ const char* syscall_to_string[] = { "Sys_SetRESGid", "Sys_GetRESUid", "Sys_GetRESGid", + "Sys_SigPending", }; const char* status_to_string[] = { diff --git a/src/oboskrnl/syscall.c b/src/oboskrnl/syscall.c index b0ee2b30..65cf4f87 100644 --- a/src/oboskrnl/syscall.c +++ b/src/oboskrnl/syscall.c @@ -484,6 +484,7 @@ uintptr_t OBOS_SyscallTable[SYSCALL_END-SYSCALL_BEGIN] = { (uintptr_t)Sys_SetRESGid, (uintptr_t)Sys_GetRESUid, (uintptr_t)Sys_GetRESGid, + (uintptr_t)Sys_SigPending, }; // Arch syscall table is defined per-arch From 4770ba735223f465546830f12018d1815dcef15b Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 09:58:19 -0500 Subject: [PATCH 93/96] core: implement suplementary group IDs --- src/oboskrnl/arch/m68k/syscall.c | 2 + src/oboskrnl/arch/x86_64/syscall.c | 2 + src/oboskrnl/scheduler/process.h | 4 ++ src/oboskrnl/scheduler/sched_sys.c | 66 ++++++++++++++++++++++++++++++ src/oboskrnl/scheduler/sched_sys.h | 3 ++ src/oboskrnl/syscall.c | 2 + src/oboskrnl/vfs/dirent.c | 15 ++++++- 7 files changed, 93 insertions(+), 1 deletion(-) diff --git a/src/oboskrnl/arch/m68k/syscall.c b/src/oboskrnl/arch/m68k/syscall.c index 1b3fa149..859f9ce2 100644 --- a/src/oboskrnl/arch/m68k/syscall.c +++ b/src/oboskrnl/arch/m68k/syscall.c @@ -166,6 +166,8 @@ const char *syscall_to_string[] = { "Sys_GetRESUid", "Sys_GetRESGid", "Sys_SigPending", + "Sys_SetGroups", + "Sys_GetGroups", }; const char* status_to_string[] = { diff --git a/src/oboskrnl/arch/x86_64/syscall.c b/src/oboskrnl/arch/x86_64/syscall.c index 2456e8d6..a85fa143 100644 --- a/src/oboskrnl/arch/x86_64/syscall.c +++ b/src/oboskrnl/arch/x86_64/syscall.c @@ -251,6 +251,8 @@ const char* syscall_to_string[] = { "Sys_GetRESUid", "Sys_GetRESGid", "Sys_SigPending", + "Sys_SetGroups", + "Sys_GetGroups", }; const char* status_to_string[] = { diff --git a/src/oboskrnl/scheduler/process.h b/src/oboskrnl/scheduler/process.h index ac697526..e77fc051 100644 --- a/src/oboskrnl/scheduler/process.h +++ b/src/oboskrnl/scheduler/process.h @@ -39,6 +39,10 @@ typedef struct process uid euid, ruid, suid; gid egid, rgid, sgid; + struct { + gid *list; + size_t nEntries; + } groups; uint32_t exitCode; bool dead; diff --git a/src/oboskrnl/scheduler/sched_sys.c b/src/oboskrnl/scheduler/sched_sys.c index 15421adb..46d1721b 100644 --- a/src/oboskrnl/scheduler/sched_sys.c +++ b/src/oboskrnl/scheduler/sched_sys.c @@ -779,6 +779,72 @@ obos_status Sys_SetGid(gid gid) return OBOS_STATUS_ACCESS_DENIED; } +obos_status Sys_SetGroups(handle process, size_t size, gid* ulist) +{ + struct process* proc = + HANDLE_TYPE(process) == HANDLE_TYPE_CURRENT ? + Core_GetCurrentThread()->proc : + nullptr; + obos_status status = OBOS_STATUS_SUCCESS; + if (!proc) + { + OBOS_LockHandleTable(OBOS_CurrentHandleTable()); + handle_desc* desc = OBOS_HandleLookup(OBOS_CurrentHandleTable(), process, HANDLE_TYPE_PROCESS, false, &status); + if (!desc) + { + OBOS_UnlockHandleTable(OBOS_CurrentHandleTable()); + return status; + } + proc = desc->un.process; + OBOS_UnlockHandleTable(OBOS_CurrentHandleTable()); + } + + gid* list = Mm_MapViewOfUserMemory(Core_GetCurrentThread()->proc->ctx, + ulist, nullptr, + size * sizeof(gid), + OBOS_PROTECTION_READ_ONLY, true, + &status); + if (obos_is_error(status) && size) + return status; + + proc->groups.list = Reallocate(OBOS_KernelAllocator, proc->groups.list, size*sizeof(gid), proc->groups.nEntries*sizeof(gid), nullptr); + if (list) + memcpy(proc->groups.list, list, size * sizeof(gid)); + proc->groups.nEntries = size; + + if (size) + Mm_VirtualMemoryFree(&Mm_KernelContext, list, size*sizeof(gid)); + return OBOS_STATUS_SUCCESS; +} +obos_status Sys_GetGroups(handle process, size_t *size, gid* list) +{ + struct process* proc = + HANDLE_TYPE(process) == HANDLE_TYPE_CURRENT ? + Core_GetCurrentThread()->proc : + nullptr; + obos_status status = OBOS_STATUS_SUCCESS; + if (!proc) + { + OBOS_LockHandleTable(OBOS_CurrentHandleTable()); + handle_desc* desc = OBOS_HandleLookup(OBOS_CurrentHandleTable(), process, HANDLE_TYPE_PROCESS, false, &status); + if (!desc) + { + OBOS_UnlockHandleTable(OBOS_CurrentHandleTable()); + return status; + } + proc = desc->un.process; + OBOS_UnlockHandleTable(OBOS_CurrentHandleTable()); + } + size_t sz = 0; + status = memcpy_usr_to_k(&sz, size, sizeof(sz)); + if (obos_is_error(status)) + return status; + status = memcpy_k_to_usr(list, proc->groups.list, OBOS_MIN(sz, proc->groups.nEntries) * sizeof(gid)); + if (obos_is_error(status)) + return status; + return memcpy_k_to_usr(size, &proc->groups.nEntries, sizeof(size_t)); +} + obos_status Sys_SetProcessGroup(handle process, uint32_t pgid) { struct process* proc = diff --git a/src/oboskrnl/scheduler/sched_sys.h b/src/oboskrnl/scheduler/sched_sys.h index 673658b2..06d8b31d 100644 --- a/src/oboskrnl/scheduler/sched_sys.h +++ b/src/oboskrnl/scheduler/sched_sys.h @@ -75,5 +75,8 @@ obos_status Sys_GetRESGid(gid* rgid, gid* egid, gid* sgid); obos_status Sys_SetUid(uid uid); obos_status Sys_SetGid(gid gid); +obos_status Sys_SetGroups(handle proc, size_t size, gid* list); +obos_status Sys_GetGroups(handle proc, size_t *size, gid* list); + obos_status Sys_SetProcessGroup(handle proc, uint32_t pgid); obos_status Sys_GetProcessGroup(handle proc, uint32_t* pgid); \ No newline at end of file diff --git a/src/oboskrnl/syscall.c b/src/oboskrnl/syscall.c index 65cf4f87..da8a315b 100644 --- a/src/oboskrnl/syscall.c +++ b/src/oboskrnl/syscall.c @@ -485,6 +485,8 @@ uintptr_t OBOS_SyscallTable[SYSCALL_END-SYSCALL_BEGIN] = { (uintptr_t)Sys_GetRESUid, (uintptr_t)Sys_GetRESGid, (uintptr_t)Sys_SigPending, + (uintptr_t)Sys_SetGroups, + (uintptr_t)Sys_GetGroups, }; // Arch syscall table is defined per-arch diff --git a/src/oboskrnl/vfs/dirent.c b/src/oboskrnl/vfs/dirent.c index 3d17ae30..25ea9463 100644 --- a/src/oboskrnl/vfs/dirent.c +++ b/src/oboskrnl/vfs/dirent.c @@ -796,7 +796,20 @@ obos_status Vfs_Access(vnode* vn, bool read, bool write, bool exec) { uid euid = Core_GetCurrentThread() && Core_GetCurrentThread()->proc ? Core_GetCurrentThread()->proc->euid : 0; gid egid = Core_GetCurrentThread() && Core_GetCurrentThread()->proc ? Core_GetCurrentThread()->proc->egid : 0; - return Vfs_AccessAs(euid, egid, vn, read, write, exec); + obos_status status = Vfs_AccessAs(euid, egid, vn, read, write, exec); + if (obos_is_success(status)) + return OBOS_STATUS_SUCCESS; + if (!Core_GetCurrentThread() || !Core_GetCurrentThread()->proc) + return status; + if (status == OBOS_STATUS_READ_ONLY) + return OBOS_STATUS_READ_ONLY; + for (size_t i = 0; i < Core_GetCurrentThread()->proc->groups.nEntries; i++) + { + status = Vfs_AccessAs(euid, Core_GetCurrentThread()->proc->groups.list[i], vn, read, write, exec); + if (obos_is_success(status)) + return OBOS_STATUS_SUCCESS; + } + return status; } obos_status Vfs_AccessAs(uid asUid, gid asGid, vnode* vn, bool read, bool write, bool exec) From da8e7c3f27ac76127c51d65f5d53fc73b984db23 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 18:42:28 -0500 Subject: [PATCH 94/96] vfs: fix bug with Vfs_FdOpenVnode --- src/oboskrnl/scheduler/sched_sys.c | 3 ++- src/oboskrnl/vfs/fd.c | 19 ++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/oboskrnl/scheduler/sched_sys.c b/src/oboskrnl/scheduler/sched_sys.c index 46d1721b..45d5a7d4 100644 --- a/src/oboskrnl/scheduler/sched_sys.c +++ b/src/oboskrnl/scheduler/sched_sys.c @@ -4,7 +4,6 @@ * Copyright (c) 2024-2025 Omar Berrow */ -#include "vfs/mount.h" #include #include #include @@ -24,6 +23,8 @@ #include #include +#include + #include #include diff --git a/src/oboskrnl/vfs/fd.c b/src/oboskrnl/vfs/fd.c index 310550ae..533eba8a 100644 --- a/src/oboskrnl/vfs/fd.c +++ b/src/oboskrnl/vfs/fd.c @@ -91,19 +91,19 @@ OBOS_EXPORT obos_status Vfs_FdOpenVnode(fd* const desc, void* vn, uint32_t oflag if (vnode->vtype == VNODE_TYPE_DIR || vnode->vtype == VNODE_TYPE_LNK) return OBOS_STATUS_NOT_A_FILE; desc->vn = vnode; - desc->flags |= FD_FLAGS_OPEN; - desc->flags |= FD_FLAGS_READ; - desc->flags |= FD_FLAGS_WRITE; + obos_status status = Vfs_Access(vnode, oflags & FD_OFLAGS_READ, oflags & FD_OFLAGS_WRITE, oflags & FD_OFLAGS_EXECUTE); if (obos_is_error(status)) return status; - if (~oflags & FD_OFLAGS_READ) - desc->flags &= ~FD_FLAGS_READ; - if (~oflags & FD_OFLAGS_WRITE) - desc->flags &= ~FD_FLAGS_WRITE; + + if (oflags & FD_OFLAGS_READ) + desc->flags |= FD_FLAGS_READ; + if (oflags & FD_OFLAGS_WRITE) + desc->flags |= FD_FLAGS_WRITE; + if (oflags & FD_OFLAGS_UNCACHED) desc->flags |= FD_FLAGS_UNCACHED; if (oflags & FD_OFLAGS_NOEXEC) @@ -112,6 +112,11 @@ OBOS_EXPORT obos_status Vfs_FdOpenVnode(fd* const desc, void* vn, uint32_t oflag desc->flags |= FD_FLAGS_UNCACHED; if (vnode->flags & VFLAGS_EVENT_DEV) desc->flags &= ~(FD_FLAGS_READ|FD_FLAGS_WRITE); + else + { + if (!(desc->flags & (FD_FLAGS_WRITE|FD_FLAGS_READ))) + return OBOS_STATUS_ACCESS_DENIED; + } desc->vn->refs++; LIST_APPEND(fd_list, &desc->vn->opened, desc); if (~desc->vn->flags & VFLAGS_EVENT_DEV) From 8df7f04080ae9f85db8b6cf0a66263b52b4c0e68 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 19:03:22 -0500 Subject: [PATCH 95/96] vfs/tty: make all tty devices be owned by gid 5 --- src/oboskrnl/vfs/tty.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/oboskrnl/vfs/tty.c b/src/oboskrnl/vfs/tty.c index 33a0cb45..bece653b 100644 --- a/src/oboskrnl/vfs/tty.c +++ b/src/oboskrnl/vfs/tty.c @@ -585,8 +585,7 @@ obos_status Vfs_RegisterTTY(const tty_interface *i, dirent **onode, bool pty) VNODE_TYPE_CHR); vn->flags |= VFLAGS_IS_TTY; vn->data = tty; - vn->perm.other_read = true; - vn->perm.other_write = true; + vn->gid = 5; // tty size_t index = pty ? last_pty_index++ : last_tty_index++; size_t szName = snprintf(nullptr, 0, "tty%ld", index); char *name = nullptr; From 21d01e0ddbd0ac4f7727823f7b17a39d799a0eb6 Mon Sep 17 00:00:00 2001 From: Omar Berrow Date: Tue, 2 Dec 2025 19:58:53 -0500 Subject: [PATCH 96/96] ahci: fix bug in populate_physical_regions --- src/drivers/generic/ahci/interface.c | 12 ++++++++---- src/oboskrnl/gpt.c | 5 +++-- src/oboskrnl/mm/handler.h | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/drivers/generic/ahci/interface.c b/src/drivers/generic/ahci/interface.c index 7db59399..a1352513 100644 --- a/src/drivers/generic/ahci/interface.c +++ b/src/drivers/generic/ahci/interface.c @@ -84,15 +84,19 @@ static obos_status populate_physical_regions(uintptr_t base, size_t size, struct { if (data->physRegionCount >= MAX_PRDT_COUNT) return OBOS_STATUS_INTERNAL_ERROR; + + Mm_HandlePageFault(ctx, addr, (data->direction == COMMAND_DIRECTION_WRITE ? 0 : PF_EC_RW) | (ctx == &Mm_KernelContext ? 0 : PF_EC_UM)); + page_info info = {}; MmS_QueryPageInfo(ctx->pt, addr, &info, nullptr); - if (!info.prot.present) - Mm_HandlePageFault(ctx, addr, (data->direction == COMMAND_DIRECTION_READ ? 0 : PF_EC_RW) | (ctx == &Mm_KernelContext ? 0 : PF_EC_UM)); + page key = {.phys=info.phys}; page* pg = RB_FIND(phys_page_tree, &Mm_PhysicalPages, &key); - if (pg->cow_type != COW_DISABLED) - Mm_HandlePageFault(ctx, addr, PF_EC_PRESENT | (data->direction == COMMAND_DIRECTION_READ ? 0 : PF_EC_RW) | (ctx == &Mm_KernelContext ? 0 : PF_EC_UM)); + OBOS_ENSURE(pg != Mm_AnonPage); + OBOS_ENSURE(pg != Mm_UserAnonPage); + MmH_RefPage(pg); + if ((lastPhys + pgSize) != info.phys) { if (addr != base) diff --git a/src/oboskrnl/gpt.c b/src/oboskrnl/gpt.c index e1ff87e2..d9f16d5f 100644 --- a/src/oboskrnl/gpt.c +++ b/src/oboskrnl/gpt.c @@ -35,7 +35,8 @@ obos_status OBOS_IdentifyGPTPartitions(fd *desc, partition *partition_list, size size_t filesize = desc->vn->filesize; if (filesize < sizeof(mbr_t)) return OBOS_STATUS_EOF; - mbr_t *protective_mbr = ZeroAllocate(OBOS_KernelAllocator, 1, sizeof(mbr_t), nullptr); + OBOS_ASSERT(OBOS_PAGE_SIZE > sizeof(mbr_t)); + mbr_t *protective_mbr = ZeroAllocate(OBOS_KernelAllocator, 1, OBOS_PAGE_SIZE, nullptr); obos_status status = Vfs_FdRead(desc, protective_mbr, sizeof(*protective_mbr), &nRead); if (obos_is_error(status)) @@ -44,7 +45,7 @@ obos_status OBOS_IdentifyGPTPartitions(fd *desc, partition *partition_list, size return OBOS_STATUS_INTERNAL_ERROR; if (protective_mbr->signature != MBR_BOOT_SIGNATURE) return OBOS_STATUS_INVALID_FILE; - Free(OBOS_KernelAllocator, protective_mbr, sizeof(*protective_mbr)); + Free(OBOS_KernelAllocator, protective_mbr, OBOS_PAGE_SIZE); size_t blkSize = Vfs_FdGetBlkSz(desc); OBOS_ASSERT(__builtin_popcount(blkSize) == 1); diff --git a/src/oboskrnl/mm/handler.h b/src/oboskrnl/mm/handler.h index c2a6b394..dfa97625 100644 --- a/src/oboskrnl/mm/handler.h +++ b/src/oboskrnl/mm/handler.h @@ -54,7 +54,7 @@ typedef enum { /// The virtual address that faulted. /// The page fault's error code. /// OBOS_STATUS_SUCCESS if the page fault was handled, OBOS_STATUS_UNHANDLED if the page fault went unhandled, otherwise an error. -obos_status Mm_HandlePageFault(context* ctx, uintptr_t addr, uint32_t ec); +OBOS_EXPORT obos_status Mm_HandlePageFault(context* ctx, uintptr_t addr, uint32_t ec); /// /// Runs the page replacement algorithm on pages in a context. /// This essentially chooses pages from within the context, and puts them within the working-set of the context.