]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_utilities/lib/errors.cpp
Security-59306.120.7.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / errors.cpp
index eab27f83273374d7e07882bb68b8eb5327d06a1f..e715b11d3e93756c5903ddc5702c96319a2b034b 100644 (file)
 //
 #include <security_utilities/errors.h>
 #include <security_utilities/debugging.h>
+#include <security_utilities/utility_config.h>
+#include <security_utilities/debugging_internal.h>
 #include <typeinfo>
 #include <stdio.h>
 #include <Security/SecBase.h>
+#include <Security/CSCommon.h>
+#include <execinfo.h>
+#include <cxxabi.h>
 
 //@@@
 // From cssmapple.h - layering break
 
 //
 // 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 ()