OverSight/Shared/Exception.m

187 lines
5.0 KiB
Objective-C
Executable File

//
// Exception.m
// OverSight
//
// Created by Patrick Wardle on 7/7/16.
// Copyright (c) 2016 Objective-See. All rights reserved.
//
#import "Consts.h"
#import "Logging.h"
#import "Exception.h"
#import "Utilities.h"
#ifdef IS_INSTALLER_APP
#import "AppDelegate.h"
#endif
//global
// ->only report an fatal exception once
BOOL wasReported = NO;
//install exception/signal handlers
void installExceptionHandlers()
{
//sigaction struct
struct sigaction sa = {0};
//init signal struct
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = signalHandler;
//objective-C exception handler
NSSetUncaughtExceptionHandler(&exceptionHandler);
//install signal handlers
sigaction(SIGILL, &sa, NULL);
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGBUS, &sa, NULL);
sigaction(SIGABRT, &sa, NULL);
sigaction(SIGTRAP, &sa, NULL);
sigaction(SIGFPE, &sa, NULL);
return;
}
//exception handler
// will be invoked for Obj-C exceptions
void exceptionHandler(NSException *exception)
{
//error msg
NSString* errorMessage = nil;
//ignore if exception was already reported
if(YES == wasReported)
{
//bail
return;
}
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"OBJECTIVE-SEE ERROR: OS version: %@ /App version: %@", [[NSProcessInfo processInfo] operatingSystemVersionString], getAppVersion()]);
//create error msg
errorMessage = [NSString stringWithFormat:@"unhandled obj-c exception caught [name: %@ / reason: %@]", [exception name], [exception reason]];
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"OBJECTIVE-SEE ERROR: %@", errorMessage]);
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"OBJECTIVE-SEE ERROR: %@", [[NSThread callStackSymbols] description]]);
//set flag
wasReported = YES;
//start installer-specific code
#ifdef IS_INSTALLER_APP
//error info dictionary
NSMutableDictionary* errorInfo = nil;
//alloc
errorInfo = [NSMutableDictionary dictionary];
//add main error msg
errorInfo[KEY_ERROR_MSG] = @"ERROR: unrecoverable fault";
//add sub msg
errorInfo[KEY_ERROR_SUB_MSG] = [exception name];
//set error URL
errorInfo[KEY_ERROR_URL] = FATAL_ERROR_URL;
//fatal error
// ->agent should exit
errorInfo[KEY_ERROR_SHOULD_EXIT] = [NSNumber numberWithBool:YES];
//display error msg
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) displayErrorWindow:errorInfo];
//need to sleep, otherwise returning from this function will cause OS to kill agent
// ->instead, we want error popup to be displayed (which will exit agent when closed)
if(YES != [NSThread isMainThread])
{
//nap
while(YES)
{
//nap
[NSThread sleepForTimeInterval:1.0f];
}
}
//end app-specific code
#endif
return;
}
//handler for signals
// will be invoked for BSD/*nix signals
void signalHandler(int signal, siginfo_t *info, void *context)
{
//error msg
NSString* errorMessage = nil;
//context
ucontext_t *uContext = NULL;
//ignore if exception was already reported
if(YES == wasReported)
{
//bail
return;
}
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"OBJECTIVE-SEE ERROR: OS version: %@ /App version: %@", [[NSProcessInfo processInfo] operatingSystemVersionString], getAppVersion()]);
//typecast context
uContext = (ucontext_t *)context;
//create error msg
errorMessage = [NSString stringWithFormat:@"unhandled exception caught, si_signo: %d /si_code: %s /si_addr: %p /rip: %p",
info->si_signo, (info->si_code == SEGV_MAPERR) ? "SEGV_MAPERR" : "SEGV_ACCERR", info->si_addr, (unsigned long*)uContext->uc_mcontext->__ss.__rip];
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"OBJECTIVE-SEE ERROR: %@", errorMessage]);
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"OBJECTIVE-SEE ERROR: %@", [[NSThread callStackSymbols] description]]);
//set flag
wasReported = YES;
//start installer-specific code
#ifdef IS_INSTALLER_APP
//error info dictionary
NSMutableDictionary* errorInfo = nil;
//alloc
errorInfo = [NSMutableDictionary dictionary];
//add main error msg
errorInfo[KEY_ERROR_MSG] = @"ERROR: unrecoverable fault";
//add sub msg
errorInfo[KEY_ERROR_SUB_MSG] = [NSString stringWithFormat:@"si_signo: %d / rip: %p", info->si_signo, (unsigned long*)uContext->uc_mcontext->__ss.__rip];
//set error URL
errorInfo[KEY_ERROR_URL] = FATAL_ERROR_URL;
//fatal error
// ->agent should exit
errorInfo[KEY_ERROR_SHOULD_EXIT] = [NSNumber numberWithBool:YES];
//display error msg
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) displayErrorWindow:errorInfo];
//end app-specific code
#endif
return;
}