From d7d187e8a451ae946fa14cead7962edbe0046f12 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 22 Jan 2015 15:02:44 -0500 Subject: [PATCH] allocators: split allocators and pagelocker Pagelocker is only needed for secure (usually wallet) operations, so don't make the zero-after-free allocator depend on it. --- src/Makefile.am | 6 +- src/base58.h | 1 + src/crypter.h | 2 +- src/key.h | 2 +- src/qt/askpassphrasedialog.cpp | 2 +- src/qt/walletmodel.h | 2 +- src/streams.h | 2 +- src/support/allocators/secure.h | 62 ++++++++++++ src/support/allocators/zeroafterfree.h | 48 ++++++++++ .../pagelocker.cpp} | 6 +- src/{allocators.h => support/pagelocker.h} | 96 +------------------ src/test/allocator_tests.cpp | 2 +- 12 files changed, 129 insertions(+), 102 deletions(-) create mode 100644 src/support/allocators/secure.h create mode 100644 src/support/allocators/zeroafterfree.h rename src/{allocators.cpp => support/pagelocker.cpp} (94%) rename src/{allocators.h => support/pagelocker.h} (66%) diff --git a/src/Makefile.am b/src/Makefile.am index da65efa71..4cefc541d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -72,7 +72,6 @@ endif BITCOIN_CORE_H = \ addrman.h \ alert.h \ - allocators.h \ amount.h \ arith_uint256.h \ base58.h \ @@ -123,7 +122,10 @@ BITCOIN_CORE_H = \ script/standard.h \ serialize.h \ streams.h \ + support/allocators/secure.h \ + support/allocators/zeroafterfree.h \ support/cleanse.h \ + support/pagelocker.h \ sync.h \ threadsafety.h \ timedata.h \ @@ -233,7 +235,6 @@ univalue_libbitcoin_univalue_a_SOURCES = \ # common: shared between bitcoind, and bitcoin-qt and non-server tools libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_common_a_SOURCES = \ - allocators.cpp \ arith_uint256.cpp \ amount.cpp \ base58.cpp \ @@ -264,6 +265,7 @@ libbitcoin_common_a_SOURCES = \ # backward-compatibility objects and their sanity checks are linked. libbitcoin_util_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_util_a_SOURCES = \ + support/pagelocker.cpp \ chainparamsbase.cpp \ clientversion.cpp \ compat/glibc_sanity.cpp \ diff --git a/src/base58.h b/src/base58.h index ed134e6e7..8de90046a 100644 --- a/src/base58.h +++ b/src/base58.h @@ -19,6 +19,7 @@ #include "pubkey.h" #include "script/script.h" #include "script/standard.h" +#include "support/allocators/zeroafterfree.h" #include #include diff --git a/src/crypter.h b/src/crypter.h index 8a91498e2..32746b00d 100644 --- a/src/crypter.h +++ b/src/crypter.h @@ -5,9 +5,9 @@ #ifndef BITCOIN_CRYPTER_H #define BITCOIN_CRYPTER_H -#include "allocators.h" #include "keystore.h" #include "serialize.h" +#include "support/allocators/secure.h" class uint256; diff --git a/src/key.h b/src/key.h index 85cc1e55d..1f1d14288 100644 --- a/src/key.h +++ b/src/key.h @@ -6,8 +6,8 @@ #ifndef BITCOIN_KEY_H #define BITCOIN_KEY_H -#include "allocators.h" #include "serialize.h" +#include "support/allocators/secure.h" #include "uint256.h" #include diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index 9b7b59c0d..229139e65 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -8,7 +8,7 @@ #include "guiconstants.h" #include "walletmodel.h" -#include "allocators.h" +#include "support/allocators/secure.h" #include #include diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index de915165f..e26343888 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -8,7 +8,7 @@ #include "paymentrequestplus.h" #include "walletmodeltransaction.h" -#include "allocators.h" /* for SecureString */ +#include "support/allocators/secure.h" #include #include diff --git a/src/streams.h b/src/streams.h index 9999c2341..fa1e18def 100644 --- a/src/streams.h +++ b/src/streams.h @@ -6,7 +6,7 @@ #ifndef BITCOIN_STREAMS_H #define BITCOIN_STREAMS_H -#include "allocators.h" +#include "support/allocators/zeroafterfree.h" #include "serialize.h" #include diff --git a/src/support/allocators/secure.h b/src/support/allocators/secure.h new file mode 100644 index 000000000..7a74d87bb --- /dev/null +++ b/src/support/allocators/secure.h @@ -0,0 +1,62 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2013 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_ALLOCATORS_SECURE_H +#define BITCOIN_ALLOCATORS_SECURE_H + +#include "support/pagelocker.h" + +#include + +// +// Allocator that locks its contents from being paged +// out of memory and clears its contents before deletion. +// +template +struct secure_allocator : public std::allocator { + // MSVC8 default copy constructor is broken + typedef std::allocator base; + typedef typename base::size_type size_type; + typedef typename base::difference_type difference_type; + typedef typename base::pointer pointer; + typedef typename base::const_pointer const_pointer; + typedef typename base::reference reference; + typedef typename base::const_reference const_reference; + typedef typename base::value_type value_type; + secure_allocator() throw() {} + secure_allocator(const secure_allocator& a) throw() : base(a) {} + template + secure_allocator(const secure_allocator& a) throw() : base(a) + { + } + ~secure_allocator() throw() {} + template + struct rebind { + typedef secure_allocator<_Other> other; + }; + + T* allocate(std::size_t n, const void* hint = 0) + { + T* p; + p = std::allocator::allocate(n, hint); + if (p != NULL) + LockedPageManager::Instance().LockRange(p, sizeof(T) * n); + return p; + } + + void deallocate(T* p, std::size_t n) + { + if (p != NULL) { + memory_cleanse(p, sizeof(T) * n); + LockedPageManager::Instance().UnlockRange(p, sizeof(T) * n); + } + std::allocator::deallocate(p, n); + } +}; + +// This is exactly like std::string, but with a custom allocator. +typedef std::basic_string, secure_allocator > SecureString; + +#endif // BITCOIN_ALLOCATORS_SECURE_H diff --git a/src/support/allocators/zeroafterfree.h b/src/support/allocators/zeroafterfree.h new file mode 100644 index 000000000..b01fcd088 --- /dev/null +++ b/src/support/allocators/zeroafterfree.h @@ -0,0 +1,48 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2013 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_ALLOCATORS_ZEROAFTERFREE_H +#define BITCOIN_ALLOCATORS_ZEROAFTERFREE_H + +#include "support/cleanse.h" + +#include +#include + +template +struct zero_after_free_allocator : public std::allocator { + // MSVC8 default copy constructor is broken + typedef std::allocator base; + typedef typename base::size_type size_type; + typedef typename base::difference_type difference_type; + typedef typename base::pointer pointer; + typedef typename base::const_pointer const_pointer; + typedef typename base::reference reference; + typedef typename base::const_reference const_reference; + typedef typename base::value_type value_type; + zero_after_free_allocator() throw() {} + zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) {} + template + zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) + { + } + ~zero_after_free_allocator() throw() {} + template + struct rebind { + typedef zero_after_free_allocator<_Other> other; + }; + + void deallocate(T* p, std::size_t n) + { + if (p != NULL) + memory_cleanse(p, sizeof(T) * n); + std::allocator::deallocate(p, n); + } +}; + +// Byte-vector that clears its contents before deletion. +typedef std::vector > CSerializeData; + +#endif // BITCOIN_ALLOCATORS_ZEROAFTERFREE_H diff --git a/src/allocators.cpp b/src/support/pagelocker.cpp similarity index 94% rename from src/allocators.cpp rename to src/support/pagelocker.cpp index d3958aa4d..440e0a519 100644 --- a/src/allocators.cpp +++ b/src/support/pagelocker.cpp @@ -2,7 +2,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "allocators.h" +#include "support/pagelocker.h" + +#if defined(HAVE_CONFIG_H) +#include "config/bitcoin-config.h" +#endif #ifdef WIN32 #ifdef _WIN32_WINNT diff --git a/src/allocators.h b/src/support/pagelocker.h similarity index 66% rename from src/allocators.h rename to src/support/pagelocker.h index 8ffe015b9..964be1aec 100644 --- a/src/allocators.h +++ b/src/support/pagelocker.h @@ -3,15 +3,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_ALLOCATORS_H -#define BITCOIN_ALLOCATORS_H +#ifndef BITCOIN_ALLOCATORS_PAGELOCKER_H +#define BITCOIN_ALLOCATORS_PAGELOCKER_H #include "support/cleanse.h" #include -#include -#include -#include #include #include @@ -178,91 +175,4 @@ void UnlockObject(const T& t) LockedPageManager::Instance().UnlockRange((void*)(&t), sizeof(T)); } -// -// Allocator that locks its contents from being paged -// out of memory and clears its contents before deletion. -// -template -struct secure_allocator : public std::allocator { - // MSVC8 default copy constructor is broken - typedef std::allocator base; - typedef typename base::size_type size_type; - typedef typename base::difference_type difference_type; - typedef typename base::pointer pointer; - typedef typename base::const_pointer const_pointer; - typedef typename base::reference reference; - typedef typename base::const_reference const_reference; - typedef typename base::value_type value_type; - secure_allocator() throw() {} - secure_allocator(const secure_allocator& a) throw() : base(a) {} - template - secure_allocator(const secure_allocator& a) throw() : base(a) - { - } - ~secure_allocator() throw() {} - template - struct rebind { - typedef secure_allocator<_Other> other; - }; - - T* allocate(std::size_t n, const void* hint = 0) - { - T* p; - p = std::allocator::allocate(n, hint); - if (p != NULL) - LockedPageManager::Instance().LockRange(p, sizeof(T) * n); - return p; - } - - void deallocate(T* p, std::size_t n) - { - if (p != NULL) { - memory_cleanse(p, sizeof(T) * n); - LockedPageManager::Instance().UnlockRange(p, sizeof(T) * n); - } - std::allocator::deallocate(p, n); - } -}; - - -// -// Allocator that clears its contents before deletion. -// -template -struct zero_after_free_allocator : public std::allocator { - // MSVC8 default copy constructor is broken - typedef std::allocator base; - typedef typename base::size_type size_type; - typedef typename base::difference_type difference_type; - typedef typename base::pointer pointer; - typedef typename base::const_pointer const_pointer; - typedef typename base::reference reference; - typedef typename base::const_reference const_reference; - typedef typename base::value_type value_type; - zero_after_free_allocator() throw() {} - zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) {} - template - zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) - { - } - ~zero_after_free_allocator() throw() {} - template - struct rebind { - typedef zero_after_free_allocator<_Other> other; - }; - - void deallocate(T* p, std::size_t n) - { - if (p != NULL) - memory_cleanse(p, sizeof(T) * n); - std::allocator::deallocate(p, n); - } -}; - -// This is exactly like std::string, but with a custom allocator. -typedef std::basic_string, secure_allocator > SecureString; - -// Byte-vector that clears its contents before deletion. -typedef std::vector > CSerializeData; - -#endif // BITCOIN_ALLOCATORS_H +#endif // BITCOIN_ALLOCATORS_PAGELOCKER_H diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp index d4df7b541..2108efece 100644 --- a/src/test/allocator_tests.cpp +++ b/src/test/allocator_tests.cpp @@ -4,7 +4,7 @@ #include "util.h" -#include "allocators.h" +#include "support/allocators/secure.h" #include "test/test_bitcoin.h" #include