Add scram(2).

This commit is contained in:
Jonas 'Sortie' Termansen 2015-10-27 17:34:54 +01:00
parent f2eb347e9f
commit 4b6b06bbc8
9 changed files with 229 additions and 29 deletions

View File

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

View File

@ -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

View File

@ -29,6 +29,7 @@
#include <errno.h>
#include <limits.h>
#include <msr.h>
#include <scram.h>
#include <signal.h>
#include <stdint.h>
#include <stdlib.h>
@ -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 : "<unknown>",
info.line,
info.function ? info.function : "<unknown>",
info.expression ? info.expression : "<unknown>");
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 : "<unknown>",
info.filename ? info.filename : "<unknown>",
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

View File

@ -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" */

View File

@ -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 \

View File

@ -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 <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <scram.h>
#if defined(__is_sortix_kernel)
#include <sortix/kernel/decl.h>
#include <sortix/kernel/panic.h>
#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
}

61
libc/include/scram.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
scram.h
Emergency process shutdown.
*******************************************************************************/
#ifndef _SCRAM_H
#define _SCRAM_H
#include <sys/cdefs.h>
#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

35
libc/scram/scram.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
scram/scram.cpp
Emergency process shutdown.
*******************************************************************************/
#include <sys/syscall.h>
#include <scram.h>
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();
}

View File

@ -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 <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <scram.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}