Merge pull request #3046 from sarchar/lockedpage-change
Changing LockedPageManager to use a managed instance
This commit is contained in:
commit
34f72ad6ef
@ -24,6 +24,9 @@
|
|||||||
#include <unistd.h> // for sysconf
|
#include <unistd.h> // for sysconf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
LockedPageManager* LockedPageManager::_instance = NULL;
|
||||||
|
boost::once_flag LockedPageManager::init_flag = BOOST_ONCE_INIT;
|
||||||
|
|
||||||
/** Determine system page size in bytes */
|
/** Determine system page size in bytes */
|
||||||
static inline size_t GetSystemPageSize()
|
static inline size_t GetSystemPageSize()
|
||||||
{
|
{
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
|
#include <boost/thread/once.hpp>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <openssl/crypto.h> // for OPENSSL_cleanse()
|
#include <openssl/crypto.h> // for OPENSSL_cleanse()
|
||||||
|
|
||||||
@ -34,6 +35,12 @@ public:
|
|||||||
page_mask = ~(page_size - 1);
|
page_mask = ~(page_size - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~LockedPageManagerBase()
|
||||||
|
{
|
||||||
|
assert(this->GetLockedPageCount() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// For all pages in affected range, increase lock count
|
// For all pages in affected range, increase lock count
|
||||||
void LockRange(void *p, size_t size)
|
void LockRange(void *p, size_t size)
|
||||||
{
|
{
|
||||||
@ -117,13 +124,39 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Singleton class to keep track of locked (ie, non-swappable) memory pages, for use in
|
* Singleton class to keep track of locked (ie, non-swappable) memory pages, for use in
|
||||||
* std::allocator templates.
|
* std::allocator templates.
|
||||||
|
*
|
||||||
|
* Some implementations of the STL allocate memory in some constructors (i.e., see
|
||||||
|
* MSVC's vector<T> implementation where it allocates 1 byte of memory in the allocator.)
|
||||||
|
* Due to the unpredictable order of static initializers, we have to make sure the
|
||||||
|
* LockedPageManager instance exists before any other STL-based objects that use
|
||||||
|
* secure_allocator are created. So instead of having LockedPageManager also be
|
||||||
|
* static-intialized, it is created on demand.
|
||||||
*/
|
*/
|
||||||
class LockedPageManager: public LockedPageManagerBase<MemoryPageLocker>
|
class LockedPageManager: public LockedPageManagerBase<MemoryPageLocker>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static LockedPageManager instance; // instantiated in util.cpp
|
static LockedPageManager& Instance()
|
||||||
|
{
|
||||||
|
boost::call_once(LockedPageManager::CreateInstance, LockedPageManager::init_flag);
|
||||||
|
return *LockedPageManager::_instance;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LockedPageManager();
|
LockedPageManager();
|
||||||
|
|
||||||
|
static void CreateInstance()
|
||||||
|
{
|
||||||
|
// Using a local static instance guarantees that the object is initialized
|
||||||
|
// when it's first needed and also deinitialized after all objects that use
|
||||||
|
// it are done with it. I can think of one unlikely scenario where we may
|
||||||
|
// have a static deinitialization order/problem, but the check in
|
||||||
|
// LockedPageManagerBase's destructor helps us detect if that ever happens.
|
||||||
|
static LockedPageManager instance;
|
||||||
|
LockedPageManager::_instance = &instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LockedPageManager* _instance;
|
||||||
|
static boost::once_flag init_flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -131,12 +164,12 @@ private:
|
|||||||
// Intended for non-dynamically allocated structures.
|
// Intended for non-dynamically allocated structures.
|
||||||
//
|
//
|
||||||
template<typename T> void LockObject(const T &t) {
|
template<typename T> void LockObject(const T &t) {
|
||||||
LockedPageManager::instance.LockRange((void*)(&t), sizeof(T));
|
LockedPageManager::Instance().LockRange((void*)(&t), sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void UnlockObject(const T &t) {
|
template<typename T> void UnlockObject(const T &t) {
|
||||||
OPENSSL_cleanse((void*)(&t), sizeof(T));
|
OPENSSL_cleanse((void*)(&t), sizeof(T));
|
||||||
LockedPageManager::instance.UnlockRange((void*)(&t), sizeof(T));
|
LockedPageManager::Instance().UnlockRange((void*)(&t), sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -168,7 +201,7 @@ struct secure_allocator : public std::allocator<T>
|
|||||||
T *p;
|
T *p;
|
||||||
p = std::allocator<T>::allocate(n, hint);
|
p = std::allocator<T>::allocate(n, hint);
|
||||||
if (p != NULL)
|
if (p != NULL)
|
||||||
LockedPageManager::instance.LockRange(p, sizeof(T) * n);
|
LockedPageManager::Instance().LockRange(p, sizeof(T) * n);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +210,7 @@ struct secure_allocator : public std::allocator<T>
|
|||||||
if (p != NULL)
|
if (p != NULL)
|
||||||
{
|
{
|
||||||
OPENSSL_cleanse(p, sizeof(T) * n);
|
OPENSSL_cleanse(p, sizeof(T) * n);
|
||||||
LockedPageManager::instance.UnlockRange(p, sizeof(T) * n);
|
LockedPageManager::Instance().UnlockRange(p, sizeof(T) * n);
|
||||||
}
|
}
|
||||||
std::allocator<T>::deallocate(p, n);
|
std::allocator<T>::deallocate(p, n);
|
||||||
}
|
}
|
||||||
|
@ -88,16 +88,16 @@ public:
|
|||||||
// Try to keep the key data out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap)
|
// Try to keep the key data out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap)
|
||||||
// Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
|
// Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
|
||||||
// Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
|
// Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
|
||||||
LockedPageManager::instance.LockRange(&chKey[0], sizeof chKey);
|
LockedPageManager::Instance().LockRange(&chKey[0], sizeof chKey);
|
||||||
LockedPageManager::instance.LockRange(&chIV[0], sizeof chIV);
|
LockedPageManager::Instance().LockRange(&chIV[0], sizeof chIV);
|
||||||
}
|
}
|
||||||
|
|
||||||
~CCrypter()
|
~CCrypter()
|
||||||
{
|
{
|
||||||
CleanKey();
|
CleanKey();
|
||||||
|
|
||||||
LockedPageManager::instance.UnlockRange(&chKey[0], sizeof chKey);
|
LockedPageManager::Instance().UnlockRange(&chKey[0], sizeof chKey);
|
||||||
LockedPageManager::instance.UnlockRange(&chIV[0], sizeof chIV);
|
LockedPageManager::Instance().UnlockRange(&chIV[0], sizeof chIV);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -95,8 +95,6 @@ void locking_callback(int mode, int i, const char* file, int line)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LockedPageManager LockedPageManager::instance;
|
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
class CInit
|
class CInit
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user