diff --git a/kernel/include/sortix/kernel/syscall.h b/kernel/include/sortix/kernel/syscall.h index e62ab625..f1ef4586 100644 --- a/kernel/include/sortix/kernel/syscall.h +++ b/kernel/include/sortix/kernel/syscall.h @@ -134,6 +134,7 @@ ssize_t sys_readv(int, const struct iovec*, int); ssize_t sys_recv(int, void*, size_t, int); ssize_t sys_recvmsg(int, struct msghdr*, int); int sys_renameat(int, const char*, int, const char*); +void sys_scram(int, const void*); int sys_sched_yield(void); ssize_t sys_send(int, const void*, size_t, int); ssize_t sys_sendmsg(int, const struct msghdr*, int); diff --git a/kernel/include/sortix/syscall.h b/kernel/include/sortix/syscall.h index 53634be4..ed77701b 100644 --- a/kernel/include/sortix/syscall.h +++ b/kernel/include/sortix/syscall.h @@ -180,6 +180,14 @@ #define SYSCALL_CLOSEFROM 152 #define SYSCALL_RESERVED1 153 #define SYSCALL_PSCTL 154 -#define SYSCALL_MAX_NUM 155 /* index of highest constant + 1 */ +#define SYSCALL_RESERVED2 155 +#define SYSCALL_RESERVED3 156 +#define SYSCALL_RESERVED4 157 +#define SYSCALL_RESERVED5 158 +#define SYSCALL_RESERVED6 159 +#define SYSCALL_RESERVED7 160 +#define SYSCALL_RESERVED8 161 +#define SYSCALL_SCRAM 162 +#define SYSCALL_MAX_NUM 163 /* index of highest constant + 1 */ #endif diff --git a/kernel/process.cpp b/kernel/process.cpp index 824bc7bd..706b4175 100644 --- a/kernel/process.cpp +++ b/kernel/process.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -1643,4 +1644,93 @@ mode_t sys_getumask(void) return process->umask; } +static void GetAssertInfo(struct scram_assert* info, + const void* user_info_ptr) +{ + memset(info, 0, sizeof(*info)); + struct scram_assert user_info; + if ( !CopyFromUser(&user_info, user_info_ptr, sizeof(user_info)) ) + return; + info->filename = GetStringFromUser(user_info.filename); + info->line = user_info.line; + info->function = GetStringFromUser(user_info.function); + info->expression = GetStringFromUser(user_info.expression); +} + +static void FreeAssertInfo(struct scram_assert* info) +{ + delete[] (char*) info->filename; + delete[] (char*) info->function; + delete[] (char*) info->expression; +} + +static +void GetUndefinedBehaviorInfo(struct scram_undefined_behavior* info, + const void* user_info_ptr) +{ + memset(info, 0, sizeof(*info)); + struct scram_undefined_behavior user_info; + if ( !CopyFromUser(&user_info, user_info_ptr, sizeof(user_info)) ) + return; + info->filename = GetStringFromUser(user_info.filename); + info->line = user_info.line; + info->column = user_info.column; + info->violation = GetStringFromUser(user_info.violation); +} + +static void FreeUndefinedBehaviorInfo(struct scram_undefined_behavior* info) +{ + delete[] info->filename; + delete[] info->violation; +} + +__attribute__((noreturn)) +void sys_scram(int event, const void* user_info) +{ + Process* process = CurrentProcess(); + // TODO: Prohibit execve such that program_image_path is protected. + process->ExitThroughSignal(SIGABRT); + if ( event == SCRAM_ASSERT ) + { + struct scram_assert info; + GetAssertInfo(&info, user_info); + Log::PrintF("%s[%ji]: Assertion failure: %s:%lu: %s: %s\n", + process->program_image_path, + (intmax_t) process->pid, + info.filename ? info.filename : "", + info.line, + info.function ? info.function : "", + info.expression ? info.expression : ""); + FreeAssertInfo(&info); + } + else if ( event == SCRAM_STACK_SMASH ) + { + Log::PrintF("%s[%ji]: Stack smashing detected\n", + process->program_image_path, + (intmax_t) process->pid); + } + else if ( event == SCRAM_UNDEFINED_BEHAVIOR ) + { + struct scram_undefined_behavior info; + GetUndefinedBehaviorInfo(&info, user_info); + Log::PrintF("%s[%ji]: Undefined behavior: %s at %s:%lu:%lu\n", + process->program_image_path, + (intmax_t) process->pid, + info.violation ? info.violation : "", + info.filename ? info.filename : "", + info.line, + info.column); + FreeUndefinedBehaviorInfo(&info); + } + else + { + Log::PrintF("%s[%ji]: Unknown scram event %i\n", + process->program_image_path, + (intmax_t) process->pid, + event); + } + // TODO: Allow debugging this event. + kthread_exit(); +} + } // namespace Sortix diff --git a/kernel/syscall.cpp b/kernel/syscall.cpp index 2537d27e..b2dd8b88 100644 --- a/kernel/syscall.cpp +++ b/kernel/syscall.cpp @@ -190,6 +190,14 @@ void* syscall_list[SYSCALL_MAX_NUM + 1] = [SYSCALL_CLOSEFROM] = (void*) sys_closefrom, [SYSCALL_RESERVED1] = (void*) sys_bad_syscall, [SYSCALL_PSCTL] = (void*) sys_psctl, + [SYSCALL_RESERVED2] = (void*) sys_bad_syscall, + [SYSCALL_RESERVED3] = (void*) sys_bad_syscall, + [SYSCALL_RESERVED4] = (void*) sys_bad_syscall, + [SYSCALL_RESERVED5] = (void*) sys_bad_syscall, + [SYSCALL_RESERVED6] = (void*) sys_bad_syscall, + [SYSCALL_RESERVED7] = (void*) sys_bad_syscall, + [SYSCALL_RESERVED8] = (void*) sys_bad_syscall, + [SYSCALL_SCRAM] = (void*) sys_scram, [SYSCALL_MAX_NUM] = (void*) sys_bad_syscall, }; } /* extern "C" */ diff --git a/libc/Makefile b/libc/Makefile index 1f8443b9..53ccb5d4 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -401,6 +401,7 @@ pwd/getpwuid_r.o \ pwd/openpw.o \ pwd/setpwent.o \ sched/sched_yield.o \ +scram/scram.o \ signal/kill.o \ signal/killpg.o \ signal/psiginfo.o \ diff --git a/libc/assert/__assert.cpp b/libc/assert/__assert.cpp index 89db95e5..c2e1cbf7 100644 --- a/libc/assert/__assert.cpp +++ b/libc/assert/__assert.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2015. This file is part of the Sortix C Library. @@ -23,12 +23,9 @@ *******************************************************************************/ #include -#include -#include -#include +#include #if defined(__is_sortix_kernel) -#include #include #endif @@ -42,8 +39,11 @@ void __assert(const char* filename, Sortix::PanicF("Assertion failure: %s:%lu: %s: %s", filename, line, function_name, expression); #else - fprintf(stderr, "Assertion failure: %s:%lu: %s: %s\n", filename, line, - function_name, expression); - abort(); + struct scram_assert info; + info.filename = filename; + info.line = line; + info.function = function_name; + info.expression = expression; + scram(SCRAM_ASSERT, &info); #endif } diff --git a/libc/include/scram.h b/libc/include/scram.h new file mode 100644 index 00000000..6c9ee073 --- /dev/null +++ b/libc/include/scram.h @@ -0,0 +1,61 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2015. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + scram.h + Emergency process shutdown. + +*******************************************************************************/ + +#ifndef _SCRAM_H +#define _SCRAM_H + +#include + +#define SCRAM_ASSERT 1 +#define SCRAM_STACK_SMASH 2 +#define SCRAM_UNDEFINED_BEHAVIOR 3 + +struct scram_assert +{ + const char* filename; + unsigned long line; + const char* function; + const char* expression; +}; + +struct scram_undefined_behavior +{ + const char* filename; + unsigned long line; + unsigned long column; + const char* violation; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((noreturn)) +void scram(int, const void*); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/libc/scram/scram.cpp b/libc/scram/scram.cpp new file mode 100644 index 00000000..6d791e7c --- /dev/null +++ b/libc/scram/scram.cpp @@ -0,0 +1,35 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2015. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + scram/scram.cpp + Emergency process shutdown. + +*******************************************************************************/ + +#include + +#include + +DEFN_SYSCALL2(void, sys_scram, SYSCALL_SCRAM, int, const void*); + +extern "C" void scram(int event, const void* info) +{ + sys_scram(event, info); + __builtin_unreachable(); +} diff --git a/libc/stdlib/realpath.cpp b/libc/stdlib/realpath.cpp index 7ea1e389..2b08c9b5 100644 --- a/libc/stdlib/realpath.cpp +++ b/libc/stdlib/realpath.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2013. + Copyright(C) Jonas 'Sortie' Termansen 2013, 2015. This file is part of the Sortix C Library. @@ -25,34 +25,30 @@ #include #include #include +#include #include #include #include #include +#ifdef PATH_MAX +#error "This realpath implementation assumes no PATH_MAX" +#endif + extern "C" char* realpath(const char* restrict path, char* restrict resolved_path) { + if ( resolved_path ) + { + struct scram_undefined_behavior info; + info.filename = __FILE__; + info.line = __LINE__; + info.column = 0; + info.violation = "realpath call with non-null argument and PATH_MAX unset"; + scram(SCRAM_UNDEFINED_BEHAVIOR, &info); + } char* ret_path = canonicalize_file_name(path); if ( !ret_path ) return NULL; - if ( !resolved_path ) - return ret_path; -#ifdef PATH_MAX - if ( PATH_MAX < strlen(ret_path) + 1 ) - return errno = ENAMETOOLONG, (char*) NULL; - strcpy(resolved_path, ret_path); - free(ret_path); - return resolved_path; -#else - if ( !isatty(2) ) - dup2(open("/dev/tty", O_WRONLY), 2); - fprintf(stderr, "%s:%u: %s(\"%s\", %p) = \"%s\": " - "This platform doesn't have PATH_MAX and the second argument " - "wasn't NULL - You cannot reliably allocate a sufficiently large " - "buffer and the POSIX standard specifies this as undefined " - "behavior, aborting.\n", __FILE__, __LINE__, __func__, path, - resolved_path, ret_path); - abort(); -#endif + return ret_path; }