Skip to content

Commit

Permalink
Kernel+LibC: Clean up how assertions work in the kernel and LibC
Browse files Browse the repository at this point in the history
This also brings LibC's abort() function closer to the spec.
  • Loading branch information
gunnarbeutner authored and awesomekling committed Apr 18, 2021
1 parent 33a9b2a commit f033416
Show file tree
Hide file tree
Showing 13 changed files with 36 additions and 73 deletions.
1 change: 0 additions & 1 deletion Kernel/API/Syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ namespace Kernel {
S(prctl) \
S(mremap) \
S(set_coredump_metadata) \
S(abort) \
S(anon_create) \
S(msyscall) \
S(readv) \
Expand Down
18 changes: 17 additions & 1 deletion Kernel/Arch/i386/CPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <Kernel/Arch/x86/ISRStubs.h>
#include <Kernel/Arch/x86/ProcessorInfo.h>
#include <Kernel/Arch/x86/SafeMem.h>
#include <Kernel/Assertions.h>
#include <Kernel/Debug.h>
#include <Kernel/IO.h>
#include <Kernel/Interrupts/APIC.h>
Expand Down Expand Up @@ -2419,6 +2420,13 @@ void __assertion_failed(const char* msg, const char* file, unsigned line, const
dmesgln("ASSERTION FAILED: {}", msg);
dmesgln("{}:{} in {}", file, line, func);

abort();
}
#endif

[[noreturn]] void abort()
{
#ifdef DEBUG
// Switch back to the current process's page tables if there are any.
// Otherwise stack walking will be a disaster.
auto process = Process::current();
Expand All @@ -2427,9 +2435,17 @@ void __assertion_failed(const char* msg, const char* file, unsigned line, const

Kernel::dump_backtrace();
Processor::halt();
}
#endif

abort();
}

[[noreturn]] void _abort()
{
asm volatile("ud2");
__builtin_unreachable();
}

NonMaskableInterruptDisabler::NonMaskableInterruptDisabler()
{
IO::out8(0x70, IO::in8(0x70) | 0x80);
Expand Down
11 changes: 6 additions & 5 deletions Kernel/Assertions.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,13 @@
# define VERIFY_NOT_REACHED() VERIFY(false)
#else
# define VERIFY(expr)
# define VERIFY_NOT_REACHED() CRASH()
# define VERIFY_NOT_REACHED() _abort()
#endif
#define CRASH() \
do { \
asm volatile("ud2"); \
} while (0)

extern "C" {
[[noreturn]] void _abort();
[[noreturn]] void abort();
}

#define VERIFY_INTERRUPTS_DISABLED() VERIFY(!(cpu_flags() & 0x200))
#define VERIFY_INTERRUPTS_ENABLED() VERIFY(cpu_flags() & 0x200)
Expand Down
1 change: 0 additions & 1 deletion Kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ set(KERNEL_SOURCES
StdLib.cpp
Syscall.cpp
Syscalls/anon_create.cpp
Syscalls/abort.cpp
Syscalls/access.cpp
Syscalls/alarm.cpp
Syscalls/beep.cpp
Expand Down
1 change: 0 additions & 1 deletion Kernel/Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,6 @@ class Process
KResultOr<FlatPtr> sys$allocate_tls(size_t);
KResultOr<int> sys$prctl(int option, FlatPtr arg1, FlatPtr arg2);
KResultOr<int> sys$set_coredump_metadata(Userspace<const Syscall::SC_set_coredump_metadata_params*>);
[[noreturn]] void sys$abort();
KResultOr<int> sys$anon_create(size_t, int options);

template<bool sockname, typename Params>
Expand Down
5 changes: 1 addition & 4 deletions Kernel/Syscall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ KResultOr<FlatPtr> handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, F
auto& process = current_thread->process();
current_thread->did_syscall();

if (function == SC_abort || function == SC_exit || function == SC_exit_thread) {
if (function == SC_exit || function == SC_exit_thread) {
// These syscalls need special handling since they never return to the caller.

if (auto* tracer = process.tracer(); tracer && tracer->is_tracing_syscalls()) {
Expand All @@ -109,9 +109,6 @@ KResultOr<FlatPtr> handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, F
}

switch (function) {
case SC_abort:
process.sys$abort();
break;
case SC_exit:
process.sys$exit(arg1);
break;
Expand Down
38 changes: 0 additions & 38 deletions Kernel/Syscalls/abort.cpp

This file was deleted.

1 change: 0 additions & 1 deletion Userland/DevTools/UserspaceEmulator/Emulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ class Emulator {
int virt$connect(int sockfd, FlatPtr address, socklen_t address_size);
int virt$shutdown(int sockfd, int how);
void virt$sync();
void virt$abort();
void virt$exit(int);
ssize_t virt$getrandom(FlatPtr buffer, size_t buffer_size, unsigned int flags);
int virt$chdir(FlatPtr, size_t);
Expand Down
11 changes: 0 additions & 11 deletions Userland/DevTools/UserspaceEmulator/Emulator_syscalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,6 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3)
case SC_sync:
virt$sync();
return 0;
case SC_abort:
virt$abort();
return 0;
case SC_exit:
virt$exit((int)arg1);
return 0;
Expand Down Expand Up @@ -1036,14 +1033,6 @@ void Emulator::virt$sync()
syscall(SC_sync);
}

void Emulator::virt$abort()
{
reportln("\n=={}== \033[33;1mSyscall: abort\033[0m, shutting down!", getpid());
m_exit_status = 127;
m_shutdown = true;
dump_backtrace();
}

void Emulator::virt$exit(int status)
{
reportln("\n=={}== \033[33;1mSyscall: exit({})\033[0m, shutting down!", getpid(), status);
Expand Down
5 changes: 2 additions & 3 deletions Userland/Libraries/LibC/assert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,12 @@ void __assertion_failed(const char* msg)
{ msg, strlen(msg) },
};
syscall(SC_set_coredump_metadata, &params);
syscall(SC_abort);
for (;;) { }
abort();
}
#endif
}

void __crash()
void _abort()
{
asm volatile("ud2");
__builtin_unreachable();
Expand Down
7 changes: 3 additions & 4 deletions Userland/Libraries/LibC/assert.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
__BEGIN_DECLS

#ifdef DEBUG
__attribute__((noreturn)) void __assertion_failed(const char* msg);
[[noreturn]] void __assertion_failed(const char* msg);
# define __stringify_helper(x) # x
# define __stringify(x) __stringify_helper(x)
# define assert(expr) \
Expand All @@ -42,12 +42,11 @@ __attribute__((noreturn)) void __assertion_failed(const char* msg);
# define VERIFY_NOT_REACHED() assert(false)
#else
# define assert(expr) ((void)(0))
# define VERIFY_NOT_REACHED() CRASH()
# define VERIFY_NOT_REACHED() _abort()
#endif

__attribute__((noreturn)) void __crash();
[[noreturn]] void _abort();

#define CRASH() __crash()
#define VERIFY assert
#define TODO VERIFY_NOT_REACHED

Expand Down
8 changes: 6 additions & 2 deletions Userland/Libraries/LibC/stdlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,12 @@ void abort()
// For starters, send ourselves a SIGABRT.
raise(SIGABRT);
// If that didn't kill us, try harder.
raise(SIGKILL);
_exit(127);
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGABRT);
sigprocmask(SIG_UNBLOCK, &set, nullptr);
raise(SIGABRT);
_abort();
}

static HashTable<const char*> s_malloced_environment_variables;
Expand Down
2 changes: 1 addition & 1 deletion Userland/Tests/Kernel/fuzz-syscalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

static bool is_deadly_syscall(int fn)
{
return fn == SC_exit || fn == SC_fork || fn == SC_sigreturn || fn == SC_exit_thread || fn == SC_abort;
return fn == SC_exit || fn == SC_fork || fn == SC_sigreturn || fn == SC_exit_thread;
}

static bool is_unfuzzable_syscall(int fn)
Expand Down

0 comments on commit f033416

Please sign in to comment.