Browse Source

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.
0.13
Cory Fields 10 years ago committed by Wladimir J. van der Laan
parent
commit
d7d187e8a4
  1. 6
      src/Makefile.am
  2. 1
      src/base58.h
  3. 2
      src/crypter.h
  4. 2
      src/key.h
  5. 2
      src/qt/askpassphrasedialog.cpp
  6. 2
      src/qt/walletmodel.h
  7. 2
      src/streams.h
  8. 62
      src/support/allocators/secure.h
  9. 48
      src/support/allocators/zeroafterfree.h
  10. 6
      src/support/pagelocker.cpp
  11. 96
      src/support/pagelocker.h
  12. 2
      src/test/allocator_tests.cpp

6
src/Makefile.am

@ -72,7 +72,6 @@ endif
BITCOIN_CORE_H = \ BITCOIN_CORE_H = \
addrman.h \ addrman.h \
alert.h \ alert.h \
allocators.h \
amount.h \ amount.h \
arith_uint256.h \ arith_uint256.h \
base58.h \ base58.h \
@ -123,7 +122,10 @@ BITCOIN_CORE_H = \
script/standard.h \ script/standard.h \
serialize.h \ serialize.h \
streams.h \ streams.h \
support/allocators/secure.h \
support/allocators/zeroafterfree.h \
support/cleanse.h \ support/cleanse.h \
support/pagelocker.h \
sync.h \ sync.h \
threadsafety.h \ threadsafety.h \
timedata.h \ timedata.h \
@ -233,7 +235,6 @@ univalue_libbitcoin_univalue_a_SOURCES = \
# common: shared between bitcoind, and bitcoin-qt and non-server tools # common: shared between bitcoind, and bitcoin-qt and non-server tools
libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES)
libbitcoin_common_a_SOURCES = \ libbitcoin_common_a_SOURCES = \
allocators.cpp \
arith_uint256.cpp \ arith_uint256.cpp \
amount.cpp \ amount.cpp \
base58.cpp \ base58.cpp \
@ -264,6 +265,7 @@ libbitcoin_common_a_SOURCES = \
# backward-compatibility objects and their sanity checks are linked. # backward-compatibility objects and their sanity checks are linked.
libbitcoin_util_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_util_a_CPPFLAGS = $(BITCOIN_INCLUDES)
libbitcoin_util_a_SOURCES = \ libbitcoin_util_a_SOURCES = \
support/pagelocker.cpp \
chainparamsbase.cpp \ chainparamsbase.cpp \
clientversion.cpp \ clientversion.cpp \
compat/glibc_sanity.cpp \ compat/glibc_sanity.cpp \

1
src/base58.h

@ -19,6 +19,7 @@
#include "pubkey.h" #include "pubkey.h"
#include "script/script.h" #include "script/script.h"
#include "script/standard.h" #include "script/standard.h"
#include "support/allocators/zeroafterfree.h"
#include <string> #include <string>
#include <vector> #include <vector>

2
src/crypter.h

@ -5,9 +5,9 @@
#ifndef BITCOIN_CRYPTER_H #ifndef BITCOIN_CRYPTER_H
#define BITCOIN_CRYPTER_H #define BITCOIN_CRYPTER_H
#include "allocators.h"
#include "keystore.h" #include "keystore.h"
#include "serialize.h" #include "serialize.h"
#include "support/allocators/secure.h"
class uint256; class uint256;

2
src/key.h

@ -6,8 +6,8 @@
#ifndef BITCOIN_KEY_H #ifndef BITCOIN_KEY_H
#define BITCOIN_KEY_H #define BITCOIN_KEY_H
#include "allocators.h"
#include "serialize.h" #include "serialize.h"
#include "support/allocators/secure.h"
#include "uint256.h" #include "uint256.h"
#include <stdexcept> #include <stdexcept>

2
src/qt/askpassphrasedialog.cpp

@ -8,7 +8,7 @@
#include "guiconstants.h" #include "guiconstants.h"
#include "walletmodel.h" #include "walletmodel.h"
#include "allocators.h" #include "support/allocators/secure.h"
#include <QKeyEvent> #include <QKeyEvent>
#include <QMessageBox> #include <QMessageBox>

2
src/qt/walletmodel.h

@ -8,7 +8,7 @@
#include "paymentrequestplus.h" #include "paymentrequestplus.h"
#include "walletmodeltransaction.h" #include "walletmodeltransaction.h"
#include "allocators.h" /* for SecureString */ #include "support/allocators/secure.h"
#include <map> #include <map>
#include <vector> #include <vector>

2
src/streams.h

@ -6,7 +6,7 @@
#ifndef BITCOIN_STREAMS_H #ifndef BITCOIN_STREAMS_H
#define BITCOIN_STREAMS_H #define BITCOIN_STREAMS_H
#include "allocators.h" #include "support/allocators/zeroafterfree.h"
#include "serialize.h" #include "serialize.h"
#include <algorithm> #include <algorithm>

62
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 <string>
//
// Allocator that locks its contents from being paged
// out of memory and clears its contents before deletion.
//
template <typename T>
struct secure_allocator : public std::allocator<T> {
// MSVC8 default copy constructor is broken
typedef std::allocator<T> 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 <typename U>
secure_allocator(const secure_allocator<U>& a) throw() : base(a)
{
}
~secure_allocator() throw() {}
template <typename _Other>
struct rebind {
typedef secure_allocator<_Other> other;
};
T* allocate(std::size_t n, const void* hint = 0)
{
T* p;
p = std::allocator<T>::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<T>::deallocate(p, n);
}
};
// This is exactly like std::string, but with a custom allocator.
typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString;
#endif // BITCOIN_ALLOCATORS_SECURE_H

48
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 <memory>
#include <vector>
template <typename T>
struct zero_after_free_allocator : public std::allocator<T> {
// MSVC8 default copy constructor is broken
typedef std::allocator<T> 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 <typename U>
zero_after_free_allocator(const zero_after_free_allocator<U>& a) throw() : base(a)
{
}
~zero_after_free_allocator() throw() {}
template <typename _Other>
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<T>::deallocate(p, n);
}
};
// Byte-vector that clears its contents before deletion.
typedef std::vector<char, zero_after_free_allocator<char> > CSerializeData;
#endif // BITCOIN_ALLOCATORS_ZEROAFTERFREE_H

6
src/allocators.cpp → src/support/pagelocker.cpp

@ -2,7 +2,11 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // 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
#ifdef _WIN32_WINNT #ifdef _WIN32_WINNT

96
src/allocators.h → src/support/pagelocker.h

@ -3,15 +3,12 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_ALLOCATORS_H #ifndef BITCOIN_ALLOCATORS_PAGELOCKER_H
#define BITCOIN_ALLOCATORS_H #define BITCOIN_ALLOCATORS_PAGELOCKER_H
#include "support/cleanse.h" #include "support/cleanse.h"
#include <map> #include <map>
#include <string>
#include <string.h>
#include <vector>
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <boost/thread/once.hpp> #include <boost/thread/once.hpp>
@ -178,91 +175,4 @@ void UnlockObject(const T& t)
LockedPageManager::Instance().UnlockRange((void*)(&t), sizeof(T)); LockedPageManager::Instance().UnlockRange((void*)(&t), sizeof(T));
} }
// #endif // BITCOIN_ALLOCATORS_PAGELOCKER_H
// Allocator that locks its contents from being paged
// out of memory and clears its contents before deletion.
//
template <typename T>
struct secure_allocator : public std::allocator<T> {
// MSVC8 default copy constructor is broken
typedef std::allocator<T> 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 <typename U>
secure_allocator(const secure_allocator<U>& a) throw() : base(a)
{
}
~secure_allocator() throw() {}
template <typename _Other>
struct rebind {
typedef secure_allocator<_Other> other;
};
T* allocate(std::size_t n, const void* hint = 0)
{
T* p;
p = std::allocator<T>::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<T>::deallocate(p, n);
}
};
//
// Allocator that clears its contents before deletion.
//
template <typename T>
struct zero_after_free_allocator : public std::allocator<T> {
// MSVC8 default copy constructor is broken
typedef std::allocator<T> 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 <typename U>
zero_after_free_allocator(const zero_after_free_allocator<U>& a) throw() : base(a)
{
}
~zero_after_free_allocator() throw() {}
template <typename _Other>
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<T>::deallocate(p, n);
}
};
// This is exactly like std::string, but with a custom allocator.
typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString;
// Byte-vector that clears its contents before deletion.
typedef std::vector<char, zero_after_free_allocator<char> > CSerializeData;
#endif // BITCOIN_ALLOCATORS_H

2
src/test/allocator_tests.cpp

@ -4,7 +4,7 @@
#include "util.h" #include "util.h"
#include "allocators.h" #include "support/allocators/secure.h"
#include "test/test_bitcoin.h" #include "test/test_bitcoin.h"
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>

Loading…
Cancel
Save