Преглед на файлове

Merge branch 'master' into mem-priv

greatbridf преди 2 години
родител
ревизия
edcbbf0ac5

+ 4 - 3
CMakeLists.txt

@@ -7,8 +7,9 @@ set(CMAKE_CXX_LINK_EXECUTABLE
     "<CMAKE_LINKER> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
 
 set(CMAKE_ASM_FLAGS "-m32")
-set(CMAKE_C_FLAGS "-nostdinc -m32 -nostdlib -W -Wall -Wextra -Wno-builtin-declaration-mismatch -Wno-format -Werror=implicit-int -Werror=implicit-function-declaration -Werror=strict-aliasing -fverbose-asm -fno-exceptions -fno-pic -ffreestanding -mstack-protector-guard=global")
-set(CMAKE_CXX_FLAGS "-nostdinc -m32 -nostdlib -W -Wall -Wextra -Wno-builtin-declaration-mismatch -Wno-format -fverbose-asm -fno-use-cxa-atexit -fno-exceptions -fno-pic -ffreestanding -fno-rtti -mstack-protector-guard=global")
+set(C_CXX_FLAGS "-nostdinc -m32 -nostdlib -W -Wall -Wextra -Wno-builtin-declaration-mismatch -Wno-format -fverbose-asm -fno-exceptions -ffreestanding -fno-pic -mstack-protector-guard=global")
+set(CMAKE_C_FLAGS "${C_CXX_FLAGS} -Werror=implicit-int -Werror=implicit-function-declaration -Werror=strict-aliasing")
+set(CMAKE_CXX_FLAGS "${C_CXX_FLAGS} -fno-use-cxa-atexit -fno-rtti")
 set(CMAKE_CXX_LINK_FLAGS "")
 set(CMAKE_CXX_STANDARD 20)
 
@@ -74,7 +75,6 @@ set(KERNEL_MAIN_SOURCES src/fs/fat.cpp
                         include/kernel/hw/timer.h
                         include/kernel/input/keycodes.h
                         include/kernel/input/input_event.h
-                        include/types/assert.h
                         include/types/bitmap.h
                         include/types/buffer.hpp
                         include/types/elf.hpp
@@ -127,6 +127,7 @@ add_custom_target(boot.img
     COMMAND mcopy -i boot.img@@1M ${CMAKE_BINARY_DIR}/user-space-program/stack-test.out ::stack.out
     COMMAND mcopy -i boot.img@@1M ${CMAKE_BINARY_DIR}/user-space-program/init.out ::init.elf
     COMMAND mcopy -i boot.img@@1M ${CMAKE_BINARY_DIR}/user-space-program/sh.out ::sh.elf
+    COMMAND mcopy -i boot.img@@1M ${CMAKE_BINARY_DIR}/user-space-program/priv-test.out ::priv.elf
 )
 
 add_custom_command(OUTPUT run

+ 2 - 1
gblibc/CMakeLists.txt

@@ -9,6 +9,7 @@ add_library(gblibc STATIC
     src/fcntl.c
     src/unistd.c
     src/wait.c
+    src/assert.c
 )
 
 target_include_directories(gblibc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -17,4 +18,4 @@ target_include_directories(gblibc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
 set_target_properties(gblibc PROPERTIES PRIVATE_HEADER
     "private-include/devutil.h,private-include/syscall.h")
 set_target_properties(gblibc PROPERTIES PUBLIC_HEADER
-    "include/stdio.h,include/stdint.h,include/stdarg.h,include/string.h,include/unistd.h,include/sys/types.h,include/sys/wait.h,include/fcntl.h")
+    "include/stdio.h,include/stdint.h,include/stdarg.h,include/string.h,include/unistd.h,include/sys/types.h,include/sys/wait.h,include/fcntl.h,include/assert.h")

+ 21 - 0
gblibc/include/assert.h

@@ -0,0 +1,21 @@
+#ifndef __GBLIBC_ASSERT_H_
+#define __GBLIBC_ASSERT_H_
+
+#ifdef NDEBUG
+#define assert(st) ((void)(st))
+#else
+#define assert(st) ((void)((st) || (__assert_fail(#st, __FILE__, __LINE__, __func__), 0)))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void __attribute__((noreturn))
+__assert_fail(const char* statement, const char* file, int line, const char* func);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 8 - 1
gblibc/include/unistd.h

@@ -3,6 +3,13 @@
 
 #include <sys/types.h>
 
+#undef STDOUT_FILENO
+#undef STDIN_FILENO
+#undef STDERR_FILENO
+#define STDOUT_FILENO (0)
+#define STDIN_FILENO (0)
+#define STDERR_FILENO (0)
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -10,7 +17,7 @@ extern "C" {
 ssize_t read(int fd, void* buf, size_t count);
 ssize_t write(int fd, const void* buf, size_t count);
 
-_Noreturn void _exit(int code);
+void __attribute__((noreturn)) _exit(int code);
 pid_t fork(void);
 int execve(const char* pathname, char* const argv[], char* const envp[]);
 

+ 12 - 0
gblibc/src/assert.c

@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <unistd.h>
+
+_Noreturn void __attribute__((weak))
+__assert_fail(const char* statement, const char* file, int line, const char* func)
+{
+    char buf[256] = {};
+    int len = snprintf(buf, sizeof(buf), "Assertion failed: (%s) in %s:%d, %s\n",
+        statement, file, line, func);
+    write(STDERR_FILENO, buf, len);
+    _exit(-1);
+}

+ 36 - 30
include/kernel/process.hpp

@@ -95,7 +95,7 @@ public:
     constexpr ~thread()
     {
         if (kstack)
-            free_n_raw_pages(to_page(kstack), 2);
+            free_n_raw_pages(to_page(kstack - THREAD_KERNEL_STACK_SIZE), 2);
     }
 };
 
@@ -149,17 +149,34 @@ public:
     class filearr {
     public:
         using container_type = types::list<fs::file>;
-        using array_type = types::hash_map<int, container_type::iterator_type, types::linux_hasher<size_t>>;
+        using array_type = types::map<int, container_type::iterator_type>;
 
     private:
-        inline static container_type* files = nullptr;
+        inline static container_type* files;
         array_type arr;
         int next_fd = 0;
 
+    public:
+        inline static void init_global_file_container(void)
+        {
+            files = types::pnew<types::kernel_allocator>(files);
+        }
+
+    private:
+        // iter should not be nullptr
+        constexpr void _close(container_type::iterator_type iter)
+        {
+            if (iter->ref == 1)
+                files->erase(iter);
+            else
+                --iter->ref;
+        }
+
     public:
         constexpr filearr(const filearr&) = delete;
         constexpr filearr& operator=(const filearr&) = delete;
         constexpr filearr& operator=(filearr&&) = delete;
+        constexpr filearr(void) = default;
         constexpr filearr(filearr&& val)
             : arr { types::move(val.arr) }
             , next_fd { val.next_fd }
@@ -167,12 +184,6 @@ public:
             val.next_fd = 0;
         }
 
-        explicit filearr()
-        {
-            if (!files)
-                files = types::pnew<types::kernel_allocator>(files);
-        }
-
         constexpr void dup(const filearr& orig)
         {
             if (this->next_fd)
@@ -180,13 +191,9 @@ public:
 
             this->next_fd = orig.next_fd;
 
-            for (int i = 0; i < this->next_fd; ++i) {
-                auto iter = orig.arr.find(i);
-                if (!iter)
-                    continue;
-
-                this->arr.emplace(iter->key, iter->value);
-                ++iter->value->ref;
+            for (auto iter : orig.arr) {
+                this->arr.insert(types::make_pair(iter.key, iter.value));
+                ++iter.value->ref;
             }
         }
 
@@ -230,31 +237,28 @@ public:
                 1 });
 
             int fd = next_fd++;
-            arr.emplace(fd, iter);
+            arr.insert(types::make_pair(fd, iter));
             return fd;
         }
 
-        // close file descriptor
-        // where iter is guaranteed not nullptr
-        constexpr void close(array_type::iterator_type iter)
+        constexpr void close(int fd)
         {
-            if (iter->value->ref == 1)
-                files->erase(iter->value);
-            else
-                --iter->value->ref;
+            auto iter = arr.find(fd);
+            if (iter) {
+                _close(iter->value);
+                arr.erase(iter);
+            }
         }
 
-        constexpr void close(int fd)
+        constexpr void close_all(void)
         {
-            auto iter = arr.find(fd);
-            if (iter)
-                close(iter);
+            for (auto iter : this->arr)
+                close(iter.key);
         }
 
         constexpr ~filearr()
         {
-            for (int i = 0; i < next_fd; ++i)
-                close(i);
+            close_all();
         }
     };
 
@@ -360,6 +364,8 @@ public:
             m_child_idx.remove(children);
         }
     }
+
+    void kill(pid_t pid, int exit_code);
 };
 
 class readyqueue final {

+ 0 - 41
include/types/assert.h

@@ -1,41 +0,0 @@
-#pragma once
-
-#include "types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void crash(void);
-void _debugger_breakpoint(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifndef NDEBUG
-#define breakpoint() _debugger_breakpoint()
-#else
-#define breakpoint() _crash()
-#endif
-
-#ifndef NDEBUG
-
-#define assert(_statement) \
-    if (!(_statement)) {   \
-        breakpoint();      \
-        crash();           \
-    }
-
-#define assert_likely(_statement)  \
-    if (unlikely(!(_statement))) { \
-        breakpoint();              \
-        crash();                   \
-    }
-
-#else
-
-#define assert(_statement) (void)(_statement)
-#define assert_likely(_statement) (void)(_statement)
-
-#endif

+ 8 - 8
src/fs/fat.cpp

@@ -1,3 +1,4 @@
+#include <assert.h>
 #include <fs/fat.hpp>
 #include <kernel/mem.h>
 #include <kernel/mm.hpp>
@@ -5,7 +6,6 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <types/allocator.hpp>
-#include <types/assert.h>
 #include <types/hash_map.hpp>
 #include <types/status.h>
 
@@ -13,13 +13,13 @@ namespace fs::fat {
 // buf MUST be larger than 512 bytes
 inline void fat32::_raw_read_sector(void* buf, uint32_t sector_no)
 {
-    assert(vfs_read(
-               device,
-               (char*)buf,
-               SECTOR_SIZE,
-               sector_no * SECTOR_SIZE,
-               SECTOR_SIZE)
-        == SECTOR_SIZE);
+    size_t n = vfs_read(
+        device,
+        (char*)buf,
+        SECTOR_SIZE,
+        sector_no * SECTOR_SIZE,
+        SECTOR_SIZE);
+    assert(n == SECTOR_SIZE);
 }
 
 // buf MUST be larger than 4096 bytes

+ 1 - 0
src/kernel.ld

@@ -22,6 +22,7 @@ SECTIONS
         *(.text*)
         *(.rodata*)
 
+        . = ALIGN(4);
         kernel_text_and_data_size = .;
         LONG(__kernel_text_and_data_end - ADDR(.text));
         asm_kernel_size = .;

+ 1 - 1
src/kernel/event/event.cpp

@@ -1,4 +1,5 @@
 #include <asm/port_io.h>
+#include <assert.h>
 #include <kernel/event/event.h>
 #include <kernel/event/evtqueue.hpp>
 #include <kernel/input/input_event.h>
@@ -6,7 +7,6 @@
 #include <kernel/process.hpp>
 #include <stdio.h>
 #include <types/allocator.hpp>
-#include <types/assert.h>
 #include <types/cplusplus.hpp>
 #include <types/list.hpp>
 #include <types/lock.hpp>

+ 2 - 2
src/kernel/hw/ata.cpp

@@ -1,4 +1,5 @@
 #include <asm/port_io.h>
+#include <assert.h>
 #include <fs/fat.hpp>
 #include <kernel/hw/ata.hpp>
 #include <kernel/syscall.hpp>
@@ -6,7 +7,6 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <types/allocator.hpp>
-#include <types/assert.h>
 #include <types/status.h>
 
 hw::ata::ata(port_id_t p)
@@ -136,7 +136,7 @@ constexpr hw::ata** p_ata_sec = &ata_sec;
 template <hw::ata** ata_bus>
 size_t _ata_read(fs::special_node* sn, char* buf, size_t buf_size, size_t offset, size_t n)
 {
-    assert_likely(buf_size >= n);
+    assert(buf_size >= n);
 
     char b[512] {};
     char* orig_buf = buf;

+ 29 - 3
src/kernel/interrupt.cpp

@@ -1,6 +1,7 @@
 #define _INTERRUPT_C_
 
 #include <asm/port_io.h>
+#include <assert.h>
 #include <kernel/hw/keyboard.h>
 #include <kernel/hw/serial.h>
 #include <kernel/hw/timer.h>
@@ -15,12 +16,19 @@
 #include <kernel_main.hpp>
 #include <stdint.h>
 #include <stdio.h>
-#include <types/assert.h>
 #include <types/size.h>
 #include <types/types.h>
 
 static struct IDT_entry IDT[256];
 
+static inline void NORETURN _halt_forever(void)
+{
+    asm_cli();
+    asm_hlt();
+    for (;;)
+        ;
+}
+
 void init_idt()
 {
     asm_cli();
@@ -159,6 +167,16 @@ static inline void _int14_panic(void* eip, void* cr2, struct page_fault_error_co
     assert(false);
 }
 
+static inline void NORETURN _int14_kill_user(void)
+{
+    char buf[256] {};
+    snprintf(buf, 256, "Segmentation Fault (pid%d killed)\n", current_process->pid);
+    kmsg(buf);
+    procs->kill(current_process->pid, -1);
+    schedule();
+    _halt_forever();
+}
+
 // page fault
 extern "C" void int14_handler(int14_data* d)
 {
@@ -169,8 +187,16 @@ extern "C" void int14_handler(int14_data* d)
         mms = kernel_mms;
 
     auto mm_area = mms->find(d->l_addr);
-    if (unlikely(mm_area == mms->end()))
-        _int14_panic(d->v_eip, d->l_addr, d->error_code);
+    if (unlikely(mm_area == mms->end())) {
+        if (d->error_code.user) {
+            // user access of address that does not exist
+            _int14_kill_user();
+        } else {
+            _int14_panic(d->v_eip, d->l_addr, d->error_code);
+        }
+    }
+    if (unlikely(d->error_code.user && mm_area->attr.in.system))
+        _int14_kill_user();
 
     pte_t* pte = to_pte(mms->m_pd, d->l_addr);
     page* page = lto_page(&mm_area, d->l_addr);

+ 3 - 3
src/kernel/mem.cpp

@@ -1,6 +1,7 @@
 #include <asm/boot.h>
 #include <asm/port_io.h>
 #include <asm/sys.h>
+#include <assert.h>
 #include <kernel/errno.h>
 #include <kernel/mem.h>
 #include <kernel/mm.hpp>
@@ -10,7 +11,6 @@
 #include <kernel_main.hpp>
 #include <stdio.h>
 #include <types/allocator.hpp>
-#include <types/assert.h>
 #include <types/bitmap.h>
 #include <types/size.h>
 #include <types/status.h>
@@ -198,7 +198,7 @@ static brk_memory_allocator
 void* k_malloc(size_t size)
 {
     void* ptr = kernel_heap_allocator->alloc(size);
-    assert_likely(ptr);
+    assert(likely(ptr));
     return ptr;
 }
 
@@ -210,7 +210,7 @@ void k_free(void* ptr)
 void* ki_malloc(size_t size)
 {
     void* ptr = kernel_ident_mapped_allocator.alloc(size);
-    assert_likely(ptr);
+    assert(likely(ptr));
     return ptr;
 }
 

+ 42 - 3
src/kernel/process.cpp

@@ -1,5 +1,6 @@
 #include <asm/port_io.h>
 #include <asm/sys.h>
+#include <assert.h>
 #include <fs/fat.hpp>
 #include <kernel/hw/ata.hpp>
 #include <kernel/interrupt.h>
@@ -12,7 +13,6 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <types/allocator.hpp>
-#include <types/assert.h>
 #include <types/cplusplus.hpp>
 #include <types/elf.hpp>
 #include <types/hash_map.hpp>
@@ -84,6 +84,42 @@ process::process(pid_t _ppid, bool _system)
 {
 }
 
+void proclist::kill(pid_t pid, int exit_code)
+{
+    process* proc = this->find(pid);
+
+    // remove threads from ready list
+    for (auto& thd : proc->thds.underlying_list()) {
+        thd.attr.ready = 0;
+        readythds->remove_all(&thd);
+    }
+
+    // write back mmap'ped files and close them
+    proc->files.close_all();
+
+    // unmap all user memory areas
+    proc->mms.clear_user();
+
+    // init should never exit
+    if (proc->ppid == 0) {
+        console->print("kernel panic: init exited!\n");
+        assert(false);
+    }
+
+    // make child processes orphans (children of init)
+    this->make_children_orphans(pid);
+
+    proc->attr.zombie = 1;
+
+    // notify parent process and init
+    auto* parent = this->find(proc->ppid);
+    auto* init = this->find(1);
+    while (!proc->wait_lst.empty()) {
+        init->wait_lst.push(proc->wait_lst.front());
+    }
+    parent->wait_lst.push({ nullptr, (void*)pid, (void*)exit_code, nullptr });
+}
+
 inline void NORETURN _noreturn_crash(void)
 {
     for (;;)
@@ -161,7 +197,7 @@ void NORETURN _kernel_init(void)
     // TODO: parse kernel parameters
     auto* _new_fs = fs::register_fs(types::_new<types::kernel_allocator, fs::fat::fat32>(fs::vfs_open("/dev/hda1")->ind));
     int ret = fs::fs_root->ind->fs->mount(fs::vfs_open("/mnt"), _new_fs);
-    assert_likely(ret == GB_OK);
+    assert(ret == GB_OK);
 
     current_process->attr.system = 0;
     current_thread->attr.system = 0;
@@ -175,7 +211,8 @@ void NORETURN _kernel_init(void)
     d.envp = envp;
     d.system = false;
 
-    assert(types::elf::elf32_load(&d) == GB_OK);
+    ret = types::elf::elf32_load(&d);
+    assert(ret == GB_OK);
 
     asm volatile(
         "movw $0x23, %%ax\n"
@@ -210,6 +247,8 @@ void NORETURN init_scheduler(void)
     procs = types::pnew<types::kernel_allocator>(procs);
     readythds = types::pnew<types::kernel_allocator>(readythds);
 
+    process::filearr::init_global_file_container();
+
     // init process has no parent
     auto* init = &procs->emplace(0)->value;
     init->files.open("/dev/console", 0);

+ 2 - 34
src/kernel/syscall.cpp

@@ -1,5 +1,6 @@
 #include <asm/port_io.h>
 #include <asm/sys.h>
+#include <assert.h>
 #include <kernel/errno.h>
 #include <kernel/interrupt.h>
 #include <kernel/log.hpp>
@@ -13,7 +14,6 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <types/allocator.hpp>
-#include <types/assert.h>
 #include <types/elf.hpp>
 #include <types/status.h>
 
@@ -159,8 +159,6 @@ void _syscall_exec(interrupt_stack* data)
 void _syscall_exit(interrupt_stack* data)
 {
     uint32_t exit_code = data->s_regs.edi;
-    pid_t pid = current_process->pid;
-    pid_t ppid = current_process->ppid;
 
     // TODO: terminating a thread only
     if (current_thread->owner->thds.size() != 1) {
@@ -168,37 +166,7 @@ void _syscall_exit(interrupt_stack* data)
     }
 
     // terminating a whole process:
-
-    // remove threads from ready list
-    for (auto& thd : current_process->thds.underlying_list()) {
-        thd.attr.ready = 0;
-        readythds->remove_all(&thd);
-    }
-
-    // TODO: write back mmap'ped files and close them
-
-    // unmap all user memory areas
-    current_process->mms.clear_user();
-
-    // init should never exit
-    if (current_process->ppid == 0) {
-        console->print("kernel panic: init exited!\n");
-        crash();
-    }
-
-    // make child processes orphans (children of init)
-    procs->make_children_orphans(pid);
-
-    current_process->attr.zombie = 1;
-
-    // notify parent process and init
-    auto* proc = procs->find(pid);
-    auto* parent = procs->find(ppid);
-    auto* init = procs->find(1);
-    while (!proc->wait_lst.empty()) {
-        init->wait_lst.push(proc->wait_lst.front());
-    }
-    parent->wait_lst.push({ current_thread, (void*)pid, (void*)exit_code, nullptr });
+    procs->kill(current_process->pid, exit_code);
 
     // switch to new process and continue
     schedule();

+ 1 - 1
src/kernel/vfs.cpp

@@ -1,3 +1,4 @@
+#include <assert.h>
 #include <kernel/errno.h>
 #include <kernel/mem.h>
 #include <kernel/tty.hpp>
@@ -5,7 +6,6 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <types/allocator.hpp>
-#include <types/assert.h>
 #include <types/list.hpp>
 #include <types/map.hpp>
 #include <types/pair.hpp>

+ 8 - 32
src/kernel_main.cpp

@@ -3,6 +3,7 @@
 #include <asm/boot.h>
 #include <asm/port_io.h>
 #include <asm/sys.h>
+#include <assert.h>
 #include <kernel/event/event.h>
 #include <kernel/hw/keyboard.h>
 #include <kernel/hw/serial.h>
@@ -16,7 +17,6 @@
 #include <kernel/vga.hpp>
 #include <stdint.h>
 #include <stdio.h>
-#include <types/assert.h>
 #include <types/bitmap.h>
 #include <types/status.h>
 #include <types/types.h>
@@ -138,7 +138,6 @@ int init_console(const char* name)
             return GB_OK;
         }
     }
-    crash();
     return GB_FAILED;
 }
 
@@ -147,7 +146,9 @@ extern "C" uint32_t check_a20_on(void);
 
 extern "C" void NORETURN kernel_main(void)
 {
-    assert(check_a20_on());
+    int ret;
+    ret = check_a20_on();
+    assert(ret == 1);
 
     asm_enable_sse();
 
@@ -164,14 +165,16 @@ extern "C" void NORETURN kernel_main(void)
 
     char buf[KERNEL_MAIN_BUF_SIZE] = { 0 };
 
-    assert(init_serial_port(PORT_SERIAL0) == GB_OK);
+    ret = init_serial_port(PORT_SERIAL0);
+    assert(ret == GB_OK);
 
     init_idt();
     init_mem();
     init_pic();
     init_pit();
 
-    assert(init_console("ttyS0") == GB_OK);
+    ret = init_console("ttyS0");
+    assert(ret == GB_OK);
 
     show_mem_info(buf);
 
@@ -180,30 +183,3 @@ extern "C" void NORETURN kernel_main(void)
     kmsg("switching execution to the scheduler...\n");
     init_scheduler();
 }
-
-void NORETURN __stack_chk_fail(void)
-{
-    kmsg("***** stack smashing detected! *****\n");
-    for (;;)
-        assert(0);
-}
-
-extern "C" void NORETURN __cxa_pure_virtual(void)
-{
-    for (;;)
-        assert(0);
-}
-
-void crash(void)
-{
-    asm volatile("ud2");
-}
-
-void _debugger_breakpoint(void)
-{
-#ifdef __BOCHS_SYSTEM__
-    asm volatile("xchgw %%bx, %%bx");
-#else
-    asm volatile("nop");
-#endif
-}

+ 2 - 2
src/types/elf.cpp

@@ -1,9 +1,9 @@
+#include <assert.h>
 #include <kernel/errno.h>
 #include <kernel/mem.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
-#include <types/assert.h>
 #include <types/elf.hpp>
 #include <types/string.hpp>
 #include <types/vector.hpp>
@@ -94,7 +94,7 @@ int types::elf::elf32_load(types::elf::elf32_load_data* d)
     // map stack area
     auto ret = mmap((void*)types::elf::ELF_STACK_TOP, types::elf::ELF_STACK_SIZE,
         fs::vfs_open("/dev/null")->ind, 0, 1, 0);
-    assert_likely(ret == GB_OK);
+    assert(ret == GB_OK);
 
     d->eip = (void*)hdr.entry;
     d->sp = reinterpret_cast<uint32_t*>(types::elf::ELF_STACK_BOTTOM);

+ 30 - 3
src/types/libstdcpp.cpp

@@ -1,10 +1,37 @@
-#include <types/assert.h>
+#include <asm/port_io.h>
+#include <assert.h>
+#include <kernel/log.hpp>
+#include <stdio.h>
+#include <types/types.h>
 
 void operator delete(void*)
 {
-    crash();
+    assert(false);
 }
 void operator delete(void*, unsigned int)
 {
-    crash();
+    assert(false);
+}
+
+extern "C" void NORETURN __stack_chk_fail(void)
+{
+    assert(false);
+}
+
+extern "C" void NORETURN __cxa_pure_virtual(void)
+{
+    assert(false);
+}
+
+void NORETURN
+__assert_fail(const char* statement, const char* file, int line, const char* func)
+{
+    char buf[256];
+    snprintf(buf, sizeof(buf), "Kernel assertion failed: (%s), %s:%d, %s\n",
+        statement, file, line, func);
+    kmsg(buf);
+    asm_cli();
+    asm_hlt();
+    for (;;)
+        ;
 }

+ 2 - 1
user-space-program/CMakeLists.txt

@@ -16,7 +16,8 @@ add_executable(interrupt-test.out interrupt-test.s)
 add_executable(stack-test.out stack-test.s)
 add_executable(init.out init.c)
 add_executable(sh.out sh.c)
+add_executable(priv-test.out priv-test.c)
 
 add_custom_target(user_space_programs
-    DEPENDS hello-world.out interrupt-test.out stack-test.out init.out sh.out
+    DEPENDS hello-world.out interrupt-test.out stack-test.out init.out sh.out priv-test.out
 )

+ 1 - 1
user-space-program/init.c

@@ -3,7 +3,7 @@
 #include <unistd.h>
 #include <sys/wait.h>
 
-#define print(str) write(0, str, strlen(str))
+#define print(str) write(STDERR_FILENO, str, strlen(str))
 
 int main(int argc, char** argv)
 {

+ 5 - 0
user-space-program/priv-test.c

@@ -0,0 +1,5 @@
+int main(void) {
+    int* ptr = (int*)0x10000;
+    *ptr = 0x114514;
+    return -1;
+}

+ 2 - 2
user-space-program/sh.c

@@ -3,7 +3,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#define print(str) write(0, str, strlen(str))
+#define print(str) write(STDOUT_FILENO, str, strlen(str))
 
 // struct cmd {
 //     enum {
@@ -56,7 +56,7 @@ int main(int argc, const char** argv)
     print("sh # ");
 
     for (;;) {
-        int n = read(0, buf, sizeof(buf));
+        int n = read(STDIN_FILENO, buf, sizeof(buf));
 
         char token[1024] = {};
         char* args[128] = { token, 0 };