diff --git a/misc.h b/misc.h index 61833034..6d58bda6 100644 --- a/misc.h +++ b/misc.h @@ -114,13 +114,13 @@ NAMESPACE_BEGIN(CryptoPP) // Forward declaration for IntToString specialization class Integer; -// ************** compile-time CRYPTOPP_ASSERTion *************** +// ************** compile-time assertion *************** #if CRYPTOPP_DOXYGEN_PROCESSING //! \brief Compile time CRYPTOPP_ASSERTion //! \param expr the expression to evaluate //! \details Asserts the expression expr though a dummy struct. -#define CRYPTOPP_COMPILE_ASSERT(expr) ... +#define CRYPTOPP_COMPILE_ASSERT(expr) { ... } #else // CRYPTOPP_DOXYGEN_PROCESSING template struct CompileAssert @@ -331,88 +331,6 @@ const T & Singleton::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const } #endif -#if defined(CRYPTOPP_BSD_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING) -//! \brief Signal handler function pointer -//! \sa SignalHandler -extern "C" { - typedef void (*SignalHandlerFn) (int); -}; - -//! Signal handler for Linux and Unix compatibles -//! \tparam S Signal number -//! \tparam O Flag indicating exsting handler should be overwriiten -//! \details SignalHandler() can be used to install a signal handler with the signature -//! void handler_fn(int). If SignalHandlerFn is not NULL, then -//! the sigaction is set to the function and the sigaction flags is set to the flags. -//! If SignalHandlerFn is NULL, then a default handler is installed -//! using sigaction flags set to 0. The default handler only returns from the call. -//! \details Upon destruction the previous signal handler is restored. -//! \warning Do not use SignalHandler in a code block that uses setjmp or longjmp -//! because the destructor may not run. -//! \since Crypto++ 5.6.5 -//! \sa SignalHandlerFn, \ref CRYPTOPP_ASSERT "CRYPTOPP_ASSERT", DebugTrapHandler -template -struct SignalHandler : private NotCopyable -{ - //! \brief Construct a signal handler - //! \param pfn Pointer to a signal handler function - //! \param flags Flags to use with the signal handler - //! \details SignalHandler() installs a signal handler with the signature - //! void handler_fn(int). If SignalHandlerFn is not NULL, then - //! the sigaction is set to the function and the sigaction flags is set to the flags. - //! If SignalHandlerFn is NULL, then a default handler is installed - //! using sigaction flags set to 0. The default handler only returns from the call. - //! \details Upon destruction the previous signal handler is restored. - //! \warning Do not use SignalHandler in a code block that uses setjmp or longjmp - //! because the destructor may not run. - //! \since Crypto++ 5.6.5 - SignalHandler(SignalHandlerFn pfn = 0, int flags = 0) : m_installed(false) - { - // http://pubs.opengroup.org/onlinepubs/007908799/xsh/sigaction.html - struct sigaction new_handler; - // memset(&new_handler, 0x00, sizeof(new_handler)); - - do - { - int ret = 0; - - ret = sigaction (S, 0, &m_old); - if (ret != 0) break; // Failed - - // Don't step on another's handler if Overwrite=false - if (m_old.sa_handler != 0 && !O) break; - - // Set up the structure to specify the action. - new_handler.sa_handler = (pfn ? pfn : &SignalHandler::NullHandler); - new_handler.sa_flags = (pfn ? flags : 0); - - ret = sigemptyset (&new_handler.sa_mask); - if (ret != 0) break; // Failed - - // Install it - ret = sigaction (S, &new_handler, 0); - if (ret != 0) break; // Failed - - m_installed = true; - - } while(0); - } - - ~SignalHandler() - { - if (m_installed) - sigaction (S, &m_old, 0); - } - -private: - - struct sigaction m_old; - bool m_installed; - - static void NullHandler(int /*unused*/) { } -}; -#endif - // ************** misc functions *************** #if (!__STDC_WANT_SECURE_LIB__ && !defined(_MEMORY_S_DEFINED)) || defined(CRYPTOPP_WANT_SECURE_LIB) diff --git a/ossig.h b/ossig.h new file mode 100644 index 00000000..44a74a5b --- /dev/null +++ b/ossig.h @@ -0,0 +1,112 @@ +// ossig.h - written and placed in the public domain by Jeffrey Walton +// Copyright assigned to Crypto++ project. + +//! \file ossig.h +//! \brief Utility class for trapping OS signals. +//! \since Crypto++ 5.6.5 + +#ifndef CRYPTOPP_OS_SIGNAL_H +#define CRYPTOPP_OS_SIGNAL_H + +#include "config.h" + +#if defined(CRYPTOPP_BSD_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE) +# include +#endif + +NAMESPACE_BEGIN(CryptoPP) + +// ************** Unix and Linux compatibles *************** + +#if defined(CRYPTOPP_BSD_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING) +//! \brief Signal handler function pointer +//! \sa SignalHandler +extern "C" { + typedef void (*SignalHandlerFn) (int); +}; + +//! Signal handler for Linux and Unix compatibles +//! \tparam S Signal number +//! \tparam O Flag indicating exsting handler should be overwriiten +//! \details SignalHandler() can be used to install a signal handler with the signature +//! void handler_fn(int). If SignalHandlerFn is not NULL, then +//! the sigaction is set to the function and the sigaction flags is set to the flags. +//! If SignalHandlerFn is NULL, then a default handler is installed +//! using sigaction flags set to 0. The default handler only returns from the call. +//! \details Upon destruction the previous signal handler is restored if the former signal handler +//! was replaced. +//! \warning Do not use SignalHandler in a code block that uses setjmp or longjmp +//! because the destructor may not run. +//! \since Crypto++ 5.6.5 +//! \sa SignalHandlerFn, \ref CRYPTOPP_ASSERT "CRYPTOPP_ASSERT", DebugTrapHandler +template +struct SignalHandler +{ + //! \brief Construct a signal handler + //! \param pfn Pointer to a signal handler function + //! \param flags Flags to use with the signal handler + //! \details SignalHandler() installs a signal handler with the signature + //! void handler_fn(int). If SignalHandlerFn is not NULL, then + //! the sigaction is set to the function and the sigaction flags is set to the flags. + //! If SignalHandlerFn is NULL, then a default handler is installed + //! using sigaction flags set to 0. The default handler only returns from the call. + //! \details Upon destruction the previous signal handler is restored if the former signal handler + //! was overwritten. + //! \warning Do not use SignalHandler in a code block that uses setjmp or longjmp + //! because the destructor may not run. setjmp is why cpu.cpp does not use SignalHandler + //! during CPU feature testing. + //! \since Crypto++ 5.6.5 + SignalHandler(SignalHandlerFn pfn = 0, int flags = 0) : m_installed(false) + { + // http://pubs.opengroup.org/onlinepubs/007908799/xsh/sigaction.html + struct sigaction new_handler; + // memset(&new_handler, 0x00, sizeof(new_handler)); + + do + { + int ret = 0; + + ret = sigaction (S, 0, &m_old); + if (ret != 0) break; // Failed + + // Don't step on another's handler if Overwrite=false + if (m_old.sa_handler != 0 && !O) break; + + // Set up the structure to specify the action. + new_handler.sa_handler = (pfn ? pfn : &SignalHandler::NullHandler); + new_handler.sa_flags = (pfn ? flags : 0); + + ret = sigemptyset (&new_handler.sa_mask); + if (ret != 0) break; // Failed + + // Install it + ret = sigaction (S, &new_handler, 0); + if (ret != 0) break; // Failed + + m_installed = true; + + } while(0); + } + + ~SignalHandler() + { + if (m_installed) + sigaction (S, &m_old, 0); + } + +private: + struct sigaction m_old; + bool m_installed; + + static void NullHandler(int /*unused*/) { /* continue*/ } + +private: + // Not copyable + SignalHandler(const SignalHandler &); + void operator=(const SignalHandler &); +}; +#endif + +NAMESPACE_END + +#endif // CRYPTOPP_OS_SIGNAL_H diff --git a/test.cpp b/test.cpp index 52dd740a..682db2f8 100644 --- a/test.cpp +++ b/test.cpp @@ -21,6 +21,7 @@ #include "whrlpool.h" #include "tiger.h" #include "smartptr.h" +#include "ossig.h" #include "trap.h" #include "validate.h" @@ -132,6 +133,7 @@ RandomNumberGenerator & GlobalRNG() // See misc.h and trap.h for comments and usage #if CRYPTOPP_DEBUG && (defined(CRYPTOPP_BSD_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE)) static const SignalHandler s_dummyHandler; +// static const DebugTrapHandle s_dummyHandler; #endif int CRYPTOPP_API main(int argc, char *argv[]) diff --git a/trap.h b/trap.h index 7a5d4a39..a15ef235 100644 --- a/trap.h +++ b/trap.h @@ -17,6 +17,7 @@ #define CRYPTOPP_TRAP_H #include "config.h" +#include "ossig.h" #if CRYPTOPP_DEBUG # include @@ -24,8 +25,6 @@ # if defined(CRYPTOPP_WIN32_AVAILABLE) # define WIN32_LEAN_AND_MEAN # include -# elif defined(CRYPTOPP_BSD_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE) -# include # endif #endif // CRYPTOPP_DEBUG @@ -131,46 +130,14 @@ NAMESPACE_BEGIN(CryptoPP) //! \since Crypto++ 5.6.5 //! \sa \ref CRYPTOPP_ASSERT "CRYPTOPP_ASSERT", SignalHandler, Issue 277, //! CVE-2016-7420 -struct DebugTrapHandler -{ - DebugTrapHandler() - { - // http://pubs.opengroup.org/onlinepubs/007908799/xsh/sigaction.html - struct sigaction old_handler, new_handler; - memset(&old_handler, 0x00, sizeof(old_handler)); - memset(&new_handler, 0x00, sizeof(new_handler)); - do - { - int ret = 0; +#if defined(CRYPTOPP_DOXYGEN_PROCESSING) +class DebugTrapHandler : public SignalHandler { }; +#else +typedef SignalHandler DebugTrapHandler; +#endif - ret = sigaction (SIGTRAP, 0, &old_handler); - if (ret != 0) break; // Failed - - // Don't step on another's handler - if (old_handler.sa_handler != 0) break; - - // Set up the structure to specify the NULL action. - new_handler.sa_handler = &DebugTrapHandler::NullHandler; - new_handler.sa_flags = 0; - - ret = sigemptyset (&new_handler.sa_mask); - if (ret != 0) break; // Failed - - // Install it - ret = sigaction (SIGTRAP, &new_handler, 0); - if (ret != 0) break; // Failed - - } while(0); - } - - static void NullHandler(int /*unused*/) { } - -private: - DebugTrapHandler(const DebugTrapHandler &); - void operator=(const DebugTrapHandler &); -}; -#endif // DebugTrapHandler +#endif // Linux, Unix and Documentation NAMESPACE_END