SCRAM(2)

NAME
scram - emergency process shutdown

SYNOPSIS
#include <scram.h>
void
scram(int event, const void *info);

DESCRIPTION
scram() unconditionally terminates the process abnormally due to the specified event. It is designed for use when the process has potentially been compromised and therefore can’t possibly continue safely. Its use does not necessarily mean the process was compromised, but it does imply a bug was detected.

The event information structures are designed to be trivially to filled in during an emergency with the information that is readily available. If the process has potentially been compromised, the calling function should not do any formatting of debug information or perform memory allocations, but just use existing values or constants as the event information and call scram() to terminate the process immediately. The kernel will use the provided event information to write a formatted error message to the kernel log.

event specifies which kind of event occurred and can be one of:

SCRAM_ASSERT
    Assertion failure.
SCRAM_STACK_SMASH
    Stack smash.
SCRAM_UNDEFINED_BEHAVIOR
    Undefined behavior.

info points to the appropriate structure containing further information on the event or NULL if there is no information available:

    struct scram_assert { /* SCRAM_ASSERT */
        const char *filename; /* file the assertion failed in */
        unsigned long line; /* line the assertion failed on */
        const char *function; /* function containing the assertion */
        const char *expression; /* assertion expression */
    };
    /* SCRAM_STACK_SMASH has no information structure */
    struct scram_undefined_behavior { /* SCRAM_UNDEFINED_BEHAVIOR */
        const char *filename; /* file with undefined behavior */
        unsigned long line; /* line with undefined behavior */
        unsigned long column; /* column on the line with undefined behavior */
        const char *violation; /* description of the undefined behavior */
    };

RETURN VALUES
The scram() function never returns as the process is unconditionally terminated.

ERRORS
scram() never fails as the process is always terminated, even on invalid parameters. The kernel may fail to allocate copies of strings, in which case "<unknown>" is used as a replacement in the error message.

NOTES
scram() is generally not meant to be used directly by application developers, but is for internal use by the standard library in the implementation of assert(3), the stack protector ((gcc) 1 -fstack-protector), and the undefined behavior sanitizer ((gcc) 1 -fsanitize=undefined). The design of scram() is motivated by gcc's upstream libssp and libubsan libraries, which attempt to print debug information prior to terminating the process abnormally. Doing so is a risk, as the process may have been compromised and basic things like stdio cannot be trusted as crucial pointers and state may have been overwritten, and memory allocations are dangerous because the heap might be damaged. Attempting to format debug information may ironically give the attacker another chance to subvert control flow. The gcc upstream libubsan library is designed for debugging and should not go anywhere near production.

The scram() function avoids all these issues by design by having the kernel print the debug information. Sortix uses neither gcc library and the standard library has its own secure implementations using scram(). It is always safe and desirable to use these features in production on Sortix.

SEE ALSO
gcc(1), _exit(2), exit_thread(2), assert(3), exit(3)

HISTORY
The scram() system call originally appeared in Sortix 1.0.