Bläddra i källkod

Merge branch 'kill'

greatbridf 2 år sedan
förälder
incheckning
24d92f5489

+ 1 - 0
CMakeLists.txt

@@ -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 - 0
include/kernel/process.hpp

@@ -364,6 +364,8 @@ public:
             m_child_idx.remove(children);
         }
     }
+
+    void kill(pid_t pid, int exit_code);
 };
 
 class readyqueue final {

+ 28 - 2
src/kernel/interrupt.cpp

@@ -21,6 +21,14 @@
 
 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);

+ 36 - 0
src/kernel/process.cpp

@@ -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");
+        crash();
+    }
+
+    // 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 (;;)

+ 1 - 33
src/kernel/syscall.cpp

@@ -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();

+ 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
 )

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

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