X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5c19dc3ae3bd8e40a9c028b0deddd50ff337692c..650c69f3f74fd8ed7cca83ea430e351a1c2fee04:/OSX/libsecurity_utilities/lib/errors.cpp diff --git a/OSX/libsecurity_utilities/lib/errors.cpp b/OSX/libsecurity_utilities/lib/errors.cpp index eab27f83..e715b11d 100644 --- a/OSX/libsecurity_utilities/lib/errors.cpp +++ b/OSX/libsecurity_utilities/lib/errors.cpp @@ -27,9 +27,14 @@ // #include #include +#include +#include #include #include #include +#include +#include +#include //@@@ // From cssmapple.h - layering break @@ -40,13 +45,8 @@ // // The base of the exception hierarchy. -// Note that the debug output here depends on a particular -// implementation feature of gcc; to wit, that the exception object -// is created and then copied (at least once) via its copy constructor. -// If your compiler does not invoke the copy constructor, you won't get -// debug output, but nothing worse should happen. // -CommonError::CommonError() +CommonError::CommonError() : whatBuffer("CommonError") { } @@ -54,34 +54,91 @@ CommonError::CommonError() // // We strongly encourage catching all exceptions by const reference, so the copy // constructor of our exceptions should never be called. -// We trace a copy to help catch violations of this rule. // CommonError::CommonError(const CommonError &source) { - SECURITY_EXCEPTION_COPY(this, &source); + strlcpy(whatBuffer, source.whatBuffer, whatBufferSize); } CommonError::~CommonError() throw () { - SECURITY_EXCEPTION_HANDLED(this); } +void CommonError::LogBacktrace() { + // Only do this work if we're actually going to log things + if(secinfoenabled("security_exception")) { + const size_t maxsize = 32; + void* callstack[maxsize]; + + int size = backtrace(callstack, maxsize); + char** names = backtrace_symbols(callstack, size); + + // C++ symbolicate the callstack + + const char* delim = " "; + string build; + char * token = NULL; + char * line = NULL; + + for(int i = 0; i < size; i++) { + build = ""; + + line = names[i]; + + while((token = strsep(&line, delim))) { + if(*token == '\0') { + build += " "; + } else { + int status = 0; + char * demangled = abi::__cxa_demangle(token, NULL, NULL, &status); + if(status == 0) { + build += demangled; + } else { + build += token; + } + build += " "; + + if(demangled) { + free(demangled); + } + } + } + + secinfo("security_exception", "%s", build.c_str()); + } + free(names); + } +} + + // // UnixError exceptions // UnixError::UnixError() : error(errno) { - SECURITY_EXCEPTION_THROW_UNIX(this, errno); + SECURITY_EXCEPTION_THROW_UNIX(this, errno); + + snprintf(whatBuffer, whatBufferSize, "UNIX errno exception: %d", this->error); + secnotice("security_exception", "%s", what()); + LogBacktrace(); } -UnixError::UnixError(int err) : error(err) +UnixError::UnixError(int err, bool suppresslogging) : error(err) { - SECURITY_EXCEPTION_THROW_UNIX(this, err); + SECURITY_EXCEPTION_THROW_UNIX(this, err); + + if(!suppresslogging || secinfoenabled("security_exception")) { + snprintf(whatBuffer, whatBufferSize, "UNIX error exception: %d", this->error); + secnotice("security_exception", "%s", what()); + LogBacktrace(); + } } const char *UnixError::what() const throw () -{ return "UNIX error exception"; } +{ + return whatBuffer; +} OSStatus UnixError::osStatus() const @@ -92,10 +149,12 @@ OSStatus UnixError::osStatus() const int UnixError::unixError() const { return error; } -void UnixError::throwMe(int err) { throw UnixError(err); } +void UnixError::throwMe(int err) { throw UnixError(err, false); } +void UnixError::throwMeNoLogging(int err) { throw UnixError(err, true); } + // @@@ This is a hack for the Network protocol state machine -UnixError UnixError::make(int err) { return UnixError(err); } +UnixError UnixError::make(int err) { return UnixError(err, false); } // @@ -103,11 +162,23 @@ UnixError UnixError::make(int err) { return UnixError(err); } // MacOSError::MacOSError(int err) : error(err) { - SECURITY_EXCEPTION_THROW_OSSTATUS(this, err); + SECURITY_EXCEPTION_THROW_OSSTATUS(this, err); + + snprintf(whatBuffer, whatBufferSize, "MacOS error: %d", this->error); + switch (err) { + case errSecCSReqFailed: + // This 'error' isn't an actual error and doesn't warrant being logged. + break; + default: + secnotice("security_exception", "%s", what()); + LogBacktrace(); + } } const char *MacOSError::what() const throw () -{ return "MacOS error"; } +{ + return whatBuffer; +} OSStatus MacOSError::osStatus() const { return error; } @@ -128,6 +199,12 @@ int MacOSError::unixError() const void MacOSError::throwMe(int error) { throw MacOSError(error); } +void MacOSError::throwMe(int error, char const *message, ...) +{ + // Ignoring the message for now, will do something with it later. + throw MacOSError(error); +} + MacOSError MacOSError::make(int error) { return MacOSError(error); } @@ -137,7 +214,9 @@ MacOSError MacOSError::make(int error) // CFError::CFError() { - SECURITY_EXCEPTION_THROW_CF(this); + SECURITY_EXCEPTION_THROW_CF(this); + secnotice("security_exception", "CFError"); + LogBacktrace(); } const char *CFError::what() const throw ()